mirror of
https://github.com/FlipsideCrypto/dcrd.git
synced 2026-02-06 10:56:47 +00:00
dcrjson: Introduce v3 and move types to module.
This commit introduces a new major version of the dcrjson module which
removes all dcrd RPC type support, instead focusing only on method and
type registration. The dcrd methods and types are moved to the
github.com/decred/dcrd/rpc/jsonrpc/types module.
In order to improve backwards compatibility with dcrjson/v2, the API
has been modified to register methods as interface{} instead of
string. This allows different method string types to be used to key
parameter types during registration and lookup, and will allow
dcrjson/v2 to forward registrations of RPC methods to v3 without
causing duplicate registrations errors for incompatible types.
With the introduction of the new types package, the RPC API has been
modified to replace concatenated hash blobs to JSON string arrays of
hash strings. The RPC API major version is bumped to reflect this
change.
A future update to dcrjson/v2 will add additional registrations,
forwarding the registrations to v3 and replacing command types with
type aliases where possible. Unfortunately, this can not be done
entirely in a single commit due to dcrjson/v2 and dcrjson/v3 sharing
the same directory in the source tree, and a branch will need to be
used for this update.
Module replacements are temporarily used to enable the changes for the
main module, including dcrctl. After the aforementioned update to
dcrjson/v2 and a forthcoming update to dcrwallet's RPC types package,
these replacements will be removed.
This commit is contained in:
parent
4f91b01616
commit
b112df6417
@ -16,12 +16,12 @@ import (
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/decred/dcrd/dcrjson/v2"
|
||||
"github.com/decred/dcrd/dcrjson/v3"
|
||||
"github.com/decred/dcrd/dcrutil"
|
||||
"github.com/decred/dcrd/internal/version"
|
||||
|
||||
// Register wallet dcrjson types so they're available.
|
||||
_ "github.com/decred/dcrwallet/rpc/jsonrpc/types"
|
||||
dcrdtypes "github.com/decred/dcrd/rpc/jsonrpc/types"
|
||||
wallettypes "github.com/decred/dcrwallet/rpc/jsonrpc/types"
|
||||
|
||||
flags "github.com/jessevdk/go-flags"
|
||||
)
|
||||
@ -47,50 +47,56 @@ var (
|
||||
// listCommands categorizes and lists all of the usable commands along with
|
||||
// their one-line usage.
|
||||
func listCommands() {
|
||||
const (
|
||||
categoryChain uint8 = iota
|
||||
categoryWallet
|
||||
numCategories
|
||||
)
|
||||
var categories = []struct {
|
||||
Header string
|
||||
Method interface{}
|
||||
Usages []string
|
||||
}{{
|
||||
Header: "Chain Server Commands:",
|
||||
Method: dcrdtypes.Method(""),
|
||||
}, {
|
||||
Header: "Wallet Server Commands (--wallet):",
|
||||
Method: wallettypes.Method(""),
|
||||
}}
|
||||
|
||||
// Get a list of registered commands and categorize and filter them.
|
||||
cmdMethods := dcrjson.RegisteredCmdMethods()
|
||||
categorized := make([][]string, numCategories)
|
||||
for _, method := range cmdMethods {
|
||||
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
|
||||
}
|
||||
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)
|
||||
}
|
||||
|
||||
// Skip the commands that aren't usable from this utility.
|
||||
if flags&unusableFlags != 0 {
|
||||
continue
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
// Skip the commands that aren't usable from this utility.
|
||||
if flags&unusableFlags != 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
// Categorize the command based on the usage flags.
|
||||
category := categoryChain
|
||||
if flags&dcrjson.UFWalletOnly != 0 {
|
||||
category = categoryWallet
|
||||
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)
|
||||
}
|
||||
categorized[category] = append(categorized[category], usage)
|
||||
}
|
||||
|
||||
// Display the command according to their categories.
|
||||
categoryTitles := make([]string, numCategories)
|
||||
categoryTitles[categoryChain] = "Chain Server Commands:"
|
||||
categoryTitles[categoryWallet] = "Wallet Server Commands (--wallet):"
|
||||
for category := uint8(0); category < numCategories; category++ {
|
||||
fmt.Println(categoryTitles[category])
|
||||
for _, usage := range categorized[category] {
|
||||
for i := range categories {
|
||||
fmt.Println(categories[i].Header)
|
||||
for _, usage := range categories[i].Usages {
|
||||
fmt.Println(usage)
|
||||
}
|
||||
fmt.Println()
|
||||
|
||||
@ -15,7 +15,9 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/decred/dcrd/dcrjson/v2"
|
||||
"github.com/decred/dcrd/dcrjson/v3"
|
||||
dcrdtypes "github.com/decred/dcrd/rpc/jsonrpc/types"
|
||||
wallettypes "github.com/decred/dcrwallet/rpc/jsonrpc/types"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -24,7 +26,7 @@ const (
|
||||
)
|
||||
|
||||
// commandUsage display the usage for a specific command.
|
||||
func commandUsage(method string) {
|
||||
func commandUsage(method interface{}) {
|
||||
usage, err := dcrjson.MethodUsageText(method)
|
||||
if err != nil {
|
||||
// This should never happen since the method was already checked
|
||||
@ -64,10 +66,15 @@ func main() {
|
||||
|
||||
// Ensure the specified method identifies a valid registered command and
|
||||
// is one of the usable types.
|
||||
method := args[0]
|
||||
methodStr := args[0]
|
||||
var method interface{} = dcrdtypes.Method(methodStr)
|
||||
usageFlags, err := dcrjson.MethodUsageFlags(method)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Unrecognized command '%s'\n", method)
|
||||
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)
|
||||
}
|
||||
|
||||
18
config.go
18
config.go
@ -25,10 +25,10 @@ import (
|
||||
"github.com/decred/dcrd/connmgr"
|
||||
"github.com/decred/dcrd/database"
|
||||
_ "github.com/decred/dcrd/database/ffldb"
|
||||
"github.com/decred/dcrd/dcrjson/v2"
|
||||
"github.com/decred/dcrd/dcrutil"
|
||||
"github.com/decred/dcrd/internal/version"
|
||||
"github.com/decred/dcrd/mempool/v2"
|
||||
"github.com/decred/dcrd/rpc/jsonrpc/types"
|
||||
"github.com/decred/dcrd/sampleconfig"
|
||||
"github.com/decred/slog"
|
||||
flags "github.com/jessevdk/go-flags"
|
||||
@ -177,9 +177,9 @@ type config struct {
|
||||
miningAddrs []dcrutil.Address
|
||||
minRelayTxFee dcrutil.Amount
|
||||
whitelists []*net.IPNet
|
||||
ipv4NetInfo dcrjson.NetworksResult
|
||||
ipv6NetInfo dcrjson.NetworksResult
|
||||
onionNetInfo dcrjson.NetworksResult
|
||||
ipv4NetInfo types.NetworksResult
|
||||
ipv6NetInfo types.NetworksResult
|
||||
onionNetInfo types.NetworksResult
|
||||
}
|
||||
|
||||
// serviceOptions defines the configuration options for the daemon as a service on
|
||||
@ -423,8 +423,8 @@ func createDefaultConfigFile(destPath string) error {
|
||||
|
||||
// generateNetworkInfo is a convenience function that creates a slice from the
|
||||
// available networks.
|
||||
func (cfg *config) generateNetworkInfo() []dcrjson.NetworksResult {
|
||||
return []dcrjson.NetworksResult{cfg.ipv4NetInfo, cfg.ipv6NetInfo,
|
||||
func (cfg *config) generateNetworkInfo() []types.NetworksResult {
|
||||
return []types.NetworksResult{cfg.ipv4NetInfo, cfg.ipv6NetInfo,
|
||||
cfg.onionNetInfo}
|
||||
}
|
||||
|
||||
@ -512,9 +512,9 @@ func loadConfig() (*config, []string, error) {
|
||||
NoExistsAddrIndex: defaultNoExistsAddrIndex,
|
||||
NoCFilters: defaultNoCFilters,
|
||||
AltDNSNames: defaultAltDNSNames,
|
||||
ipv4NetInfo: dcrjson.NetworksResult{Name: "IPV4"},
|
||||
ipv6NetInfo: dcrjson.NetworksResult{Name: "IPV6"},
|
||||
onionNetInfo: dcrjson.NetworksResult{Name: "Onion"},
|
||||
ipv4NetInfo: types.NetworksResult{Name: "IPV4"},
|
||||
ipv6NetInfo: types.NetworksResult{Name: "IPV6"},
|
||||
onionNetInfo: types.NetworksResult{Name: "Onion"},
|
||||
}
|
||||
|
||||
// Service options which are only added on Windows.
|
||||
|
||||
@ -21,17 +21,17 @@ func CmdMethod(cmd interface{}) (string, error) {
|
||||
method, ok := concreteTypeToMethod[rt]
|
||||
registerLock.RUnlock()
|
||||
if !ok {
|
||||
str := fmt.Sprintf("%q is not registered", method)
|
||||
str := fmt.Sprintf("%T is not registered", cmd)
|
||||
return "", makeError(ErrUnregisteredMethod, str)
|
||||
}
|
||||
|
||||
return method, nil
|
||||
return reflect.ValueOf(method).String(), nil
|
||||
}
|
||||
|
||||
// MethodUsageFlags returns the usage flags for the passed command method. The
|
||||
// provided method must be associated with a registered type. All commands
|
||||
// provided by this package are registered by default.
|
||||
func MethodUsageFlags(method string) (UsageFlag, error) {
|
||||
func MethodUsageFlags(method interface{}) (UsageFlag, error) {
|
||||
// Look up details about the provided method and error out if not
|
||||
// registered.
|
||||
registerLock.RLock()
|
||||
@ -178,7 +178,7 @@ func fieldUsage(structField reflect.StructField, defaultVal *reflect.Value) stri
|
||||
// methodUsageText returns a one-line usage string for the provided command and
|
||||
// method info. This is the main work horse for the exported MethodUsageText
|
||||
// function.
|
||||
func methodUsageText(rtp reflect.Type, defaults map[int]reflect.Value, method string) string {
|
||||
func methodUsageText(rtp reflect.Type, defaults map[int]reflect.Value, method interface{}) string {
|
||||
// Generate the individual usage for each field in the command. Several
|
||||
// simplifying assumptions are made here because the RegisterCmd
|
||||
// function has already rigorously enforced the layout.
|
||||
@ -209,7 +209,7 @@ func methodUsageText(rtp reflect.Type, defaults map[int]reflect.Value, method st
|
||||
}
|
||||
|
||||
// Generate and return the one-line usage string.
|
||||
usageStr := method
|
||||
usageStr := reflect.ValueOf(method).String()
|
||||
if len(reqFieldUsages) > 0 {
|
||||
usageStr += " " + strings.Join(reqFieldUsages, " ")
|
||||
}
|
||||
@ -222,7 +222,7 @@ func methodUsageText(rtp reflect.Type, defaults map[int]reflect.Value, method st
|
||||
// MethodUsageText returns a one-line usage string for the provided method. The
|
||||
// provided method must be associated with a registered type. All commands
|
||||
// provided by this package are registered by default.
|
||||
func MethodUsageText(method string) (string, error) {
|
||||
func MethodUsageText(method interface{}) (string, error) {
|
||||
// Look up details about the provided method and error out if not
|
||||
// registered.
|
||||
registerLock.RLock()
|
||||
|
||||
@ -28,12 +28,12 @@ func TestCmdMethod(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "nil pointer of registered type",
|
||||
cmd: (*GetBlockCmd)(nil),
|
||||
cmd: (*testGetBlockCmd)(nil),
|
||||
method: "getblock",
|
||||
},
|
||||
{
|
||||
name: "nil instance of registered type",
|
||||
cmd: &GetBlockCountCmd{},
|
||||
name: "zero instance of registered type",
|
||||
cmd: &testGetBlockCountCmd{},
|
||||
method: "getblockcount",
|
||||
},
|
||||
}
|
||||
|
||||
@ -43,7 +43,7 @@ func MarshalCmd(rpcVersion string, id interface{}, cmd interface{}) ([]byte, err
|
||||
method, ok := concreteTypeToMethod[rt]
|
||||
registerLock.RUnlock()
|
||||
if !ok {
|
||||
str := fmt.Sprintf("%q is not registered", method)
|
||||
str := fmt.Sprintf("%T is not registered", cmd)
|
||||
return nil, makeError(ErrUnregisteredMethod, str)
|
||||
}
|
||||
|
||||
@ -60,7 +60,7 @@ func MarshalCmd(rpcVersion string, id interface{}, cmd interface{}) ([]byte, err
|
||||
params := makeParams(rt.Elem(), rv.Elem())
|
||||
|
||||
// Generate and marshal the final JSON-RPC request.
|
||||
rawCmd, err := NewRequest(rpcVersion, id, method, params)
|
||||
rawCmd, err := NewRequest(rpcVersion, id, reflect.ValueOf(method).String(), params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -105,16 +105,15 @@ func populateDefaults(numParams int, info *methodInfo, rv reflect.Value) {
|
||||
}
|
||||
}
|
||||
|
||||
// UnmarshalCmd unmarshals a JSON-RPC request into a suitable concrete command
|
||||
// so long as the method type contained within the marshalled request is
|
||||
// registered.
|
||||
func UnmarshalCmd(r *Request) (interface{}, error) {
|
||||
// ParseParams unmarshals and parses the parameters for a JSON-RPC request based
|
||||
// on the registered method.
|
||||
func ParseParams(method interface{}, params []json.RawMessage) (interface{}, error) {
|
||||
registerLock.RLock()
|
||||
rtp, ok := methodToConcreteType[r.Method]
|
||||
info := methodToInfo[r.Method]
|
||||
rtp, ok := methodToConcreteType[method]
|
||||
info := methodToInfo[method]
|
||||
registerLock.RUnlock()
|
||||
if !ok {
|
||||
str := fmt.Sprintf("%q is not registered", r.Method)
|
||||
str := fmt.Sprintf("%q is not registered", method)
|
||||
return nil, makeError(ErrUnregisteredMethod, str)
|
||||
}
|
||||
rt := rtp.Elem()
|
||||
@ -122,7 +121,7 @@ func UnmarshalCmd(r *Request) (interface{}, error) {
|
||||
rv := rvp.Elem()
|
||||
|
||||
// Ensure the number of parameters are correct.
|
||||
numParams := len(r.Params)
|
||||
numParams := len(params)
|
||||
if err := checkNumParams(numParams, &info); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -133,7 +132,7 @@ func UnmarshalCmd(r *Request) (interface{}, error) {
|
||||
rvf := rv.Field(i)
|
||||
// Unmarshal the parameter into the struct field.
|
||||
concreteVal := rvf.Addr().Interface()
|
||||
if err := json.Unmarshal(r.Params[i], &concreteVal); err != nil {
|
||||
if err := json.Unmarshal(params[i], &concreteVal); err != nil {
|
||||
// The most common error is the wrong type, so
|
||||
// explicitly detect that error and make it nicer.
|
||||
fieldName := strings.ToLower(rt.Field(i).Name)
|
||||
@ -509,7 +508,7 @@ func assignField(paramNum int, fieldName string, dest reflect.Value, src reflect
|
||||
// - Conversion from string to arrays, slices, structs, and maps by treating
|
||||
// the string as marshalled JSON and calling json.Unmarshal into the
|
||||
// destination field
|
||||
func NewCmd(method string, args ...interface{}) (interface{}, error) {
|
||||
func NewCmd(method interface{}, args ...interface{}) (interface{}, error) {
|
||||
// Look up details about the provided method. Any methods that aren't
|
||||
// registered are an error.
|
||||
registerLock.RLock()
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// Copyright (c) 2014 The btcsuite developers
|
||||
// Copyright (c) 2015-2016 The Decred 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.
|
||||
|
||||
@ -419,13 +419,13 @@ func TestMarshalCmdErrors(t *testing.T) {
|
||||
{
|
||||
name: "nil instance of registered type",
|
||||
id: 1,
|
||||
cmd: (*GetBlockCmd)(nil),
|
||||
cmd: (*testGetBlockCmd)(nil),
|
||||
err: Error{Code: ErrInvalidType},
|
||||
},
|
||||
{
|
||||
name: "nil instance of registered type",
|
||||
name: "zero instance of registered type",
|
||||
id: []int{0, 1},
|
||||
cmd: &GetBlockCountCmd{},
|
||||
cmd: &testGetBlockCountCmd{},
|
||||
err: Error{Code: ErrInvalidType},
|
||||
},
|
||||
}
|
||||
@ -448,60 +448,46 @@ func TestMarshalCmdErrors(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestUnmarshalCmdErrors tests the error paths of the UnmarshalCmd function.
|
||||
func TestUnmarshalCmdErrors(t *testing.T) {
|
||||
// TestParseParamsErrors tests the error paths of the ParseParams function.
|
||||
func TestParseParamsErrors(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
method string
|
||||
params []json.RawMessage
|
||||
request Request
|
||||
err Error
|
||||
}{
|
||||
{
|
||||
name: "unregistered type",
|
||||
request: Request{
|
||||
Jsonrpc: "1.0",
|
||||
Method: "bogusmethod",
|
||||
Params: nil,
|
||||
ID: nil,
|
||||
},
|
||||
err: Error{Code: ErrUnregisteredMethod},
|
||||
name: "unregistered type",
|
||||
method: "bogusmethod",
|
||||
params: nil,
|
||||
err: Error{Code: ErrUnregisteredMethod},
|
||||
},
|
||||
{
|
||||
name: "incorrect number of params",
|
||||
request: Request{
|
||||
Jsonrpc: "1.0",
|
||||
Method: "getblockcount",
|
||||
Params: []json.RawMessage{[]byte(`"bogusparam"`)},
|
||||
ID: nil,
|
||||
},
|
||||
err: Error{Code: ErrNumParams},
|
||||
name: "incorrect number of params",
|
||||
method: "getblockcount",
|
||||
params: []json.RawMessage{[]byte(`"bogusparam"`)},
|
||||
err: Error{Code: ErrNumParams},
|
||||
},
|
||||
{
|
||||
name: "invalid type for a parameter",
|
||||
request: Request{
|
||||
Jsonrpc: "1.0",
|
||||
Method: "getblock",
|
||||
Params: []json.RawMessage{[]byte("1")},
|
||||
ID: nil,
|
||||
},
|
||||
err: Error{Code: ErrInvalidType},
|
||||
name: "invalid type for a parameter",
|
||||
method: "getblock",
|
||||
params: []json.RawMessage{[]byte("1")},
|
||||
err: Error{Code: ErrInvalidType},
|
||||
},
|
||||
{
|
||||
name: "invalid JSON for a parameter",
|
||||
request: Request{
|
||||
Jsonrpc: "1.0",
|
||||
Method: "getblock",
|
||||
Params: []json.RawMessage{[]byte(`"1`)},
|
||||
ID: nil,
|
||||
},
|
||||
err: Error{Code: ErrInvalidType},
|
||||
name: "invalid JSON for a parameter",
|
||||
method: "getblock",
|
||||
params: []json.RawMessage{[]byte(`"1`)},
|
||||
err: Error{Code: ErrInvalidType},
|
||||
},
|
||||
}
|
||||
|
||||
t.Logf("Running %d tests", len(tests))
|
||||
for i, test := range tests {
|
||||
_, err := UnmarshalCmd(&test.request)
|
||||
_, err := ParseParams(test.method, test.params)
|
||||
if reflect.TypeOf(err) != reflect.TypeOf(test.err) {
|
||||
t.Errorf("Test #%d (%s) wrong error type - got `%T` (%v), want `%T`",
|
||||
i, test.name, err, err, test.err)
|
||||
|
||||
@ -1,19 +1,16 @@
|
||||
// Copyright (c) 2015 The btcsuite developers
|
||||
// Copyright (c) 2015-2016 The Decred 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 dcrjson provides primitives for working with the Decred JSON-RPC API.
|
||||
Package dcrjson provides infrastructure for working with the Decred JSON-RPC APIs.
|
||||
|
||||
Overview
|
||||
|
||||
When communicating via the JSON-RPC protocol, all of the commands need to be
|
||||
When communicating via the JSON-RPC protocol, all requests and responses must be
|
||||
marshalled to and from the the wire in the appropriate format. This package
|
||||
provides data structures and primitives to ease this process.
|
||||
|
||||
In addition, it also provides some additional features such as custom command
|
||||
registration, command categorization, and reflection-based help generation.
|
||||
provides infrastructure and primitives to ease this process.
|
||||
|
||||
JSON-RPC Protocol Overview
|
||||
|
||||
@ -37,7 +34,7 @@ method (a.k.a. command) being sent. Each parameter can be as simple as an int
|
||||
or a complex structure containing many nested fields. The id field is used to
|
||||
identify a request and will be included in the associated response.
|
||||
|
||||
When working with asynchronous transports, such as websockets, spontaneous
|
||||
When working with streamed RPC transports, such as websockets, spontaneous
|
||||
notifications are also possible. As indicated, they are the same as a request
|
||||
object, except they have the id field set to null. Therefore, servers will
|
||||
ignore requests with the id field set to null, while clients can choose to
|
||||
@ -50,24 +47,16 @@ for the most part, the error field will be set as described on failure.
|
||||
|
||||
Marshalling and Unmarshalling
|
||||
|
||||
Based upon the discussion above, it should be easy to see how the types of this
|
||||
package map into the required parts of the protocol
|
||||
|
||||
- Request Objects (type Request)
|
||||
- Commands (type <Foo>Cmd)
|
||||
- Notifications (type <Foo>Ntfn)
|
||||
- Response Objects (type Response)
|
||||
- Result (type <Foo>Result)
|
||||
|
||||
To simplify the marshalling of the requests and responses, the MarshalCmd and
|
||||
MarshalResponse functions are provided. They return the raw bytes ready to be
|
||||
sent across the wire.
|
||||
|
||||
Unmarshalling a received Request object is a two step process:
|
||||
1) Unmarshal the raw bytes into a Request struct instance via json.Unmarshal
|
||||
2) Use UnmarshalCmd on the Result field of the unmarshalled Request to create
|
||||
a concrete command or notification instance with all struct fields set
|
||||
accordingly
|
||||
2) Use ParseParams on the Method and Params fields of the unmarshalled Request
|
||||
to create a concrete command or notification instance with all struct fields
|
||||
set accordingly. The concrete types must have been registered for the method
|
||||
by an external package
|
||||
|
||||
This approach is used since it provides the caller with access to the additional
|
||||
fields in the request that are not part of the command such as the ID.
|
||||
@ -82,18 +71,16 @@ fields in the response such as the ID and Error.
|
||||
|
||||
Command Creation
|
||||
|
||||
This package provides two approaches for creating a new command. This first,
|
||||
and preferred, method is to use one of the New<Foo>Cmd functions. This allows
|
||||
static compile-time checking to help ensure the parameters stay in sync with
|
||||
the struct definitions.
|
||||
|
||||
The second approach is the NewCmd function which takes a method (command) name
|
||||
This package provides the NewCmd function which takes a method (command) name
|
||||
and variable arguments. The function includes full checking to ensure the
|
||||
parameters are accurate according to provided method, however these checks are,
|
||||
obviously, run-time which means any mistakes won't be found until the code is
|
||||
actually executed. However, it is quite useful for user-supplied commands
|
||||
that are intentionally dynamic.
|
||||
|
||||
External packages can and should implement types implementing Command for use
|
||||
with MarshalCmd/ParseParams.
|
||||
|
||||
Custom Command Registration
|
||||
|
||||
The command handling of this package is built around the concept of registered
|
||||
@ -117,8 +104,7 @@ Help Generation
|
||||
|
||||
To facilitate providing consistent help to users of the RPC server, this package
|
||||
exposes the GenerateHelp and function which uses reflection on registered
|
||||
commands or notifications, as well as the provided expected result types, to
|
||||
generate the final help text.
|
||||
commands or notifications to generate the final help text.
|
||||
|
||||
In addition, the MethodUsageText function is provided to generate consistent
|
||||
one-line usage for registered commands and notifications using reflection.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// Copyright (c) 2014 The btcsuite developers
|
||||
// Copyright (c) 2015-2016 The Decred 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.
|
||||
|
||||
@ -19,8 +19,10 @@ func ExampleMarshalCmd() {
|
||||
// optional fields. Also, notice the call to Bool which is a
|
||||
// convenience function for creating a pointer out of a primitive for
|
||||
// optional parameters.
|
||||
//
|
||||
// testGetBlockCmd was registered at init by the test.
|
||||
blockHash := "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"
|
||||
gbCmd := NewGetBlockCmd(blockHash, Bool(false), nil)
|
||||
gbCmd := &testGetBlockCmd{Hash: blockHash, Verbose: Bool(false), VerboseTx: nil}
|
||||
|
||||
// Marshal the command to the format suitable for sending to the RPC
|
||||
// server. Typically the client would increment the id here which is
|
||||
@ -41,8 +43,8 @@ func ExampleMarshalCmd() {
|
||||
}
|
||||
|
||||
// This example demonstrates how to unmarshal a JSON-RPC request and then
|
||||
// unmarshal the concrete request into a concrete command.
|
||||
func ExampleUnmarshalCmd() {
|
||||
// parse the parameters into a concrete type.
|
||||
func ExampleParseParams() {
|
||||
// Ordinarily this would be read from the wire, but for this example,
|
||||
// it is hard coded here for clarity.
|
||||
data := []byte(`{"jsonrpc":"1.0","method":"getblock","params":["000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f",false],"id":1}`)
|
||||
@ -67,17 +69,17 @@ func ExampleUnmarshalCmd() {
|
||||
return
|
||||
}
|
||||
|
||||
// Unmarshal the request into a concrete command.
|
||||
cmd, err := UnmarshalCmd(&request)
|
||||
// Unmarshal the request into concrete params.
|
||||
params, err := ParseParams(request.Method, request.Params)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
// Type assert the command to the appropriate type.
|
||||
gbCmd, ok := cmd.(*GetBlockCmd)
|
||||
// Type assert the params to the appropriate type.
|
||||
gbCmd, ok := params.(*testGetBlockCmd)
|
||||
if !ok {
|
||||
fmt.Printf("Incorrect command type: %T\n", cmd)
|
||||
fmt.Printf("Incorrect params type: %T\n", params)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
module github.com/decred/dcrd/dcrjson/v2
|
||||
module github.com/decred/dcrd/dcrjson/v3
|
||||
|
||||
go 1.11
|
||||
|
||||
|
||||
@ -503,7 +503,7 @@ func isValidResultType(kind reflect.Kind) bool {
|
||||
// "help--condition1": "command specified"
|
||||
// "help--result0": "List of commands"
|
||||
// "help--result1": "Help for specified command"
|
||||
func GenerateHelp(method string, descs map[string]string, resultTypes ...interface{}) (string, error) {
|
||||
func GenerateHelp(method interface{}, descs map[string]string, resultTypes ...interface{}) (string, error) {
|
||||
// Look up details about the provided method and error out if not
|
||||
// registered.
|
||||
registerLock.RLock()
|
||||
@ -511,7 +511,7 @@ func GenerateHelp(method string, descs map[string]string, resultTypes ...interfa
|
||||
info := methodToInfo[method]
|
||||
registerLock.RUnlock()
|
||||
if !ok {
|
||||
str := fmt.Sprintf("%q is not registered", method)
|
||||
str := fmt.Sprintf("%#v is not registered", method)
|
||||
return "", makeError(ErrUnregisteredMethod, str)
|
||||
}
|
||||
|
||||
@ -553,7 +553,8 @@ func GenerateHelp(method string, descs map[string]string, resultTypes ...interfa
|
||||
}
|
||||
|
||||
// Generate and return the help for the method.
|
||||
help := methodHelp(xT, rtp, info.defaults, method, resultTypes)
|
||||
methodStr := reflect.ValueOf(method).String()
|
||||
help := methodHelp(xT, rtp, info.defaults, methodStr, resultTypes)
|
||||
if missingKey != "" {
|
||||
return help, makeError(ErrMissingDescription, missingKey)
|
||||
}
|
||||
|
||||
@ -84,12 +84,3 @@ func String(v string) *string {
|
||||
*p = v
|
||||
return p
|
||||
}
|
||||
|
||||
// EstimateSmartFeeModeAddr is a helper routine that allocates a new
|
||||
// EstimateSmartFeeMode value to store v and returns a pointer to it. This is
|
||||
// useful when assigning optional parameters.
|
||||
func EstimateSmartFeeModeAddr(v EstimateSmartFeeMode) *EstimateSmartFeeMode {
|
||||
p := new(EstimateSmartFeeMode)
|
||||
*p = v
|
||||
return p
|
||||
}
|
||||
|
||||
@ -100,16 +100,6 @@ func TestHelpers(t *testing.T) {
|
||||
return &val
|
||||
}(),
|
||||
},
|
||||
{
|
||||
name: "estimatesmartfeemode",
|
||||
f: func() interface{} {
|
||||
return EstimateSmartFeeModeAddr("abc")
|
||||
},
|
||||
expected: func() interface{} {
|
||||
val := EstimateSmartFeeMode("abc")
|
||||
return &val
|
||||
}(),
|
||||
},
|
||||
}
|
||||
|
||||
t.Logf("Running %d tests", len(tests))
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// Copyright (c) 2014 The btcsuite developers
|
||||
// Copyright (c) 2015-2016 The Decred 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.
|
||||
|
||||
@ -20,9 +20,7 @@ import (
|
||||
type UsageFlag uint32
|
||||
|
||||
const (
|
||||
// UFWalletOnly indicates that the command can only be used with an RPC
|
||||
// server that supports wallet commands.
|
||||
UFWalletOnly UsageFlag = 1 << iota
|
||||
_ UsageFlag = 1 << iota // unused, was UFWalletOnly
|
||||
|
||||
// UFWebsocketOnly indicates that the command can only be used when
|
||||
// communicating with an RPC server over websockets. This typically
|
||||
@ -42,13 +40,15 @@ const (
|
||||
|
||||
// Map of UsageFlag values back to their constant names for pretty printing.
|
||||
var usageFlagStrings = map[UsageFlag]string{
|
||||
UFWalletOnly: "UFWalletOnly",
|
||||
UFWebsocketOnly: "UFWebsocketOnly",
|
||||
UFNotification: "UFNotification",
|
||||
}
|
||||
|
||||
// String returns the UsageFlag in human-readable form.
|
||||
func (fl UsageFlag) String() string {
|
||||
// Mask off the deprecated WalletOnly bit
|
||||
fl &^= 0x01
|
||||
|
||||
// No flags are set.
|
||||
if fl == 0 {
|
||||
return "0x0"
|
||||
@ -56,9 +56,9 @@ func (fl UsageFlag) String() string {
|
||||
|
||||
// Add individual bit flags.
|
||||
s := ""
|
||||
for flag := UFWalletOnly; flag < highestUsageFlagBit; flag <<= 1 {
|
||||
if fl&flag == flag {
|
||||
s += usageFlagStrings[flag] + "|"
|
||||
for flag := UsageFlag(1); flag < highestUsageFlagBit; flag <<= 1 {
|
||||
if name, ok := usageFlagStrings[fl&flag]; ok {
|
||||
s += name + "|"
|
||||
fl -= flag
|
||||
}
|
||||
}
|
||||
@ -86,9 +86,9 @@ type methodInfo struct {
|
||||
var (
|
||||
// These fields are used to map the registered types to method names.
|
||||
registerLock sync.RWMutex
|
||||
methodToConcreteType = make(map[string]reflect.Type)
|
||||
methodToInfo = make(map[string]methodInfo)
|
||||
concreteTypeToMethod = make(map[reflect.Type]string)
|
||||
methodToConcreteType = make(map[interface{}]reflect.Type)
|
||||
methodToInfo = make(map[interface{}]methodInfo)
|
||||
concreteTypeToMethod = make(map[reflect.Type]interface{})
|
||||
)
|
||||
|
||||
// baseKindString returns the base kind for a given reflect.Type after
|
||||
@ -125,10 +125,10 @@ func isAcceptableKind(kind reflect.Kind) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// RegisterCmd registers a new command that will automatically marshal to and
|
||||
// from JSON-RPC with full type checking and positional parameter support. It
|
||||
// also accepts usage flags which identify the circumstances under which the
|
||||
// command can be used.
|
||||
// Register registers a method that will automatically marshal to and from
|
||||
// JSON-RPC with full type checking and positional parameter support. It also
|
||||
// accepts usage flags which identify the circumstances under which the command
|
||||
// can be used.
|
||||
//
|
||||
// This package automatically registers all of the exported commands by default
|
||||
// using this function, however it is also exported so callers can easily
|
||||
@ -137,8 +137,9 @@ func isAcceptableKind(kind reflect.Kind) bool {
|
||||
// The type format is very strict since it needs to be able to automatically
|
||||
// marshal to and from JSON-RPC 1.0. The following enumerates the requirements:
|
||||
//
|
||||
// - The provided command must be a single pointer to a struct
|
||||
// - All fields must be exported
|
||||
// - The method must be a string or string type
|
||||
// - The provided params must be a pointer to a struct
|
||||
// - All parameter fields must be exported
|
||||
// - The order of the positional parameters in the marshalled JSON will be in
|
||||
// the same order as declared in the struct definition
|
||||
// - Struct embedding is not supported
|
||||
@ -151,16 +152,29 @@ func isAcceptableKind(kind reflect.Kind) bool {
|
||||
// - A field that has a 'jsonrpcdefault' struct tag must be an optional field
|
||||
// (pointer)
|
||||
//
|
||||
// Duplicate registrations with identical method and params types are allowed.
|
||||
// All other duplicate registrations of a method will error.
|
||||
//
|
||||
// NOTE: This function only needs to be able to examine the structure of the
|
||||
// passed struct, so it does not need to be an actual instance. Therefore, it
|
||||
// is recommended to simply pass a nil pointer cast to the appropriate type.
|
||||
// For example, (*FooCmd)(nil).
|
||||
func RegisterCmd(method string, cmd interface{}, flags UsageFlag) error {
|
||||
func Register(method interface{}, params interface{}, flags UsageFlag) error {
|
||||
registerLock.Lock()
|
||||
defer registerLock.Unlock()
|
||||
|
||||
if _, ok := methodToConcreteType[method]; ok {
|
||||
str := fmt.Sprintf("method %q is already registered", method)
|
||||
if reflect.ValueOf(method).Kind() != reflect.String {
|
||||
str := fmt.Sprintf("method %q is not a string type", method)
|
||||
return makeError(ErrInvalidType, str)
|
||||
}
|
||||
|
||||
rtp := reflect.TypeOf(params)
|
||||
if paramsType, ok := methodToConcreteType[method]; ok {
|
||||
if rtp == paramsType {
|
||||
return nil
|
||||
}
|
||||
str := fmt.Sprintf("method %q is already registered for "+
|
||||
"type %T", method, paramsType)
|
||||
return makeError(ErrDuplicateMethod, str)
|
||||
}
|
||||
|
||||
@ -171,7 +185,6 @@ func RegisterCmd(method string, cmd interface{}, flags UsageFlag) error {
|
||||
return makeError(ErrInvalidUsageFlags, str)
|
||||
}
|
||||
|
||||
rtp := reflect.TypeOf(cmd)
|
||||
if rtp.Kind() != reflect.Ptr {
|
||||
str := fmt.Sprintf("type must be *struct not '%s (%s)'", rtp,
|
||||
rtp.Kind())
|
||||
@ -267,25 +280,29 @@ func RegisterCmd(method string, cmd interface{}, flags UsageFlag) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// MustRegisterCmd performs the same function as RegisterCmd except it panics
|
||||
// if there is an error. This should only be called from package init
|
||||
// functions.
|
||||
func MustRegisterCmd(method string, cmd interface{}, flags UsageFlag) {
|
||||
if err := RegisterCmd(method, cmd, flags); err != nil {
|
||||
panic(fmt.Sprintf("failed to register type %q: %v\n", method,
|
||||
err))
|
||||
// MustRegister performs the same function as Register except it panics if there
|
||||
// is an error. This should only be called from package init functions.
|
||||
//
|
||||
// See Register for more details about correct usage.
|
||||
func MustRegister(method interface{}, cmd interface{}, flags UsageFlag) {
|
||||
if err := Register(method, cmd, flags); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// RegisteredCmdMethods returns a sorted list of methods for all registered
|
||||
// RegisteredMethods returns a sorted list of methods for all registered
|
||||
// commands.
|
||||
func RegisteredCmdMethods() []string {
|
||||
func RegisteredMethods(methodType interface{}) []string {
|
||||
registerLock.Lock()
|
||||
defer registerLock.Unlock()
|
||||
|
||||
typ := reflect.TypeOf(methodType)
|
||||
|
||||
methods := make([]string, 0, len(methodToInfo))
|
||||
for k := range methodToInfo {
|
||||
methods = append(methods, k)
|
||||
if typ == reflect.TypeOf(k) {
|
||||
methods = append(methods, reflect.ValueOf(k).String())
|
||||
}
|
||||
}
|
||||
|
||||
sort.Strings(methods)
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// Copyright (c) 2014 The btcsuite developers
|
||||
// Copyright (c) 2015-2016 The Decred 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.
|
||||
|
||||
@ -11,6 +11,27 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
// Register methods for testing purposes. This does not conflict with
|
||||
// registration performed by external packages as they are done in separate
|
||||
// builds.
|
||||
func init() {
|
||||
MustRegister("getblock", (*testGetBlockCmd)(nil), 0)
|
||||
MustRegister("getblockcount", (*testGetBlockCountCmd)(nil), 0)
|
||||
MustRegister("session", (*testSessionCmd)(nil), UFWebsocketOnly)
|
||||
MustRegister("help", (*testHelpCmd)(nil), 0)
|
||||
}
|
||||
|
||||
type testGetBlockCmd struct {
|
||||
Hash string
|
||||
Verbose *bool `jsonrpcdefault:"true"`
|
||||
VerboseTx *bool `jsonrpcdefault:"false"`
|
||||
}
|
||||
type testGetBlockCountCmd struct{}
|
||||
type testSessionCmd struct{}
|
||||
type testHelpCmd struct {
|
||||
Command *string
|
||||
}
|
||||
|
||||
// TestUsageFlagStringer tests the stringized output for the UsageFlag type.
|
||||
func TestUsageFlagStringer(t *testing.T) {
|
||||
t.Parallel()
|
||||
@ -20,12 +41,12 @@ func TestUsageFlagStringer(t *testing.T) {
|
||||
want string
|
||||
}{
|
||||
{0, "0x0"},
|
||||
{UFWalletOnly, "UFWalletOnly"},
|
||||
{1, "0x0"}, // was UFWalletOnly
|
||||
{UFWebsocketOnly, "UFWebsocketOnly"},
|
||||
{UFNotification, "UFNotification"},
|
||||
{UFWalletOnly | UFWebsocketOnly, "UFWalletOnly|UFWebsocketOnly"},
|
||||
{UFWalletOnly | UFWebsocketOnly | (1 << 31),
|
||||
"UFWalletOnly|UFWebsocketOnly|0x80000000"},
|
||||
{UFWebsocketOnly | UFNotification, "UFWebsocketOnly|UFNotification"},
|
||||
{1 | UFWebsocketOnly | UFNotification | (1 << 31),
|
||||
"UFWebsocketOnly|UFNotification|0x80000000"},
|
||||
}
|
||||
|
||||
// Detect additional usage flags that don't have the stringer added.
|
||||
@ -206,8 +227,7 @@ func TestRegisterCmdErrors(t *testing.T) {
|
||||
|
||||
t.Logf("Running %d tests", len(tests))
|
||||
for i, test := range tests {
|
||||
err := RegisterCmd(test.method, test.cmdFunc(),
|
||||
test.flags)
|
||||
err := Register(test.method, test.cmdFunc(), test.flags)
|
||||
if reflect.TypeOf(err) != reflect.TypeOf(test.err) {
|
||||
t.Errorf("Test #%d (%s) wrong error - got %T, "+
|
||||
"want %T", i, test.name, err, test.err)
|
||||
@ -237,7 +257,7 @@ func TestMustRegisterCmdPanic(t *testing.T) {
|
||||
}()
|
||||
|
||||
// Intentionally try to register an invalid type to force a panic.
|
||||
MustRegisterCmd("panicme", 0, 0)
|
||||
MustRegister("panicme", 0, 0)
|
||||
}
|
||||
|
||||
// TestRegisteredCmdMethods tests the RegisteredCmdMethods function ensure it
|
||||
@ -245,8 +265,8 @@ func TestMustRegisterCmdPanic(t *testing.T) {
|
||||
func TestRegisteredCmdMethods(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Ensure the registered methods are returned.
|
||||
methods := RegisteredCmdMethods()
|
||||
// Ensure the registered methods for plain string methods are returned.
|
||||
methods := RegisteredMethods("")
|
||||
if len(methods) == 0 {
|
||||
t.Fatal("RegisteredCmdMethods: no methods")
|
||||
}
|
||||
|
||||
13
go.mod
13
go.mod
@ -16,7 +16,8 @@ require (
|
||||
github.com/decred/dcrd/database v1.1.0
|
||||
github.com/decred/dcrd/dcrec v1.0.0
|
||||
github.com/decred/dcrd/dcrec/secp256k1 v1.0.2
|
||||
github.com/decred/dcrd/dcrjson/v2 v2.0.0
|
||||
github.com/decred/dcrd/dcrjson/v2 v2.2.0
|
||||
github.com/decred/dcrd/dcrjson/v3 v3.0.0
|
||||
github.com/decred/dcrd/dcrutil v1.3.0
|
||||
github.com/decred/dcrd/fees v1.0.0
|
||||
github.com/decred/dcrd/gcs v1.0.2
|
||||
@ -25,10 +26,11 @@ require (
|
||||
github.com/decred/dcrd/mempool/v2 v2.0.0
|
||||
github.com/decred/dcrd/mining v1.1.0
|
||||
github.com/decred/dcrd/peer v1.1.0
|
||||
github.com/decred/dcrd/rpc/jsonrpc/types v0.0.0
|
||||
github.com/decred/dcrd/rpcclient/v2 v2.0.0
|
||||
github.com/decred/dcrd/txscript v1.1.0
|
||||
github.com/decred/dcrd/wire v1.2.0
|
||||
github.com/decred/dcrwallet/rpc/jsonrpc/types v1.0.0
|
||||
github.com/decred/dcrwallet/rpc/jsonrpc/types v1.1.0
|
||||
github.com/decred/slog v1.0.0
|
||||
github.com/gorilla/websocket v1.4.0
|
||||
github.com/jessevdk/go-flags v1.4.0
|
||||
@ -47,7 +49,7 @@ replace (
|
||||
github.com/decred/dcrd/connmgr => ./connmgr
|
||||
github.com/decred/dcrd/database => ./database
|
||||
github.com/decred/dcrd/dcrec => ./dcrec
|
||||
github.com/decred/dcrd/dcrjson/v2 => ./dcrjson
|
||||
github.com/decred/dcrd/dcrjson/v3 => ./dcrjson
|
||||
github.com/decred/dcrd/dcrutil/v2 => ./dcrutil
|
||||
github.com/decred/dcrd/fees => ./fees
|
||||
github.com/decred/dcrd/gcs => ./gcs
|
||||
@ -57,7 +59,12 @@ replace (
|
||||
github.com/decred/dcrd/mempool/v2 => ./mempool
|
||||
github.com/decred/dcrd/mining => ./mining
|
||||
github.com/decred/dcrd/peer => ./peer
|
||||
github.com/decred/dcrd/rpc/jsonrpc/types => ./rpc/jsonrpc/types
|
||||
github.com/decred/dcrd/rpcclient/v2 => ./rpcclient
|
||||
github.com/decred/dcrd/txscript/v2 => ./txscript
|
||||
github.com/decred/dcrd/wire => ./wire
|
||||
)
|
||||
|
||||
replace github.com/decred/dcrd/dcrjson/v2 v2.2.0 => github.com/jrick/btcd/dcrjson/v2 v2.0.0-20190715200557-9fffa6c80ab0
|
||||
|
||||
replace github.com/decred/dcrwallet/rpc/jsonrpc/types v1.1.0 => github.com/jrick/btcwallet/rpc/jsonrpc/types v0.0.0-20190715193601-785bca9161e7
|
||||
|
||||
10
go.sum
10
go.sum
@ -32,6 +32,10 @@ github.com/decred/dcrd/dcrec/secp256k1 v1.0.0/go.mod h1:JPMFscGlgXTV684jxQNDijae
|
||||
github.com/decred/dcrd/dcrec/secp256k1 v1.0.1/go.mod h1:lhu4eZFSfTJWUnR3CFRcpD+Vta0KUAqnhTsTksHXgy0=
|
||||
github.com/decred/dcrd/dcrec/secp256k1 v1.0.2 h1:awk7sYJ4pGWmtkiGHFfctztJjHMKGLV8jctGQhAbKe0=
|
||||
github.com/decred/dcrd/dcrec/secp256k1 v1.0.2/go.mod h1:CHTUIVfmDDd0KFVFpNX1pFVCBUegxW387nN0IGwNKR0=
|
||||
github.com/decred/dcrd/dcrjson/v2 v2.0.0 h1:W0q4Alh36c5N318eUpfmU8kXoCNgImMLI87NIXni9Us=
|
||||
github.com/decred/dcrd/dcrjson/v2 v2.0.0/go.mod h1:FYueNy8BREAFq04YNEwcTsmGFcNqY+ehUUO81w2igi4=
|
||||
github.com/decred/dcrd/dcrjson/v2 v2.1.0-0.20190709184057-e4f5e3f84f39 h1:gRp7NXypQMNiK8MX4rxEgB7jWXZrpE9R3tqNYGoLeM0=
|
||||
github.com/decred/dcrd/dcrjson/v2 v2.1.0-0.20190709184057-e4f5e3f84f39/go.mod h1:x4dY9EiT+awLvXz4wNzGlVtzR9EXYkZglXlrnDoLI6g=
|
||||
github.com/decred/dcrd/dcrutil v1.1.1/go.mod h1:Jsttr0pEvzPAw+qay1kS1/PsbZYPyhluiNwwY6yBJS4=
|
||||
github.com/decred/dcrd/dcrutil v1.2.0/go.mod h1:tUNHS2gj7ApeEVS8gb6O+4wJW7w3O2MSRyRdcjW1JxU=
|
||||
github.com/decred/dcrd/dcrutil v1.3.0 h1:LtKIiDnq925yJT/4OpIKKiU9/WaxfD9LfhxrpLSi0Qs=
|
||||
@ -56,6 +60,12 @@ github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGAR
|
||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/jrick/bitset v1.0.0 h1:Ws0PXV3PwXqWK2n7Vz6idCdrV/9OrBXgHEJi27ZB9Dw=
|
||||
github.com/jrick/bitset v1.0.0/go.mod h1:ZOYB5Uvkla7wIEY4FEssPVi3IQXa02arznRaYaAEPe4=
|
||||
github.com/jrick/btcd/dcrjson/v2 v2.0.0-20190712210503-292c1e5e80ac h1:2vTh3IBLNrz5hsSpL8ADkxaIRSU8UW64wqUC0wmADtc=
|
||||
github.com/jrick/btcd/dcrjson/v2 v2.0.0-20190712210503-292c1e5e80ac/go.mod h1:JwKNPWI2B+oMTtj4zv5ale8682i99PF+ETEydAGdQIg=
|
||||
github.com/jrick/btcd/dcrjson/v2 v2.0.0-20190715200557-9fffa6c80ab0 h1:wgwsgxMRl8Z3MohHq+RxTxsZI8S3qHdJq88tZkX9Rv8=
|
||||
github.com/jrick/btcd/dcrjson/v2 v2.0.0-20190715200557-9fffa6c80ab0/go.mod h1:JwKNPWI2B+oMTtj4zv5ale8682i99PF+ETEydAGdQIg=
|
||||
github.com/jrick/btcwallet/rpc/jsonrpc/types v0.0.0-20190715193601-785bca9161e7 h1:mzBwESVcoOOQRdj+redewvo14ZY8o7FndeaNvMjYqss=
|
||||
github.com/jrick/btcwallet/rpc/jsonrpc/types v0.0.0-20190715193601-785bca9161e7/go.mod h1:3sSyqYX80jbLe3O/o3VgxHR82Up8lRLvhhbWZ26wCos=
|
||||
github.com/jrick/logrotate v1.0.0 h1:lQ1bL/n9mBNeIXoTUoYRlK4dHuNJVofX9oWqBtPnSzI=
|
||||
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
|
||||
@ -6,11 +6,13 @@
|
||||
// NOTE: This file is intended to house the RPC commands that are supported by
|
||||
// a chain server.
|
||||
|
||||
package dcrjson
|
||||
package types
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/decred/dcrd/dcrjson/v3"
|
||||
)
|
||||
|
||||
// AddNodeSubCmd defines the type used in the addnode JSON-RPC command for the
|
||||
@ -268,27 +270,27 @@ func NewExistsAddressesCmd(addresses []string) *ExistsAddressesCmd {
|
||||
|
||||
// ExistsMissedTicketsCmd defines the existsmissedtickets JSON-RPC command.
|
||||
type ExistsMissedTicketsCmd struct {
|
||||
TxHashBlob string
|
||||
TxHashes []string
|
||||
}
|
||||
|
||||
// NewExistsMissedTicketsCmd returns a new instance which can be used to issue an
|
||||
// existsmissedtickets JSON-RPC command.
|
||||
func NewExistsMissedTicketsCmd(txHashBlob string) *ExistsMissedTicketsCmd {
|
||||
func NewExistsMissedTicketsCmd(txHashes []string) *ExistsMissedTicketsCmd {
|
||||
return &ExistsMissedTicketsCmd{
|
||||
TxHashBlob: txHashBlob,
|
||||
TxHashes: txHashes,
|
||||
}
|
||||
}
|
||||
|
||||
// ExistsExpiredTicketsCmd defines the existsexpiredtickets JSON-RPC command.
|
||||
type ExistsExpiredTicketsCmd struct {
|
||||
TxHashBlob string
|
||||
TxHashes []string
|
||||
}
|
||||
|
||||
// NewExistsExpiredTicketsCmd returns a new instance which can be used to issue an
|
||||
// existsexpiredtickets JSON-RPC command.
|
||||
func NewExistsExpiredTicketsCmd(txHashBlob string) *ExistsExpiredTicketsCmd {
|
||||
func NewExistsExpiredTicketsCmd(txHashes []string) *ExistsExpiredTicketsCmd {
|
||||
return &ExistsExpiredTicketsCmd{
|
||||
TxHashBlob: txHashBlob,
|
||||
TxHashes: txHashes,
|
||||
}
|
||||
}
|
||||
|
||||
@ -307,27 +309,27 @@ func NewExistsLiveTicketCmd(txHash string) *ExistsLiveTicketCmd {
|
||||
|
||||
// ExistsLiveTicketsCmd defines the existslivetickets JSON-RPC command.
|
||||
type ExistsLiveTicketsCmd struct {
|
||||
TxHashBlob string
|
||||
TxHashes []string
|
||||
}
|
||||
|
||||
// NewExistsLiveTicketsCmd returns a new instance which can be used to issue an
|
||||
// existslivetickets JSON-RPC command.
|
||||
func NewExistsLiveTicketsCmd(txHashBlob string) *ExistsLiveTicketsCmd {
|
||||
func NewExistsLiveTicketsCmd(txHashes []string) *ExistsLiveTicketsCmd {
|
||||
return &ExistsLiveTicketsCmd{
|
||||
TxHashBlob: txHashBlob,
|
||||
TxHashes: txHashes,
|
||||
}
|
||||
}
|
||||
|
||||
// ExistsMempoolTxsCmd defines the existsmempooltxs JSON-RPC command.
|
||||
type ExistsMempoolTxsCmd struct {
|
||||
TxHashBlob string
|
||||
TxHashes []string
|
||||
}
|
||||
|
||||
// NewExistsMempoolTxsCmd returns a new instance which can be used to issue an
|
||||
// existslivetickets JSON-RPC command.
|
||||
func NewExistsMempoolTxsCmd(txHashBlob string) *ExistsMempoolTxsCmd {
|
||||
func NewExistsMempoolTxsCmd(txHashes []string) *ExistsMempoolTxsCmd {
|
||||
return &ExistsMempoolTxsCmd{
|
||||
TxHashBlob: txHashBlob,
|
||||
TxHashes: txHashes,
|
||||
}
|
||||
}
|
||||
|
||||
@ -502,7 +504,7 @@ func convertTemplateRequestField(fieldName string, iface interface{}) (interface
|
||||
|
||||
str := fmt.Sprintf("the %s field must be unspecified, a boolean, or "+
|
||||
"a 64-bit integer", fieldName)
|
||||
return nil, makeError(ErrInvalidType, str)
|
||||
return nil, dcrjson.Error{Code: dcrjson.ErrInvalidType, Message: str}
|
||||
}
|
||||
|
||||
// UnmarshalJSON provides a custom Unmarshal method for TemplateRequest. This
|
||||
@ -653,13 +655,13 @@ func NewGetInfoCmd() *GetInfoCmd {
|
||||
|
||||
// GetHeadersCmd defines the getheaders JSON-RPC command.
|
||||
type GetHeadersCmd struct {
|
||||
BlockLocators string `json:"blocklocators"`
|
||||
HashStop string `json:"hashstop"`
|
||||
BlockLocators []string `json:"blocklocators"`
|
||||
HashStop string `json:"hashstop"`
|
||||
}
|
||||
|
||||
// NewGetHeadersCmd returns a new instance which can be used to issue a
|
||||
// getheaders JSON-RPC command.
|
||||
func NewGetHeadersCmd(blockLocators string, hashStop string) *GetHeadersCmd {
|
||||
func NewGetHeadersCmd(blockLocators []string, hashStop string) *GetHeadersCmd {
|
||||
return &GetHeadersCmd{
|
||||
BlockLocators: blockLocators,
|
||||
HashStop: hashStop,
|
||||
@ -1195,81 +1197,81 @@ func NewVersionCmd() *VersionCmd { return new(VersionCmd) }
|
||||
|
||||
func init() {
|
||||
// No special flags for commands in this file.
|
||||
flags := UsageFlag(0)
|
||||
flags := dcrjson.UsageFlag(0)
|
||||
|
||||
MustRegisterCmd("addnode", (*AddNodeCmd)(nil), flags)
|
||||
MustRegisterCmd("createrawssrtx", (*CreateRawSSRtxCmd)(nil), flags)
|
||||
MustRegisterCmd("createrawsstx", (*CreateRawSStxCmd)(nil), flags)
|
||||
MustRegisterCmd("createrawtransaction", (*CreateRawTransactionCmd)(nil), flags)
|
||||
MustRegisterCmd("debuglevel", (*DebugLevelCmd)(nil), flags)
|
||||
MustRegisterCmd("decoderawtransaction", (*DecodeRawTransactionCmd)(nil), flags)
|
||||
MustRegisterCmd("decodescript", (*DecodeScriptCmd)(nil), flags)
|
||||
MustRegisterCmd("estimatefee", (*EstimateFeeCmd)(nil), flags)
|
||||
MustRegisterCmd("estimatesmartfee", (*EstimateSmartFeeCmd)(nil), flags)
|
||||
MustRegisterCmd("estimatestakediff", (*EstimateStakeDiffCmd)(nil), flags)
|
||||
MustRegisterCmd("existsaddress", (*ExistsAddressCmd)(nil), flags)
|
||||
MustRegisterCmd("existsaddresses", (*ExistsAddressesCmd)(nil), flags)
|
||||
MustRegisterCmd("existsmissedtickets", (*ExistsMissedTicketsCmd)(nil), flags)
|
||||
MustRegisterCmd("existsexpiredtickets", (*ExistsExpiredTicketsCmd)(nil), flags)
|
||||
MustRegisterCmd("existsliveticket", (*ExistsLiveTicketCmd)(nil), flags)
|
||||
MustRegisterCmd("existslivetickets", (*ExistsLiveTicketsCmd)(nil), flags)
|
||||
MustRegisterCmd("existsmempooltxs", (*ExistsMempoolTxsCmd)(nil), flags)
|
||||
MustRegisterCmd("generate", (*GenerateCmd)(nil), flags)
|
||||
MustRegisterCmd("getaddednodeinfo", (*GetAddedNodeInfoCmd)(nil), flags)
|
||||
MustRegisterCmd("getbestblock", (*GetBestBlockCmd)(nil), flags)
|
||||
MustRegisterCmd("getbestblockhash", (*GetBestBlockHashCmd)(nil), flags)
|
||||
MustRegisterCmd("getblock", (*GetBlockCmd)(nil), flags)
|
||||
MustRegisterCmd("getblockchaininfo", (*GetBlockChainInfoCmd)(nil), flags)
|
||||
MustRegisterCmd("getblockcount", (*GetBlockCountCmd)(nil), flags)
|
||||
MustRegisterCmd("getblockhash", (*GetBlockHashCmd)(nil), flags)
|
||||
MustRegisterCmd("getblockheader", (*GetBlockHeaderCmd)(nil), flags)
|
||||
MustRegisterCmd("getblocksubsidy", (*GetBlockSubsidyCmd)(nil), flags)
|
||||
MustRegisterCmd("getblocktemplate", (*GetBlockTemplateCmd)(nil), flags)
|
||||
MustRegisterCmd("getcfilter", (*GetCFilterCmd)(nil), flags)
|
||||
MustRegisterCmd("getcfilterheader", (*GetCFilterHeaderCmd)(nil), flags)
|
||||
MustRegisterCmd("getchaintips", (*GetChainTipsCmd)(nil), flags)
|
||||
MustRegisterCmd("getcoinsupply", (*GetCoinSupplyCmd)(nil), flags)
|
||||
MustRegisterCmd("getconnectioncount", (*GetConnectionCountCmd)(nil), flags)
|
||||
MustRegisterCmd("getcurrentnet", (*GetCurrentNetCmd)(nil), flags)
|
||||
MustRegisterCmd("getdifficulty", (*GetDifficultyCmd)(nil), flags)
|
||||
MustRegisterCmd("getgenerate", (*GetGenerateCmd)(nil), flags)
|
||||
MustRegisterCmd("gethashespersec", (*GetHashesPerSecCmd)(nil), flags)
|
||||
MustRegisterCmd("getheaders", (*GetHeadersCmd)(nil), flags)
|
||||
MustRegisterCmd("getinfo", (*GetInfoCmd)(nil), flags)
|
||||
MustRegisterCmd("getmempoolinfo", (*GetMempoolInfoCmd)(nil), flags)
|
||||
MustRegisterCmd("getmininginfo", (*GetMiningInfoCmd)(nil), flags)
|
||||
MustRegisterCmd("getnetworkinfo", (*GetNetworkInfoCmd)(nil), flags)
|
||||
MustRegisterCmd("getnettotals", (*GetNetTotalsCmd)(nil), flags)
|
||||
MustRegisterCmd("getnetworkhashps", (*GetNetworkHashPSCmd)(nil), flags)
|
||||
MustRegisterCmd("getpeerinfo", (*GetPeerInfoCmd)(nil), flags)
|
||||
MustRegisterCmd("getrawmempool", (*GetRawMempoolCmd)(nil), flags)
|
||||
MustRegisterCmd("getrawtransaction", (*GetRawTransactionCmd)(nil), flags)
|
||||
MustRegisterCmd("getstakedifficulty", (*GetStakeDifficultyCmd)(nil), flags)
|
||||
MustRegisterCmd("getstakeversioninfo", (*GetStakeVersionInfoCmd)(nil), flags)
|
||||
MustRegisterCmd("getstakeversions", (*GetStakeVersionsCmd)(nil), flags)
|
||||
MustRegisterCmd("getticketpoolvalue", (*GetTicketPoolValueCmd)(nil), flags)
|
||||
MustRegisterCmd("gettxout", (*GetTxOutCmd)(nil), flags)
|
||||
MustRegisterCmd("gettxoutsetinfo", (*GetTxOutSetInfoCmd)(nil), flags)
|
||||
MustRegisterCmd("getvoteinfo", (*GetVoteInfoCmd)(nil), flags)
|
||||
MustRegisterCmd("getwork", (*GetWorkCmd)(nil), flags)
|
||||
MustRegisterCmd("help", (*HelpCmd)(nil), flags)
|
||||
MustRegisterCmd("livetickets", (*LiveTicketsCmd)(nil), flags)
|
||||
MustRegisterCmd("missedtickets", (*MissedTicketsCmd)(nil), flags)
|
||||
MustRegisterCmd("node", (*NodeCmd)(nil), flags)
|
||||
MustRegisterCmd("ping", (*PingCmd)(nil), flags)
|
||||
MustRegisterCmd("rebroadcastmissed", (*RebroadcastMissedCmd)(nil), flags)
|
||||
MustRegisterCmd("rebroadcastwinners", (*RebroadcastWinnersCmd)(nil), flags)
|
||||
MustRegisterCmd("searchrawtransactions", (*SearchRawTransactionsCmd)(nil), flags)
|
||||
MustRegisterCmd("sendrawtransaction", (*SendRawTransactionCmd)(nil), flags)
|
||||
MustRegisterCmd("setgenerate", (*SetGenerateCmd)(nil), flags)
|
||||
MustRegisterCmd("stop", (*StopCmd)(nil), flags)
|
||||
MustRegisterCmd("submitblock", (*SubmitBlockCmd)(nil), flags)
|
||||
MustRegisterCmd("ticketfeeinfo", (*TicketFeeInfoCmd)(nil), flags)
|
||||
MustRegisterCmd("ticketsforaddress", (*TicketsForAddressCmd)(nil), flags)
|
||||
MustRegisterCmd("ticketvwap", (*TicketVWAPCmd)(nil), flags)
|
||||
MustRegisterCmd("txfeeinfo", (*TxFeeInfoCmd)(nil), flags)
|
||||
MustRegisterCmd("validateaddress", (*ValidateAddressCmd)(nil), flags)
|
||||
MustRegisterCmd("verifychain", (*VerifyChainCmd)(nil), flags)
|
||||
MustRegisterCmd("verifymessage", (*VerifyMessageCmd)(nil), flags)
|
||||
MustRegisterCmd("version", (*VersionCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("addnode"), (*AddNodeCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("createrawssrtx"), (*CreateRawSSRtxCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("createrawsstx"), (*CreateRawSStxCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("createrawtransaction"), (*CreateRawTransactionCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("debuglevel"), (*DebugLevelCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("decoderawtransaction"), (*DecodeRawTransactionCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("decodescript"), (*DecodeScriptCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("estimatefee"), (*EstimateFeeCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("estimatesmartfee"), (*EstimateSmartFeeCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("estimatestakediff"), (*EstimateStakeDiffCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("existsaddress"), (*ExistsAddressCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("existsaddresses"), (*ExistsAddressesCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("existsmissedtickets"), (*ExistsMissedTicketsCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("existsexpiredtickets"), (*ExistsExpiredTicketsCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("existsliveticket"), (*ExistsLiveTicketCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("existslivetickets"), (*ExistsLiveTicketsCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("existsmempooltxs"), (*ExistsMempoolTxsCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("generate"), (*GenerateCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("getaddednodeinfo"), (*GetAddedNodeInfoCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("getbestblock"), (*GetBestBlockCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("getbestblockhash"), (*GetBestBlockHashCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("getblock"), (*GetBlockCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("getblockchaininfo"), (*GetBlockChainInfoCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("getblockcount"), (*GetBlockCountCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("getblockhash"), (*GetBlockHashCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("getblockheader"), (*GetBlockHeaderCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("getblocksubsidy"), (*GetBlockSubsidyCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("getblocktemplate"), (*GetBlockTemplateCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("getcfilter"), (*GetCFilterCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("getcfilterheader"), (*GetCFilterHeaderCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("getchaintips"), (*GetChainTipsCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("getcoinsupply"), (*GetCoinSupplyCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("getconnectioncount"), (*GetConnectionCountCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("getcurrentnet"), (*GetCurrentNetCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("getdifficulty"), (*GetDifficultyCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("getgenerate"), (*GetGenerateCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("gethashespersec"), (*GetHashesPerSecCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("getheaders"), (*GetHeadersCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("getinfo"), (*GetInfoCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("getmempoolinfo"), (*GetMempoolInfoCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("getmininginfo"), (*GetMiningInfoCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("getnetworkinfo"), (*GetNetworkInfoCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("getnettotals"), (*GetNetTotalsCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("getnetworkhashps"), (*GetNetworkHashPSCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("getpeerinfo"), (*GetPeerInfoCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("getrawmempool"), (*GetRawMempoolCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("getrawtransaction"), (*GetRawTransactionCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("getstakedifficulty"), (*GetStakeDifficultyCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("getstakeversioninfo"), (*GetStakeVersionInfoCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("getstakeversions"), (*GetStakeVersionsCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("getticketpoolvalue"), (*GetTicketPoolValueCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("gettxout"), (*GetTxOutCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("gettxoutsetinfo"), (*GetTxOutSetInfoCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("getvoteinfo"), (*GetVoteInfoCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("getwork"), (*GetWorkCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("help"), (*HelpCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("livetickets"), (*LiveTicketsCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("missedtickets"), (*MissedTicketsCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("node"), (*NodeCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("ping"), (*PingCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("rebroadcastmissed"), (*RebroadcastMissedCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("rebroadcastwinners"), (*RebroadcastWinnersCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("searchrawtransactions"), (*SearchRawTransactionsCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("sendrawtransaction"), (*SendRawTransactionCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("setgenerate"), (*SetGenerateCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("stop"), (*StopCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("submitblock"), (*SubmitBlockCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("ticketfeeinfo"), (*TicketFeeInfoCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("ticketsforaddress"), (*TicketsForAddressCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("ticketvwap"), (*TicketVWAPCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("txfeeinfo"), (*TxFeeInfoCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("validateaddress"), (*ValidateAddressCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("verifychain"), (*VerifyChainCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("verifymessage"), (*VerifyMessageCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("version"), (*VersionCmd)(nil), flags)
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -3,7 +3,7 @@
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package dcrjson
|
||||
package types
|
||||
|
||||
import "encoding/json"
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package dcrjson
|
||||
package types
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
@ -6,7 +6,9 @@
|
||||
// NOTE: This file is intended to house the RPC commands that are supported by
|
||||
// a chain server, but are only available via websockets.
|
||||
|
||||
package dcrjson
|
||||
package types
|
||||
|
||||
import "github.com/decred/dcrd/dcrjson/v3"
|
||||
|
||||
// AuthenticateCmd defines the authenticate JSON-RPC command.
|
||||
type AuthenticateCmd struct {
|
||||
@ -150,34 +152,32 @@ func NewStopNotifyNewTransactionsCmd() *StopNotifyNewTransactionsCmd {
|
||||
|
||||
// RescanCmd defines the rescan JSON-RPC command.
|
||||
type RescanCmd struct {
|
||||
// Concatenated block hashes in non-byte-reversed hex encoding. Must
|
||||
// have length evenly divisible by 2*chainhash.HashSize.
|
||||
BlockHashes string
|
||||
BlockHashes []string
|
||||
}
|
||||
|
||||
// NewRescanCmd returns a new instance which can be used to issue a rescan
|
||||
// JSON-RPC command.
|
||||
func NewRescanCmd(blockHashes string) *RescanCmd {
|
||||
func NewRescanCmd(blockHashes []string) *RescanCmd {
|
||||
return &RescanCmd{BlockHashes: blockHashes}
|
||||
}
|
||||
|
||||
func init() {
|
||||
// The commands in this file are only usable by websockets.
|
||||
flags := UFWebsocketOnly
|
||||
flags := dcrjson.UFWebsocketOnly
|
||||
|
||||
MustRegisterCmd("authenticate", (*AuthenticateCmd)(nil), flags)
|
||||
MustRegisterCmd("loadtxfilter", (*LoadTxFilterCmd)(nil), flags)
|
||||
MustRegisterCmd("notifyblocks", (*NotifyBlocksCmd)(nil), flags)
|
||||
MustRegisterCmd("notifynewtransactions", (*NotifyNewTransactionsCmd)(nil), flags)
|
||||
MustRegisterCmd("notifynewtickets", (*NotifyNewTicketsCmd)(nil), flags)
|
||||
MustRegisterCmd("notifyspentandmissedtickets",
|
||||
dcrjson.MustRegister(Method("authenticate"), (*AuthenticateCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("loadtxfilter"), (*LoadTxFilterCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("notifyblocks"), (*NotifyBlocksCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("notifynewtransactions"), (*NotifyNewTransactionsCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("notifynewtickets"), (*NotifyNewTicketsCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("notifyspentandmissedtickets"),
|
||||
(*NotifySpentAndMissedTicketsCmd)(nil), flags)
|
||||
MustRegisterCmd("notifystakedifficulty",
|
||||
dcrjson.MustRegister(Method("notifystakedifficulty"),
|
||||
(*NotifyStakeDifficultyCmd)(nil), flags)
|
||||
MustRegisterCmd("notifywinningtickets",
|
||||
dcrjson.MustRegister(Method("notifywinningtickets"),
|
||||
(*NotifyWinningTicketsCmd)(nil), flags)
|
||||
MustRegisterCmd("session", (*SessionCmd)(nil), flags)
|
||||
MustRegisterCmd("stopnotifyblocks", (*StopNotifyBlocksCmd)(nil), flags)
|
||||
MustRegisterCmd("stopnotifynewtransactions", (*StopNotifyNewTransactionsCmd)(nil), flags)
|
||||
MustRegisterCmd("rescan", (*RescanCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("session"), (*SessionCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("stopnotifyblocks"), (*StopNotifyBlocksCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("stopnotifynewtransactions"), (*StopNotifyNewTransactionsCmd)(nil), flags)
|
||||
dcrjson.MustRegister(Method("rescan"), (*RescanCmd)(nil), flags)
|
||||
}
|
||||
@ -3,7 +3,7 @@
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package dcrjson
|
||||
package types
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@ -11,6 +11,8 @@ import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/decred/dcrd/dcrjson/v3"
|
||||
)
|
||||
|
||||
// TestChainSvrWsCmds tests all of the chain server websocket-specific commands
|
||||
@ -31,7 +33,7 @@ func TestChainSvrWsCmds(t *testing.T) {
|
||||
{
|
||||
name: "authenticate",
|
||||
newCmd: func() (interface{}, error) {
|
||||
return NewCmd("authenticate", "user", "pass")
|
||||
return dcrjson.NewCmd(Method("authenticate"), "user", "pass")
|
||||
},
|
||||
staticCmd: func() interface{} {
|
||||
return NewAuthenticateCmd("user", "pass")
|
||||
@ -42,7 +44,7 @@ func TestChainSvrWsCmds(t *testing.T) {
|
||||
{
|
||||
name: "notifywinningtickets",
|
||||
newCmd: func() (interface{}, error) {
|
||||
return NewCmd("notifywinningtickets")
|
||||
return dcrjson.NewCmd(Method("notifywinningtickets"))
|
||||
},
|
||||
staticCmd: func() interface{} {
|
||||
return NewNotifyWinningTicketsCmd()
|
||||
@ -53,7 +55,7 @@ func TestChainSvrWsCmds(t *testing.T) {
|
||||
{
|
||||
name: "notifyspentandmissedtickets",
|
||||
newCmd: func() (interface{}, error) {
|
||||
return NewCmd("notifyspentandmissedtickets")
|
||||
return dcrjson.NewCmd(Method("notifyspentandmissedtickets"))
|
||||
},
|
||||
staticCmd: func() interface{} {
|
||||
return NewNotifySpentAndMissedTicketsCmd()
|
||||
@ -64,7 +66,7 @@ func TestChainSvrWsCmds(t *testing.T) {
|
||||
{
|
||||
name: "notifynewtickets",
|
||||
newCmd: func() (interface{}, error) {
|
||||
return NewCmd("notifynewtickets")
|
||||
return dcrjson.NewCmd(Method("notifynewtickets"))
|
||||
},
|
||||
staticCmd: func() interface{} {
|
||||
return NewNotifyNewTicketsCmd()
|
||||
@ -75,7 +77,7 @@ func TestChainSvrWsCmds(t *testing.T) {
|
||||
{
|
||||
name: "notifystakedifficulty",
|
||||
newCmd: func() (interface{}, error) {
|
||||
return NewCmd("notifystakedifficulty")
|
||||
return dcrjson.NewCmd(Method("notifystakedifficulty"))
|
||||
},
|
||||
staticCmd: func() interface{} {
|
||||
return NewNotifyStakeDifficultyCmd()
|
||||
@ -86,7 +88,7 @@ func TestChainSvrWsCmds(t *testing.T) {
|
||||
{
|
||||
name: "notifyblocks",
|
||||
newCmd: func() (interface{}, error) {
|
||||
return NewCmd("notifyblocks")
|
||||
return dcrjson.NewCmd(Method("notifyblocks"))
|
||||
},
|
||||
staticCmd: func() interface{} {
|
||||
return NewNotifyBlocksCmd()
|
||||
@ -97,7 +99,7 @@ func TestChainSvrWsCmds(t *testing.T) {
|
||||
{
|
||||
name: "stopnotifyblocks",
|
||||
newCmd: func() (interface{}, error) {
|
||||
return NewCmd("stopnotifyblocks")
|
||||
return dcrjson.NewCmd(Method("stopnotifyblocks"))
|
||||
},
|
||||
staticCmd: func() interface{} {
|
||||
return NewStopNotifyBlocksCmd()
|
||||
@ -108,33 +110,33 @@ func TestChainSvrWsCmds(t *testing.T) {
|
||||
{
|
||||
name: "notifynewtransactions",
|
||||
newCmd: func() (interface{}, error) {
|
||||
return NewCmd("notifynewtransactions")
|
||||
return dcrjson.NewCmd(Method("notifynewtransactions"))
|
||||
},
|
||||
staticCmd: func() interface{} {
|
||||
return NewNotifyNewTransactionsCmd(nil)
|
||||
},
|
||||
marshalled: `{"jsonrpc":"1.0","method":"notifynewtransactions","params":[],"id":1}`,
|
||||
unmarshalled: &NotifyNewTransactionsCmd{
|
||||
Verbose: Bool(false),
|
||||
Verbose: dcrjson.Bool(false),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "notifynewtransactions optional",
|
||||
newCmd: func() (interface{}, error) {
|
||||
return NewCmd("notifynewtransactions", true)
|
||||
return dcrjson.NewCmd(Method("notifynewtransactions"), true)
|
||||
},
|
||||
staticCmd: func() interface{} {
|
||||
return NewNotifyNewTransactionsCmd(Bool(true))
|
||||
return NewNotifyNewTransactionsCmd(dcrjson.Bool(true))
|
||||
},
|
||||
marshalled: `{"jsonrpc":"1.0","method":"notifynewtransactions","params":[true],"id":1}`,
|
||||
unmarshalled: &NotifyNewTransactionsCmd{
|
||||
Verbose: Bool(true),
|
||||
Verbose: dcrjson.Bool(true),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "stopnotifynewtransactions",
|
||||
newCmd: func() (interface{}, error) {
|
||||
return NewCmd("stopnotifynewtransactions")
|
||||
return dcrjson.NewCmd(Method("stopnotifynewtransactions"))
|
||||
},
|
||||
staticCmd: func() interface{} {
|
||||
return NewStopNotifyNewTransactionsCmd()
|
||||
@ -145,14 +147,14 @@ func TestChainSvrWsCmds(t *testing.T) {
|
||||
{
|
||||
name: "rescan",
|
||||
newCmd: func() (interface{}, error) {
|
||||
return NewCmd("rescan", "0000000000000000000000000000000000000000000000000000000000000123")
|
||||
return dcrjson.NewCmd(Method("rescan"), []string{"0000000000000000000000000000000000000000000000000000000000000123"})
|
||||
},
|
||||
staticCmd: func() interface{} {
|
||||
return NewRescanCmd("0000000000000000000000000000000000000000000000000000000000000123")
|
||||
return NewRescanCmd([]string{"0000000000000000000000000000000000000000000000000000000000000123"})
|
||||
},
|
||||
marshalled: `{"jsonrpc":"1.0","method":"rescan","params":["0000000000000000000000000000000000000000000000000000000000000123"],"id":1}`,
|
||||
marshalled: `{"jsonrpc":"1.0","method":"rescan","params":[["0000000000000000000000000000000000000000000000000000000000000123"]],"id":1}`,
|
||||
unmarshalled: &RescanCmd{
|
||||
BlockHashes: "0000000000000000000000000000000000000000000000000000000000000123",
|
||||
BlockHashes: []string{"0000000000000000000000000000000000000000000000000000000000000123"},
|
||||
},
|
||||
},
|
||||
}
|
||||
@ -161,7 +163,7 @@ func TestChainSvrWsCmds(t *testing.T) {
|
||||
for i, test := range tests {
|
||||
// Marshal the command as created by the new static command
|
||||
// creation function.
|
||||
marshalled, err := MarshalCmd("1.0", testID, test.staticCmd())
|
||||
marshalled, err := dcrjson.MarshalCmd("1.0", testID, test.staticCmd())
|
||||
if err != nil {
|
||||
t.Errorf("MarshalCmd #%d (%s) unexpected error: %v", i,
|
||||
test.name, err)
|
||||
@ -179,13 +181,13 @@ func TestChainSvrWsCmds(t *testing.T) {
|
||||
// new command creation function.
|
||||
cmd, err := test.newCmd()
|
||||
if err != nil {
|
||||
t.Errorf("Test #%d (%s) unexpected NewCmd error: %v ",
|
||||
t.Errorf("Test #%d (%s) unexpected dcrjson.NewCmd error: %v ",
|
||||
i, test.name, err)
|
||||
}
|
||||
|
||||
// Marshal the command as created by the generic new command
|
||||
// creation function.
|
||||
marshalled, err = MarshalCmd("1.0", testID, cmd)
|
||||
marshalled, err = dcrjson.MarshalCmd("1.0", testID, cmd)
|
||||
if err != nil {
|
||||
t.Errorf("MarshalCmd #%d (%s) unexpected error: %v", i,
|
||||
test.name, err)
|
||||
@ -199,7 +201,7 @@ func TestChainSvrWsCmds(t *testing.T) {
|
||||
continue
|
||||
}
|
||||
|
||||
var request Request
|
||||
var request dcrjson.Request
|
||||
if err := json.Unmarshal(marshalled, &request); err != nil {
|
||||
t.Errorf("Test #%d (%s) unexpected error while "+
|
||||
"unmarshalling JSON-RPC request: %v", i,
|
||||
@ -207,9 +209,9 @@ func TestChainSvrWsCmds(t *testing.T) {
|
||||
continue
|
||||
}
|
||||
|
||||
cmd, err = UnmarshalCmd(&request)
|
||||
cmd, err = dcrjson.ParseParams(Method(request.Method), request.Params)
|
||||
if err != nil {
|
||||
t.Errorf("UnmarshalCmd #%d (%s) unexpected error: %v", i,
|
||||
t.Errorf("ParseParams #%d (%s) unexpected error: %v", i,
|
||||
test.name, err)
|
||||
continue
|
||||
}
|
||||
@ -6,50 +6,52 @@
|
||||
// NOTE: This file is intended to house the RPC websocket notifications that are
|
||||
// supported by a chain server.
|
||||
|
||||
package dcrjson
|
||||
package types
|
||||
|
||||
import "github.com/decred/dcrd/dcrjson/v3"
|
||||
|
||||
const (
|
||||
// BlockConnectedNtfnMethod is the method used for notifications from
|
||||
// the chain server that a block has been connected.
|
||||
BlockConnectedNtfnMethod = "blockconnected"
|
||||
BlockConnectedNtfnMethod Method = "blockconnected"
|
||||
|
||||
// BlockDisconnectedNtfnMethod is the method used for notifications from
|
||||
// the chain server that a block has been disconnected.
|
||||
BlockDisconnectedNtfnMethod = "blockdisconnected"
|
||||
BlockDisconnectedNtfnMethod Method = "blockdisconnected"
|
||||
|
||||
// NewTicketsNtfnMethod is the method of the daemon newtickets notification.
|
||||
NewTicketsNtfnMethod = "newtickets"
|
||||
NewTicketsNtfnMethod Method = "newtickets"
|
||||
|
||||
// ReorganizationNtfnMethod is the method used for notifications that the
|
||||
// block chain is in the process of a reorganization.
|
||||
ReorganizationNtfnMethod = "reorganization"
|
||||
ReorganizationNtfnMethod Method = "reorganization"
|
||||
|
||||
// TxAcceptedNtfnMethod is the method used for notifications from the
|
||||
// chain server that a transaction has been accepted into the mempool.
|
||||
TxAcceptedNtfnMethod = "txaccepted"
|
||||
TxAcceptedNtfnMethod Method = "txaccepted"
|
||||
|
||||
// TxAcceptedVerboseNtfnMethod is the method used for notifications from
|
||||
// the chain server that a transaction has been accepted into the
|
||||
// mempool. This differs from TxAcceptedNtfnMethod in that it provides
|
||||
// more details in the notification.
|
||||
TxAcceptedVerboseNtfnMethod = "txacceptedverbose"
|
||||
TxAcceptedVerboseNtfnMethod Method = "txacceptedverbose"
|
||||
|
||||
// RelevantTxAcceptedNtfnMethod is the method used for notifications
|
||||
// from the chain server that inform a client that a relevant
|
||||
// transaction was accepted by the mempool.
|
||||
RelevantTxAcceptedNtfnMethod = "relevanttxaccepted"
|
||||
RelevantTxAcceptedNtfnMethod Method = "relevanttxaccepted"
|
||||
|
||||
// SpentAndMissedTicketsNtfnMethod is the method of the daemon
|
||||
// spentandmissedtickets notification.
|
||||
SpentAndMissedTicketsNtfnMethod = "spentandmissedtickets"
|
||||
SpentAndMissedTicketsNtfnMethod Method = "spentandmissedtickets"
|
||||
|
||||
// StakeDifficultyNtfnMethod is the method of the daemon stakedifficulty
|
||||
// notification.
|
||||
StakeDifficultyNtfnMethod = "stakedifficulty"
|
||||
StakeDifficultyNtfnMethod Method = "stakedifficulty"
|
||||
|
||||
// WinningTicketsNtfnMethod is the method of the daemon winningtickets
|
||||
// notification.
|
||||
WinningTicketsNtfnMethod = "winningtickets"
|
||||
WinningTicketsNtfnMethod Method = "winningtickets"
|
||||
)
|
||||
|
||||
// BlockConnectedNtfn defines the blockconnected JSON-RPC notification.
|
||||
@ -215,16 +217,16 @@ func NewWinningTicketsNtfn(hash string, height int32, tickets map[string]string)
|
||||
func init() {
|
||||
// The commands in this file are only usable by websockets and are
|
||||
// notifications.
|
||||
flags := UFWebsocketOnly | UFNotification
|
||||
flags := dcrjson.UFWebsocketOnly | dcrjson.UFNotification
|
||||
|
||||
MustRegisterCmd(BlockConnectedNtfnMethod, (*BlockConnectedNtfn)(nil), flags)
|
||||
MustRegisterCmd(BlockDisconnectedNtfnMethod, (*BlockDisconnectedNtfn)(nil), flags)
|
||||
MustRegisterCmd(NewTicketsNtfnMethod, (*NewTicketsNtfn)(nil), flags)
|
||||
MustRegisterCmd(ReorganizationNtfnMethod, (*ReorganizationNtfn)(nil), flags)
|
||||
MustRegisterCmd(TxAcceptedNtfnMethod, (*TxAcceptedNtfn)(nil), flags)
|
||||
MustRegisterCmd(TxAcceptedVerboseNtfnMethod, (*TxAcceptedVerboseNtfn)(nil), flags)
|
||||
MustRegisterCmd(RelevantTxAcceptedNtfnMethod, (*RelevantTxAcceptedNtfn)(nil), flags)
|
||||
MustRegisterCmd(SpentAndMissedTicketsNtfnMethod, (*SpentAndMissedTicketsNtfn)(nil), flags)
|
||||
MustRegisterCmd(StakeDifficultyNtfnMethod, (*StakeDifficultyNtfn)(nil), flags)
|
||||
MustRegisterCmd(WinningTicketsNtfnMethod, (*WinningTicketsNtfn)(nil), flags)
|
||||
dcrjson.MustRegister(BlockConnectedNtfnMethod, (*BlockConnectedNtfn)(nil), flags)
|
||||
dcrjson.MustRegister(BlockDisconnectedNtfnMethod, (*BlockDisconnectedNtfn)(nil), flags)
|
||||
dcrjson.MustRegister(NewTicketsNtfnMethod, (*NewTicketsNtfn)(nil), flags)
|
||||
dcrjson.MustRegister(ReorganizationNtfnMethod, (*ReorganizationNtfn)(nil), flags)
|
||||
dcrjson.MustRegister(TxAcceptedNtfnMethod, (*TxAcceptedNtfn)(nil), flags)
|
||||
dcrjson.MustRegister(TxAcceptedVerboseNtfnMethod, (*TxAcceptedVerboseNtfn)(nil), flags)
|
||||
dcrjson.MustRegister(RelevantTxAcceptedNtfnMethod, (*RelevantTxAcceptedNtfn)(nil), flags)
|
||||
dcrjson.MustRegister(SpentAndMissedTicketsNtfnMethod, (*SpentAndMissedTicketsNtfn)(nil), flags)
|
||||
dcrjson.MustRegister(StakeDifficultyNtfnMethod, (*StakeDifficultyNtfn)(nil), flags)
|
||||
dcrjson.MustRegister(WinningTicketsNtfnMethod, (*WinningTicketsNtfn)(nil), flags)
|
||||
}
|
||||
@ -3,7 +3,7 @@
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package dcrjson
|
||||
package types
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@ -11,6 +11,8 @@ import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/decred/dcrd/dcrjson/v3"
|
||||
)
|
||||
|
||||
// TestChainSvrWsNtfns tests all of the chain server websocket-specific
|
||||
@ -30,7 +32,7 @@ func TestChainSvrWsNtfns(t *testing.T) {
|
||||
{
|
||||
name: "blockconnected",
|
||||
newNtfn: func() (interface{}, error) {
|
||||
return NewCmd("blockconnected", "header", []string{"tx0", "tx1"})
|
||||
return dcrjson.NewCmd(Method("blockconnected"), "header", []string{"tx0", "tx1"})
|
||||
},
|
||||
staticNtfn: func() interface{} {
|
||||
return NewBlockConnectedNtfn("header", []string{"tx0", "tx1"})
|
||||
@ -44,7 +46,7 @@ func TestChainSvrWsNtfns(t *testing.T) {
|
||||
{
|
||||
name: "blockdisconnected",
|
||||
newNtfn: func() (interface{}, error) {
|
||||
return NewCmd("blockdisconnected", "header")
|
||||
return dcrjson.NewCmd(Method("blockdisconnected"), "header")
|
||||
},
|
||||
staticNtfn: func() interface{} {
|
||||
return NewBlockDisconnectedNtfn("header")
|
||||
@ -57,7 +59,7 @@ func TestChainSvrWsNtfns(t *testing.T) {
|
||||
{
|
||||
name: "newtickets",
|
||||
newNtfn: func() (interface{}, error) {
|
||||
return NewCmd("newtickets", "123", 100, 3, []string{"a", "b"})
|
||||
return dcrjson.NewCmd(Method("newtickets"), "123", 100, 3, []string{"a", "b"})
|
||||
},
|
||||
staticNtfn: func() interface{} {
|
||||
return NewNewTicketsNtfn("123", 100, 3, []string{"a", "b"})
|
||||
@ -73,7 +75,7 @@ func TestChainSvrWsNtfns(t *testing.T) {
|
||||
{
|
||||
name: "relevanttxaccepted",
|
||||
newNtfn: func() (interface{}, error) {
|
||||
return NewCmd("relevanttxaccepted", "001122")
|
||||
return dcrjson.NewCmd(Method("relevanttxaccepted"), "001122")
|
||||
},
|
||||
staticNtfn: func() interface{} {
|
||||
return NewRelevantTxAcceptedNtfn("001122")
|
||||
@ -86,7 +88,7 @@ func TestChainSvrWsNtfns(t *testing.T) {
|
||||
{
|
||||
name: "spentandmissedtickets",
|
||||
newNtfn: func() (interface{}, error) {
|
||||
return NewCmd("spentandmissedtickets", "123", 100, 3, map[string]string{"a": "b"})
|
||||
return dcrjson.NewCmd(Method("spentandmissedtickets"), "123", 100, 3, map[string]string{"a": "b"})
|
||||
},
|
||||
staticNtfn: func() interface{} {
|
||||
return NewSpentAndMissedTicketsNtfn("123", 100, 3, map[string]string{"a": "b"})
|
||||
@ -102,7 +104,7 @@ func TestChainSvrWsNtfns(t *testing.T) {
|
||||
{
|
||||
name: "txaccepted",
|
||||
newNtfn: func() (interface{}, error) {
|
||||
return NewCmd("txaccepted", "123", 1.5)
|
||||
return dcrjson.NewCmd(Method("txaccepted"), "123", 1.5)
|
||||
},
|
||||
staticNtfn: func() interface{} {
|
||||
return NewTxAcceptedNtfn("123", 1.5)
|
||||
@ -116,7 +118,7 @@ func TestChainSvrWsNtfns(t *testing.T) {
|
||||
{
|
||||
name: "txacceptedverbose",
|
||||
newNtfn: func() (interface{}, error) {
|
||||
return NewCmd("txacceptedverbose", `{"hex":"001122","txid":"123","version":1,"locktime":4294967295,"vin":null,"vout":null,"confirmations":0}`)
|
||||
return dcrjson.NewCmd(Method("txacceptedverbose"), `{"hex":"001122","txid":"123","version":1,"locktime":4294967295,"vin":null,"vout":null,"confirmations":0}`)
|
||||
},
|
||||
staticNtfn: func() interface{} {
|
||||
txResult := TxRawResult{
|
||||
@ -146,7 +148,7 @@ func TestChainSvrWsNtfns(t *testing.T) {
|
||||
{
|
||||
name: "winningtickets",
|
||||
newNtfn: func() (interface{}, error) {
|
||||
return NewCmd("winningtickets", "123", 100, map[string]string{"a": "b"})
|
||||
return dcrjson.NewCmd(Method("winningtickets"), "123", 100, map[string]string{"a": "b"})
|
||||
},
|
||||
staticNtfn: func() interface{} {
|
||||
return NewWinningTicketsNtfn("123", 100, map[string]string{"a": "b"})
|
||||
@ -164,7 +166,7 @@ func TestChainSvrWsNtfns(t *testing.T) {
|
||||
for i, test := range tests {
|
||||
// Marshal the notification as created by the new static
|
||||
// creation function. The ID is nil for notifications.
|
||||
marshalled, err := MarshalCmd("1.0", nil, test.staticNtfn())
|
||||
marshalled, err := dcrjson.MarshalCmd("1.0", nil, test.staticNtfn())
|
||||
if err != nil {
|
||||
t.Errorf("MarshalCmd #%d (%s) unexpected error: %v", i,
|
||||
test.name, err)
|
||||
@ -182,14 +184,14 @@ func TestChainSvrWsNtfns(t *testing.T) {
|
||||
// generic new notification creation function.
|
||||
cmd, err := test.newNtfn()
|
||||
if err != nil {
|
||||
t.Errorf("Test #%d (%s) unexpected NewCmd error: %v ",
|
||||
t.Errorf("Test #%d (%s) unexpected dcrjson.NewCmd error: %v ",
|
||||
i, test.name, err)
|
||||
}
|
||||
|
||||
// Marshal the notification as created by the generic new
|
||||
// notification creation function. The ID is nil for
|
||||
// notifications.
|
||||
marshalled, err = MarshalCmd("1.0", nil, cmd)
|
||||
marshalled, err = dcrjson.MarshalCmd("1.0", nil, cmd)
|
||||
if err != nil {
|
||||
t.Errorf("MarshalCmd #%d (%s) unexpected error: %v", i,
|
||||
test.name, err)
|
||||
@ -203,7 +205,7 @@ func TestChainSvrWsNtfns(t *testing.T) {
|
||||
continue
|
||||
}
|
||||
|
||||
var request Request
|
||||
var request dcrjson.Request
|
||||
if err := json.Unmarshal(marshalled, &request); err != nil {
|
||||
t.Errorf("Test #%d (%s) unexpected error while "+
|
||||
"unmarshalling JSON-RPC request: %v", i,
|
||||
@ -211,9 +213,9 @@ func TestChainSvrWsNtfns(t *testing.T) {
|
||||
continue
|
||||
}
|
||||
|
||||
cmd, err = UnmarshalCmd(&request)
|
||||
cmd, err = dcrjson.ParseParams(Method(request.Method), request.Params)
|
||||
if err != nil {
|
||||
t.Errorf("UnmarshalCmd #%d (%s) unexpected error: %v", i,
|
||||
t.Errorf("ParseParams #%d (%s) unexpected error: %v", i,
|
||||
test.name, err)
|
||||
continue
|
||||
}
|
||||
@ -3,7 +3,7 @@
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package dcrjson
|
||||
package types
|
||||
|
||||
// SessionResult models the data from the session command.
|
||||
type SessionResult struct {
|
||||
7
rpc/jsonrpc/types/go.mod
Normal file
7
rpc/jsonrpc/types/go.mod
Normal file
@ -0,0 +1,7 @@
|
||||
module github.com/decred/dcrd/rpc/jsonrpc/types
|
||||
|
||||
go 1.11
|
||||
|
||||
require github.com/decred/dcrd/dcrjson/v3 v3.0.0
|
||||
|
||||
replace github.com/decred/dcrd/dcrjson/v3 => ../../../dcrjson
|
||||
8
rpc/jsonrpc/types/go.sum
Normal file
8
rpc/jsonrpc/types/go.sum
Normal file
@ -0,0 +1,8 @@
|
||||
github.com/dchest/blake256 v1.0.0 h1:6gUgI5MHdz9g0TdrgKqXsoDX+Zjxmm1Sc6OsoGru50I=
|
||||
github.com/dchest/blake256 v1.0.0/go.mod h1:xXNWCE1jsAP8DAjP+rKw2MbeqLczjI3TRx2VK+9OEYY=
|
||||
github.com/decred/dcrd v1.3.0 h1:EEXm7BdiROfazDtuFsOu9mfotnyy00bgCuVwUqaszFo=
|
||||
github.com/decred/dcrd/chaincfg/chainhash v1.0.1 h1:0vG7U9+dSjSCaHQKdoSKURK2pOb47+b+8FK5q4+Je7M=
|
||||
github.com/decred/dcrd/chaincfg/chainhash v1.0.1/go.mod h1:OVfvaOsNLS/A1y4Eod0Ip/Lf8qga7VXCQjUQLbkY0Go=
|
||||
github.com/decred/dcrd/dcrjson v1.2.0 h1:3BFFQHq3/YO/zae9WLxQkXsX6AXKx3+M8H3yk4oXZi0=
|
||||
github.com/decred/dcrd/dcrjson/v2 v2.0.0 h1:W0q4Alh36c5N318eUpfmU8kXoCNgImMLI87NIXni9Us=
|
||||
github.com/decred/dcrd/dcrjson/v2 v2.0.0/go.mod h1:FYueNy8BREAFq04YNEwcTsmGFcNqY+ehUUO81w2igi4=
|
||||
10
rpc/jsonrpc/types/helpers.go
Normal file
10
rpc/jsonrpc/types/helpers.go
Normal file
@ -0,0 +1,10 @@
|
||||
package types
|
||||
|
||||
// EstimateSmartFeeModeAddr is a helper routine that allocates a new
|
||||
// EstimateSmartFeeMode value to store v and returns a pointer to it. This is
|
||||
// useful when assigning optional parameters.
|
||||
func EstimateSmartFeeModeAddr(v EstimateSmartFeeMode) *EstimateSmartFeeMode {
|
||||
p := new(EstimateSmartFeeMode)
|
||||
*p = v
|
||||
return p
|
||||
}
|
||||
8
rpc/jsonrpc/types/method.go
Normal file
8
rpc/jsonrpc/types/method.go
Normal file
@ -0,0 +1,8 @@
|
||||
// Copyright (c) 2019 The Decred developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package types
|
||||
|
||||
// Method is the type used to register method and parameter pairs with dcrjson.
|
||||
type Method string
|
||||
403
rpcserver.go
403
rpcserver.go
File diff suppressed because it is too large
Load Diff
109
rpcserverhelp.go
109
rpcserverhelp.go
@ -11,7 +11,8 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/decred/dcrd/dcrjson/v2"
|
||||
"github.com/decred/dcrd/dcrjson/v3"
|
||||
"github.com/decred/dcrd/rpc/jsonrpc/types"
|
||||
)
|
||||
|
||||
// helpDescsEnUS defines the English descriptions used for the help strings.
|
||||
@ -169,14 +170,14 @@ var helpDescsEnUS = map[string]string{
|
||||
"existsaddresses--result0": "Bitset of bools showing if addresses exist or not",
|
||||
|
||||
// ExitsMissedTicketsCmd help.
|
||||
"existsmissedtickets--synopsis": "Test for the existence of the provided tickets in the missed ticket map",
|
||||
"existsmissedtickets-txhashblob": "Blob containing the hashes to check",
|
||||
"existsmissedtickets--result0": "Bool blob showing if the ticket exists in the missed ticket database or not",
|
||||
"existsmissedtickets--synopsis": "Test for the existence of the provided tickets in the missed ticket map",
|
||||
"existsmissedtickets-txhashes": "Array of hashes to check",
|
||||
"existsmissedtickets--result0": "Bool blob showing if the ticket exists in the missed ticket database or not",
|
||||
|
||||
// ExistsExpiredTicketsCmd help.
|
||||
"existsexpiredtickets--synopsis": "Test for the existence of the provided tickets in the expired ticket map",
|
||||
"existsexpiredtickets-txhashblob": "Blob containing the hashes to check",
|
||||
"existsexpiredtickets--result0": "Bool blob showing if ticket exists in the expired ticket database or not",
|
||||
"existsexpiredtickets--synopsis": "Test for the existence of the provided tickets in the expired ticket map",
|
||||
"existsexpiredtickets-txhashes": "Array of hashes to check",
|
||||
"existsexpiredtickets--result0": "Bool blob showing if ticket exists in the expired ticket database or not",
|
||||
|
||||
// ExistsLiveTicketCmd help.
|
||||
"existsliveticket--synopsis": "Test for the existence of the provided ticket",
|
||||
@ -184,14 +185,14 @@ var helpDescsEnUS = map[string]string{
|
||||
"existsliveticket--result0": "Bool showing if address exists in the live ticket database or not",
|
||||
|
||||
// ExistsLiveTicketsCmd help.
|
||||
"existslivetickets--synopsis": "Test for the existence of the provided tickets in the live ticket map",
|
||||
"existslivetickets-txhashblob": "Blob containing the hashes to check",
|
||||
"existslivetickets--result0": "Bool blob showing if ticket exists in the live ticket database or not",
|
||||
"existslivetickets--synopsis": "Test for the existence of the provided tickets in the live ticket map",
|
||||
"existslivetickets-txhashes": "Array of hashes to check",
|
||||
"existslivetickets--result0": "Bool blob showing if ticket exists in the live ticket database or not",
|
||||
|
||||
// ExistsMempoolTxsCmd help.
|
||||
"existsmempooltxs--synopsis": "Test for the existence of the provided txs in the mempool",
|
||||
"existsmempooltxs-txhashblob": "Blob containing the hashes to check",
|
||||
"existsmempooltxs--result0": "Bool blob showing if txs exist in the mempool or not",
|
||||
"existsmempooltxs--synopsis": "Test for the existence of the provided txs in the mempool",
|
||||
"existsmempooltxs-txhashes": "Array of hashes to check",
|
||||
"existsmempooltxs--result0": "Bool blob showing if txs exist in the mempool or not",
|
||||
|
||||
// GenerateCmd help
|
||||
"generate--synopsis": "Generates a set number of blocks (simnet or regtest only) and returns a JSON\n" +
|
||||
@ -571,7 +572,7 @@ var helpDescsEnUS = map[string]string{
|
||||
|
||||
// GetHeadersCmd help.
|
||||
"getheaders--synopsis": "Returns block headers starting with the first known block hash from the request",
|
||||
"getheaders-blocklocators": "Concatenated hashes of blocks. Headers are returned starting from the first known hash in this list",
|
||||
"getheaders-blocklocators": "Array of block locator hashes. Headers are returned starting from the first known hash in this list",
|
||||
"getheaders-hashstop": "Optional block hash to stop including block headers for",
|
||||
"getheadersresult-headers": "Serialized block headers of all located blocks, limited to some arbitrary maximum number of hashes (currently 2000, which matches the wire protocol headers message, but this is not guaranteed)",
|
||||
|
||||
@ -827,7 +828,7 @@ var helpDescsEnUS = map[string]string{
|
||||
|
||||
// Rescan help.
|
||||
"rescan--synopsis": "Rescan blocks for transactions matching the loaded transaction filter.",
|
||||
"rescan-blockhashes": "Concatenated block hashes to rescan. Each next block must be a child of the previous.",
|
||||
"rescan-blockhashes": "Array of block hashes to rescan. Each next block must be a child of the previous.",
|
||||
|
||||
// -------- Decred-specific help --------
|
||||
|
||||
@ -943,17 +944,17 @@ var helpDescsEnUS = map[string]string{
|
||||
// rpcResultTypes specifies the result types that each RPC command can return.
|
||||
// This information is used to generate the help. Each result type must be a
|
||||
// pointer to the type (or nil to indicate no return value).
|
||||
var rpcResultTypes = map[string][]interface{}{
|
||||
var rpcResultTypes = map[types.Method][]interface{}{
|
||||
"addnode": nil,
|
||||
"createrawsstx": {(*string)(nil)},
|
||||
"createrawssrtx": {(*string)(nil)},
|
||||
"createrawtransaction": {(*string)(nil)},
|
||||
"debuglevel": {(*string)(nil), (*string)(nil)},
|
||||
"decoderawtransaction": {(*dcrjson.TxRawDecodeResult)(nil)},
|
||||
"decodescript": {(*dcrjson.DecodeScriptResult)(nil)},
|
||||
"decoderawtransaction": {(*types.TxRawDecodeResult)(nil)},
|
||||
"decodescript": {(*types.DecodeScriptResult)(nil)},
|
||||
"estimatefee": {(*float64)(nil)},
|
||||
"estimatesmartfee": {(*float64)(nil)},
|
||||
"estimatestakediff": {(*dcrjson.EstimateStakeDiffResult)(nil)},
|
||||
"estimatestakediff": {(*types.EstimateStakeDiffResult)(nil)},
|
||||
"existsaddress": {(*bool)(nil)},
|
||||
"existsaddresses": {(*string)(nil)},
|
||||
"existsmissedtickets": {(*string)(nil)},
|
||||
@ -961,66 +962,66 @@ var rpcResultTypes = map[string][]interface{}{
|
||||
"existsliveticket": {(*bool)(nil)},
|
||||
"existslivetickets": {(*string)(nil)},
|
||||
"existsmempooltxs": {(*string)(nil)},
|
||||
"getaddednodeinfo": {(*[]string)(nil), (*[]dcrjson.GetAddedNodeInfoResult)(nil)},
|
||||
"getbestblock": {(*dcrjson.GetBestBlockResult)(nil)},
|
||||
"getaddednodeinfo": {(*[]string)(nil), (*[]types.GetAddedNodeInfoResult)(nil)},
|
||||
"getbestblock": {(*types.GetBestBlockResult)(nil)},
|
||||
"generate": {(*[]string)(nil)},
|
||||
"getbestblockhash": {(*string)(nil)},
|
||||
"getblock": {(*string)(nil), (*dcrjson.GetBlockVerboseResult)(nil)},
|
||||
"getblockchaininfo": {(*dcrjson.GetBlockChainInfoResult)(nil)},
|
||||
"getblock": {(*string)(nil), (*types.GetBlockVerboseResult)(nil)},
|
||||
"getblockchaininfo": {(*types.GetBlockChainInfoResult)(nil)},
|
||||
"getblockcount": {(*int64)(nil)},
|
||||
"getblockhash": {(*string)(nil)},
|
||||
"getblockheader": {(*string)(nil), (*dcrjson.GetBlockHeaderVerboseResult)(nil)},
|
||||
"getblocksubsidy": {(*dcrjson.GetBlockSubsidyResult)(nil)},
|
||||
"getblocktemplate": {(*dcrjson.GetBlockTemplateResult)(nil), (*string)(nil), nil},
|
||||
"getblockheader": {(*string)(nil), (*types.GetBlockHeaderVerboseResult)(nil)},
|
||||
"getblocksubsidy": {(*types.GetBlockSubsidyResult)(nil)},
|
||||
"getblocktemplate": {(*types.GetBlockTemplateResult)(nil), (*string)(nil), nil},
|
||||
"getcfilter": {(*string)(nil)},
|
||||
"getcfilterheader": {(*string)(nil)},
|
||||
"getchaintips": {(*[]dcrjson.GetChainTipsResult)(nil)},
|
||||
"getchaintips": {(*[]types.GetChainTipsResult)(nil)},
|
||||
"getconnectioncount": {(*int32)(nil)},
|
||||
"getcurrentnet": {(*uint32)(nil)},
|
||||
"getdifficulty": {(*float64)(nil)},
|
||||
"getstakedifficulty": {(*dcrjson.GetStakeDifficultyResult)(nil)},
|
||||
"getstakeversioninfo": {(*dcrjson.GetStakeVersionInfoResult)(nil)},
|
||||
"getstakeversions": {(*dcrjson.GetStakeVersionsResult)(nil)},
|
||||
"getstakedifficulty": {(*types.GetStakeDifficultyResult)(nil)},
|
||||
"getstakeversioninfo": {(*types.GetStakeVersionInfoResult)(nil)},
|
||||
"getstakeversions": {(*types.GetStakeVersionsResult)(nil)},
|
||||
"getgenerate": {(*bool)(nil)},
|
||||
"gethashespersec": {(*float64)(nil)},
|
||||
"getheaders": {(*dcrjson.GetHeadersResult)(nil)},
|
||||
"getinfo": {(*dcrjson.InfoChainResult)(nil)},
|
||||
"getmempoolinfo": {(*dcrjson.GetMempoolInfoResult)(nil)},
|
||||
"getmininginfo": {(*dcrjson.GetMiningInfoResult)(nil)},
|
||||
"getnettotals": {(*dcrjson.GetNetTotalsResult)(nil)},
|
||||
"getheaders": {(*types.GetHeadersResult)(nil)},
|
||||
"getinfo": {(*types.InfoChainResult)(nil)},
|
||||
"getmempoolinfo": {(*types.GetMempoolInfoResult)(nil)},
|
||||
"getmininginfo": {(*types.GetMiningInfoResult)(nil)},
|
||||
"getnettotals": {(*types.GetNetTotalsResult)(nil)},
|
||||
"getnetworkhashps": {(*int64)(nil)},
|
||||
"getpeerinfo": {(*[]dcrjson.GetPeerInfoResult)(nil)},
|
||||
"getrawmempool": {(*[]string)(nil), (*dcrjson.GetRawMempoolVerboseResult)(nil)},
|
||||
"getrawtransaction": {(*string)(nil), (*dcrjson.TxRawResult)(nil)},
|
||||
"getpeerinfo": {(*[]types.GetPeerInfoResult)(nil)},
|
||||
"getrawmempool": {(*[]string)(nil), (*types.GetRawMempoolVerboseResult)(nil)},
|
||||
"getrawtransaction": {(*string)(nil), (*types.TxRawResult)(nil)},
|
||||
"getticketpoolvalue": {(*float64)(nil)},
|
||||
"gettxout": {(*dcrjson.GetTxOutResult)(nil)},
|
||||
"getvoteinfo": {(*dcrjson.GetVoteInfoResult)(nil)},
|
||||
"getwork": {(*dcrjson.GetWorkResult)(nil), (*bool)(nil)},
|
||||
"gettxout": {(*types.GetTxOutResult)(nil)},
|
||||
"getvoteinfo": {(*types.GetVoteInfoResult)(nil)},
|
||||
"getwork": {(*types.GetWorkResult)(nil), (*bool)(nil)},
|
||||
"getcoinsupply": {(*int64)(nil)},
|
||||
"help": {(*string)(nil), (*string)(nil)},
|
||||
"livetickets": {(*dcrjson.LiveTicketsResult)(nil)},
|
||||
"missedtickets": {(*dcrjson.MissedTicketsResult)(nil)},
|
||||
"livetickets": {(*types.LiveTicketsResult)(nil)},
|
||||
"missedtickets": {(*types.MissedTicketsResult)(nil)},
|
||||
"node": nil,
|
||||
"ping": nil,
|
||||
"rebroadcastmissed": nil,
|
||||
"rebroadcastwinners": nil,
|
||||
"searchrawtransactions": {(*string)(nil), (*[]dcrjson.SearchRawTransactionsResult)(nil)},
|
||||
"searchrawtransactions": {(*string)(nil), (*[]types.SearchRawTransactionsResult)(nil)},
|
||||
"sendrawtransaction": {(*string)(nil)},
|
||||
"setgenerate": nil,
|
||||
"stop": {(*string)(nil)},
|
||||
"submitblock": {nil, (*string)(nil)},
|
||||
"ticketfeeinfo": {(*dcrjson.TicketFeeInfoResult)(nil)},
|
||||
"ticketsforaddress": {(*dcrjson.TicketsForAddressResult)(nil)},
|
||||
"ticketfeeinfo": {(*types.TicketFeeInfoResult)(nil)},
|
||||
"ticketsforaddress": {(*types.TicketsForAddressResult)(nil)},
|
||||
"ticketvwap": {(*float64)(nil)},
|
||||
"txfeeinfo": {(*dcrjson.TxFeeInfoResult)(nil)},
|
||||
"validateaddress": {(*dcrjson.ValidateAddressChainResult)(nil)},
|
||||
"txfeeinfo": {(*types.TxFeeInfoResult)(nil)},
|
||||
"validateaddress": {(*types.ValidateAddressChainResult)(nil)},
|
||||
"verifychain": {(*bool)(nil)},
|
||||
"verifymessage": {(*bool)(nil)},
|
||||
"version": {(*map[string]dcrjson.VersionResult)(nil)},
|
||||
"version": {(*map[string]types.VersionResult)(nil)},
|
||||
|
||||
// Websocket commands.
|
||||
"loadtxfilter": nil,
|
||||
"session": {(*dcrjson.SessionResult)(nil)},
|
||||
"session": {(*types.SessionResult)(nil)},
|
||||
"notifywinningtickets": nil,
|
||||
"notifyspentandmissedtickets": nil,
|
||||
"notifynewtickets": nil,
|
||||
@ -1041,13 +1042,13 @@ var rpcResultTypes = map[string][]interface{}{
|
||||
type helpCacher struct {
|
||||
sync.Mutex
|
||||
usage string
|
||||
methodHelp map[string]string
|
||||
methodHelp map[types.Method]string
|
||||
}
|
||||
|
||||
// rpcMethodHelp returns an RPC help string for the provided method.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (c *helpCacher) rpcMethodHelp(method string) (string, error) {
|
||||
func (c *helpCacher) rpcMethodHelp(method types.Method) (string, error) {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
|
||||
@ -1060,7 +1061,7 @@ func (c *helpCacher) rpcMethodHelp(method string) (string, error) {
|
||||
resultTypes, ok := rpcResultTypes[method]
|
||||
if !ok {
|
||||
return "", errors.New("no result types specified for method " +
|
||||
method)
|
||||
string(method))
|
||||
}
|
||||
|
||||
// Generate, cache, and return the help.
|
||||
@ -1114,6 +1115,6 @@ func (c *helpCacher) rpcUsage(includeWebsockets bool) (string, error) {
|
||||
// usage for the RPC server commands and caches the results for future calls.
|
||||
func newHelpCacher() *helpCacher {
|
||||
return &helpCacher{
|
||||
methodHelp: make(map[string]string),
|
||||
methodHelp: make(map[types.Method]string),
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,8 +25,9 @@ import (
|
||||
"github.com/decred/dcrd/blockchain"
|
||||
"github.com/decred/dcrd/blockchain/stake"
|
||||
"github.com/decred/dcrd/chaincfg/chainhash"
|
||||
"github.com/decred/dcrd/dcrjson/v2"
|
||||
"github.com/decred/dcrd/dcrjson/v3"
|
||||
"github.com/decred/dcrd/dcrutil"
|
||||
"github.com/decred/dcrd/rpc/jsonrpc/types"
|
||||
"github.com/decred/dcrd/txscript"
|
||||
"github.com/decred/dcrd/wire"
|
||||
)
|
||||
@ -60,8 +61,8 @@ type wsCommandHandler func(*wsClient, interface{}) (interface{}, error)
|
||||
// wsHandlers maps RPC command strings to appropriate websocket handler
|
||||
// functions. This is set by init because help references wsHandlers and thus
|
||||
// causes a dependency loop.
|
||||
var wsHandlers map[string]wsCommandHandler
|
||||
var wsHandlersBeforeInit = map[string]wsCommandHandler{
|
||||
var wsHandlers map[types.Method]wsCommandHandler
|
||||
var wsHandlersBeforeInit = map[types.Method]wsCommandHandler{
|
||||
"loadtxfilter": handleLoadTxFilter,
|
||||
"notifyblocks": handleNotifyBlocks,
|
||||
"notifywinningtickets": handleWinningTickets,
|
||||
@ -712,7 +713,7 @@ func (m *wsNotificationManager) notifyBlockConnected(clients map[chan struct{}]*
|
||||
// just accepted, there should be no issues serializing it.
|
||||
panic(err)
|
||||
}
|
||||
ntfn := dcrjson.BlockConnectedNtfn{
|
||||
ntfn := types.BlockConnectedNtfn{
|
||||
Header: hex.EncodeToString(headerBytes),
|
||||
SubscribedTxs: nil, // Set individually for each client
|
||||
}
|
||||
@ -774,7 +775,7 @@ func (*wsNotificationManager) notifyBlockDisconnected(clients map[chan struct{}]
|
||||
// it.
|
||||
panic(err)
|
||||
}
|
||||
ntfn := dcrjson.BlockDisconnectedNtfn{
|
||||
ntfn := types.BlockDisconnectedNtfn{
|
||||
Header: hex.EncodeToString(headerBytes),
|
||||
}
|
||||
marshalledJSON, err := dcrjson.MarshalCmd("1.0", nil, &ntfn)
|
||||
@ -798,7 +799,7 @@ func (m *wsNotificationManager) notifyReorganization(clients map[chan struct{}]*
|
||||
}
|
||||
|
||||
// Notify interested websocket clients about the disconnected block.
|
||||
ntfn := dcrjson.NewReorganizationNtfn(rd.OldHash.String(),
|
||||
ntfn := types.NewReorganizationNtfn(rd.OldHash.String(),
|
||||
int32(rd.OldHeight),
|
||||
rd.NewHash.String(),
|
||||
int32(rd.NewHeight))
|
||||
@ -837,7 +838,7 @@ func (*wsNotificationManager) notifyWinningTickets(
|
||||
}
|
||||
|
||||
// Notify interested websocket clients about the connected block.
|
||||
ntfn := dcrjson.NewWinningTicketsNtfn(wtnd.BlockHash.String(),
|
||||
ntfn := types.NewWinningTicketsNtfn(wtnd.BlockHash.String(),
|
||||
int32(wtnd.BlockHeight), ticketMap)
|
||||
|
||||
marshalledJSON, err := dcrjson.MarshalCmd("1.0", nil, ntfn)
|
||||
@ -877,7 +878,7 @@ func (*wsNotificationManager) notifySpentAndMissedTickets(clients map[chan struc
|
||||
}
|
||||
|
||||
// Notify interested websocket clients about the connected block.
|
||||
ntfn := dcrjson.NewSpentAndMissedTicketsNtfn(tnd.Hash.String(),
|
||||
ntfn := types.NewSpentAndMissedTicketsNtfn(tnd.Hash.String(),
|
||||
int32(tnd.Height), tnd.StakeDifficulty, ticketMap)
|
||||
|
||||
marshalledJSON, err := dcrjson.MarshalCmd("1.0", nil, ntfn)
|
||||
@ -926,7 +927,7 @@ func (*wsNotificationManager) notifyNewTickets(clients map[chan struct{}]*wsClie
|
||||
}
|
||||
|
||||
// Notify interested websocket clients about the connected block.
|
||||
ntfn := dcrjson.NewNewTicketsNtfn(tnd.Hash.String(), int32(tnd.Height),
|
||||
ntfn := types.NewNewTicketsNtfn(tnd.Hash.String(), int32(tnd.Height),
|
||||
tnd.StakeDifficulty, tickets)
|
||||
|
||||
marshalledJSON, err := dcrjson.MarshalCmd("1.0", nil, ntfn)
|
||||
@ -944,7 +945,7 @@ func (*wsNotificationManager) notifyNewTickets(clients map[chan struct{}]*wsClie
|
||||
// maturing ticket updates.
|
||||
func (*wsNotificationManager) notifyStakeDifficulty(clients map[chan struct{}]*wsClient, sdnd *StakeDifficultyNtfnData) {
|
||||
// Notify interested websocket clients about the connected block.
|
||||
ntfn := dcrjson.NewStakeDifficultyNtfn(sdnd.BlockHash.String(),
|
||||
ntfn := types.NewStakeDifficultyNtfn(sdnd.BlockHash.String(),
|
||||
int32(sdnd.BlockHeight),
|
||||
sdnd.StakeDifficulty)
|
||||
|
||||
@ -982,7 +983,7 @@ func (m *wsNotificationManager) notifyForNewTx(clients map[chan struct{}]*wsClie
|
||||
amount += txOut.Value
|
||||
}
|
||||
|
||||
ntfn := dcrjson.NewTxAcceptedNtfn(txHashStr,
|
||||
ntfn := types.NewTxAcceptedNtfn(txHashStr,
|
||||
dcrutil.Amount(amount).ToCoin())
|
||||
marshalledJSON, err := dcrjson.MarshalCmd("1.0", nil, ntfn)
|
||||
if err != nil {
|
||||
@ -991,7 +992,7 @@ func (m *wsNotificationManager) notifyForNewTx(clients map[chan struct{}]*wsClie
|
||||
return
|
||||
}
|
||||
|
||||
var verboseNtfn *dcrjson.TxAcceptedVerboseNtfn
|
||||
var verboseNtfn *types.TxAcceptedVerboseNtfn
|
||||
var marshalledJSONVerbose []byte
|
||||
for _, wsc := range clients {
|
||||
if wsc.verboseTxUpdates {
|
||||
@ -1007,7 +1008,7 @@ func (m *wsNotificationManager) notifyForNewTx(clients map[chan struct{}]*wsClie
|
||||
return
|
||||
}
|
||||
|
||||
verboseNtfn = dcrjson.NewTxAcceptedVerboseNtfn(*rawTx)
|
||||
verboseNtfn = types.NewTxAcceptedVerboseNtfn(*rawTx)
|
||||
marshalledJSONVerbose, err = dcrjson.MarshalCmd("1.0", nil,
|
||||
verboseNtfn)
|
||||
if err != nil {
|
||||
@ -1087,7 +1088,7 @@ func (m *wsNotificationManager) notifyRelevantTxAccepted(tx *dcrutil.Tx,
|
||||
}
|
||||
|
||||
if len(clientsToNotify) != 0 {
|
||||
n := dcrjson.NewRelevantTxAcceptedNtfn(txHexString(msgTx))
|
||||
n := types.NewRelevantTxAcceptedNtfn(txHexString(msgTx))
|
||||
marshalled, err := dcrjson.MarshalCmd("1.0", nil, n)
|
||||
if err != nil {
|
||||
rpcsLog.Errorf("Failed to marshal notification: %v", err)
|
||||
@ -1307,7 +1308,7 @@ out:
|
||||
// the authenticate request, an authenticate request is received
|
||||
// when the client is already authenticated, or incorrect
|
||||
// authentication credentials are provided in the request.
|
||||
switch authCmd, ok := cmd.cmd.(*dcrjson.AuthenticateCmd); {
|
||||
switch authCmd, ok := cmd.params.(*types.AuthenticateCmd); {
|
||||
case c.authenticated && ok:
|
||||
rpcsLog.Warnf("Websocket client %s is already authenticated",
|
||||
c.addr)
|
||||
@ -1544,7 +1545,7 @@ out:
|
||||
// the authenticate request, an authenticate request is received
|
||||
// when the client is already authenticated, or incorrect
|
||||
// authentication credentials are provided in the request.
|
||||
switch authCmd, ok := cmd.cmd.(*dcrjson.AuthenticateCmd); {
|
||||
switch authCmd, ok := cmd.params.(*types.AuthenticateCmd); {
|
||||
case c.authenticated && ok:
|
||||
rpcsLog.Warnf("Websocket client %s is already authenticated",
|
||||
c.addr)
|
||||
@ -1610,7 +1611,7 @@ out:
|
||||
var resp interface{}
|
||||
wsHandler, ok := wsHandlers[cmd.method]
|
||||
if ok {
|
||||
resp, err = wsHandler(c, cmd.cmd)
|
||||
resp, err = wsHandler(c, cmd.params)
|
||||
} else {
|
||||
resp, err = c.server.standardCmdResult(cmd, nil)
|
||||
}
|
||||
@ -1681,7 +1682,7 @@ func (c *wsClient) serviceRequest(r *parsedRPCCmd) {
|
||||
// exist fallback to handling the command as a standard command.
|
||||
wsHandler, ok := wsHandlers[r.method]
|
||||
if ok {
|
||||
result, err = wsHandler(c, r.cmd)
|
||||
result, err = wsHandler(c, r.params)
|
||||
} else {
|
||||
result, err = c.server.standardCmdResult(r, nil)
|
||||
}
|
||||
@ -1924,18 +1925,18 @@ func newWebsocketClient(server *rpcServer, conn *websocket.Conn,
|
||||
|
||||
// handleWebsocketHelp implements the help command for websocket connections.
|
||||
func handleWebsocketHelp(wsc *wsClient, icmd interface{}) (interface{}, error) {
|
||||
cmd, ok := icmd.(*dcrjson.HelpCmd)
|
||||
cmd, ok := icmd.(*types.HelpCmd)
|
||||
if !ok {
|
||||
return nil, dcrjson.ErrRPCInternal
|
||||
}
|
||||
|
||||
// Provide a usage overview of all commands when no specific command
|
||||
// was specified.
|
||||
var command string
|
||||
var method types.Method
|
||||
if cmd.Command != nil {
|
||||
command = *cmd.Command
|
||||
method = types.Method(*cmd.Command)
|
||||
}
|
||||
if command == "" {
|
||||
if method == "" {
|
||||
usage, err := wsc.server.helpCacher.rpcUsage(true)
|
||||
if err != nil {
|
||||
context := "Failed to generate RPC usage"
|
||||
@ -1947,21 +1948,19 @@ func handleWebsocketHelp(wsc *wsClient, icmd interface{}) (interface{}, error) {
|
||||
// Check that the command asked for is supported and implemented.
|
||||
// Search the list of websocket handlers as well as the main list of
|
||||
// handlers since help should only be provided for those cases.
|
||||
valid := true
|
||||
if _, ok := rpcHandlers[command]; !ok {
|
||||
if _, ok := wsHandlers[command]; !ok {
|
||||
valid = false
|
||||
}
|
||||
_, valid := rpcHandlers[method]
|
||||
if !valid {
|
||||
_, valid = wsHandlers[method]
|
||||
}
|
||||
if !valid {
|
||||
return nil, &dcrjson.RPCError{
|
||||
Code: dcrjson.ErrRPCInvalidParameter,
|
||||
Message: "Unknown command: " + command,
|
||||
Message: "Unknown method: " + string(method),
|
||||
}
|
||||
}
|
||||
|
||||
// Get the help for the command.
|
||||
help, err := wsc.server.helpCacher.rpcMethodHelp(command)
|
||||
help, err := wsc.server.helpCacher.rpcMethodHelp(method)
|
||||
if err != nil {
|
||||
context := "Failed to generate help"
|
||||
return nil, rpcInternalError(err.Error(), context)
|
||||
@ -1972,7 +1971,7 @@ func handleWebsocketHelp(wsc *wsClient, icmd interface{}) (interface{}, error) {
|
||||
// handleLoadTxFilter implements the loadtxfilter command extension for
|
||||
// websocket connections.
|
||||
func handleLoadTxFilter(wsc *wsClient, icmd interface{}) (interface{}, error) {
|
||||
cmd := icmd.(*dcrjson.LoadTxFilterCmd)
|
||||
cmd := icmd.(*types.LoadTxFilterCmd)
|
||||
|
||||
outPoints := make([]*wire.OutPoint, len(cmd.OutPoints))
|
||||
for i := range cmd.OutPoints {
|
||||
@ -2021,7 +2020,7 @@ func handleNotifyBlocks(wsc *wsClient, icmd interface{}) (interface{}, error) {
|
||||
// handleSession implements the session command extension for websocket
|
||||
// connections.
|
||||
func handleSession(wsc *wsClient, icmd interface{}) (interface{}, error) {
|
||||
return &dcrjson.SessionResult{SessionID: wsc.sessionID}, nil
|
||||
return &types.SessionResult{SessionID: wsc.sessionID}, nil
|
||||
}
|
||||
|
||||
// handleWinningTickets implements the notifywinningtickets command
|
||||
@ -2062,7 +2061,7 @@ func handleStopNotifyBlocks(wsc *wsClient, icmd interface{}) (interface{}, error
|
||||
// handleNotifyNewTransations implements the notifynewtransactions command
|
||||
// extension for websocket connections.
|
||||
func handleNotifyNewTransactions(wsc *wsClient, icmd interface{}) (interface{}, error) {
|
||||
cmd, ok := icmd.(*dcrjson.NotifyNewTransactionsCmd)
|
||||
cmd, ok := icmd.(*types.NotifyNewTransactionsCmd)
|
||||
if !ok {
|
||||
return nil, dcrjson.ErrRPCInternal
|
||||
}
|
||||
@ -2165,7 +2164,7 @@ func rescanBlock(filter *wsClientFilter, block *dcrutil.Block) []string {
|
||||
// handleRescan implements the rescan command extension for websocket
|
||||
// connections.
|
||||
func handleRescan(wsc *wsClient, icmd interface{}) (interface{}, error) {
|
||||
cmd, ok := icmd.(*dcrjson.RescanCmd)
|
||||
cmd, ok := icmd.(*types.RescanCmd)
|
||||
if !ok {
|
||||
return nil, dcrjson.ErrRPCInternal
|
||||
}
|
||||
@ -2181,12 +2180,12 @@ func handleRescan(wsc *wsClient, icmd interface{}) (interface{}, error) {
|
||||
}
|
||||
}
|
||||
|
||||
blockHashes, err := dcrjson.DecodeConcatenatedHashes(cmd.BlockHashes)
|
||||
blockHashes, err := decodeHashes(cmd.BlockHashes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
discoveredData := make([]dcrjson.RescannedBlock, 0, len(blockHashes))
|
||||
discoveredData := make([]types.RescannedBlock, 0, len(blockHashes))
|
||||
|
||||
// Iterate over each block in the request and rescan. When a block
|
||||
// contains relevant transactions, add it to the response.
|
||||
@ -2211,14 +2210,14 @@ func handleRescan(wsc *wsClient, icmd interface{}) (interface{}, error) {
|
||||
|
||||
transactions := rescanBlock(filter, block)
|
||||
if len(transactions) != 0 {
|
||||
discoveredData = append(discoveredData, dcrjson.RescannedBlock{
|
||||
discoveredData = append(discoveredData, types.RescannedBlock{
|
||||
Hash: blockHashes[i].String(),
|
||||
Transactions: transactions,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return &dcrjson.RescanResult{DiscoveredData: discoveredData}, nil
|
||||
return &types.RescanResult{DiscoveredData: discoveredData}, nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user