Add version command to JSON-RPC API for API versioning

This commit is contained in:
Alex 2016-12-15 14:10:06 -07:00
parent 602232500e
commit 9f962b60d6
8 changed files with 163 additions and 3 deletions

View file

@ -1,6 +1,7 @@
ISC License
Copyright (c) 2013-2016 The btcsuite developers
Copyright (c) 2015-2016 The Decred developers
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above

View file

@ -1,4 +1,5 @@
// Copyright (c) 2014 The btcsuite developers
// Copyright (c) 2014-2016 The btcsuite developers
// Copyright (c) 2015-2016 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
@ -89,6 +90,19 @@ func NewGetCurrentNetCmd() *GetCurrentNetCmd {
return &GetCurrentNetCmd{}
}
// VersionCmd defines the version JSON-RPC command.
//
// NOTE: This is a btcsuite extension ported from
// github.com/decred/dcrd/dcrjson.
type VersionCmd struct{}
// NewVersionCmd returns a new instance which can be used to issue a JSON-RPC
// version command.
//
// NOTE: This is a btcsuite extension ported from
// github.com/decred/dcrd/dcrjson.
func NewVersionCmd() *VersionCmd { return new(VersionCmd) }
func init() {
// No special flags for commands in this file.
flags := UsageFlag(0)
@ -98,4 +112,5 @@ func init() {
MustRegisterCmd("generate", (*GenerateCmd)(nil), flags)
MustRegisterCmd("getbestblock", (*GetBestBlockCmd)(nil), flags)
MustRegisterCmd("getcurrentnet", (*GetCurrentNetCmd)(nil), flags)
MustRegisterCmd("version", (*VersionCmd)(nil), flags)
}

View file

@ -1,4 +1,5 @@
// Copyright (c) 2014 The btcsuite developers
// Copyright (c) 2014-2016 The btcsuite developers
// Copyright (c) 2015-2016 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
@ -135,6 +136,17 @@ func TestBtcdExtCmds(t *testing.T) {
marshalled: `{"jsonrpc":"1.0","method":"getcurrentnet","params":[],"id":1}`,
unmarshalled: &btcjson.GetCurrentNetCmd{},
},
{
name: "version",
newCmd: func() (interface{}, error) {
return btcjson.NewCmd("version")
},
staticCmd: func() interface{} {
return btcjson.NewVersionCmd()
},
marshalled: `{"jsonrpc":"1.0","method":"version","params":[],"id":1}`,
unmarshalled: &btcjson.VersionCmd{},
},
}
t.Logf("Running %d tests", len(tests))

20
btcjson/btcdextresults.go Normal file
View file

@ -0,0 +1,20 @@
// Copyright (c) 2016 The btcsuite developers
// Copyright (c) 2015-2016 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package btcjson
// VersionResult models objects included in the version response. In the actual
// result, these objects are keyed by the program or API name.
//
// NOTE: This is a btcsuite extension ported from
// github.com/decred/dcrd/dcrjson.
type VersionResult struct {
VersionString string `json:"versionstring"`
Major uint32 `json:"major"`
Minor uint32 `json:"minor"`
Patch uint32 `json:"patch"`
Prerelease string `json:"prerelease"`
BuildMetadata string `json:"buildmetadata"`
}

View file

@ -0,0 +1,55 @@
// Copyright (c) 2016 The btcsuite developers
// Copyright (c) 2015-2016 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package btcjson_test
import (
"encoding/json"
"testing"
"github.com/btcsuite/btcd/btcjson"
)
// TestBtcdExtCustomResults ensures any results that have custom marshalling
// work as inteded.
// and unmarshal code of results are as expected.
func TestBtcdExtCustomResults(t *testing.T) {
t.Parallel()
tests := []struct {
name string
result interface{}
expected string
}{
{
name: "versionresult",
result: &btcjson.VersionResult{
VersionString: "1.0.0",
Major: 1,
Minor: 0,
Patch: 0,
Prerelease: "pr",
BuildMetadata: "bm",
},
expected: `{"versionstring":"1.0.0","major":1,"minor":0,"patch":0,"prerelease":"pr","buildmetadata":"bm"}`,
},
}
t.Logf("Running %d tests", len(tests))
for i, test := range tests {
marshalled, err := json.Marshal(test.result)
if err != nil {
t.Errorf("Test #%d (%s) unexpected error: %v", i,
test.name, err)
continue
}
if string(marshalled) != test.expected {
t.Errorf("Test #%d (%s) unexpected marhsalled data - "+
"got %s, want %s", i, test.name, marshalled,
test.expected)
continue
}
}
}

View file

@ -583,6 +583,7 @@ The following is an overview of the RPC methods which are implemented by btcd, b
|4|[searchrawtransactions](#searchrawtransactions)|Y|Query for transactions related to a particular address.|None|
|5|[node](#node)|N|Attempts to add or remove a peer. |None|
|6|[generate](#generate)|N|When in simnet or regtest mode, generate a set number of blocks. |None|
|7|[version](#version)|Y|Returns the JSON-RPC API version.|
<a name="ExtMethodDetails" />
@ -664,6 +665,19 @@ The following is an overview of the RPC methods which are implemented by btcd, b
***
<a name="version"/>
| | |
|---|---|
|Method|version|
|Parameters|None|
|Description|Returns the version of the JSON-RPC API built into this release of btcd.|
|Returns|`{ (json object)`<br />&nbsp;&nbsp;`"btcdjsonrpcapi": {`<br />&nbsp;&nbsp;&nbsp;&nbsp;`"versionstring": "x.y.z", (string) the version of the JSON-RPC API`<br />&nbsp;&nbsp;&nbsp;&nbsp;`"major": x, (numeric) the major version of the JSON-RPC API`<br />&nbsp;&nbsp;&nbsp;&nbsp;`"minor": y, (numeric) the minor version of the JSON-RPC API`<br />&nbsp;&nbsp;&nbsp;&nbsp;`"patch": z, (numeric) the patch version of the JSON-RPC API`<br />&nbsp;&nbsp;&nbsp;&nbsp;`"prerelease": "", (string) prerelease info for the JSON-RPC API`<br />&nbsp;&nbsp;&nbsp;&nbsp;`"buildmetadata": "" (string) metadata about the server build`<br />&nbsp;&nbsp;`}`<br />`}`|
|Example Return|`{`<br />&nbsp;&nbsp;`"btcdjsonrpcapi": {`<br />&nbsp;&nbsp;&nbsp;&nbsp;`"versionstring": "1.0.0",`<br />&nbsp;&nbsp;&nbsp;&nbsp;`"major": 1, `<br />&nbsp;&nbsp;&nbsp;&nbsp;`"minor": 0,`<br />&nbsp;&nbsp;&nbsp;&nbsp;`"patch": 0,`<br />&nbsp;&nbsp;&nbsp;&nbsp;`"prerelease": "",`<br />&nbsp;&nbsp;&nbsp;&nbsp;`"buildmetadata": ""`<br />&nbsp;&nbsp;`}`<br />`}`|
[Return to Overview](#MethodOverview)<br />
***
<a name="WSExtMethods" />
### 7. Websocket Extension Methods (Websocket-specific)

View file

@ -1,4 +1,5 @@
// Copyright (c) 2013-2016 The btcsuite developers
// Copyright (c) 2015-2016 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
@ -42,6 +43,14 @@ import (
"github.com/btcsuite/websocket"
)
// API version constants
const (
jsonrpcSemverString = "1.0.0"
jsonrpcSemverMajor = 1
jsonrpcSemverMinor = 0
jsonrpcSemverPatch = 0
)
const (
// rpcAuthTimeoutSeconds is the number of seconds a connection to the
// RPC server is allowed to stay open without authenticating before it
@ -175,6 +184,7 @@ var rpcHandlersBeforeInit = map[string]commandHandler{
"validateaddress": handleValidateAddress,
"verifychain": handleVerifyChain,
"verifymessage": handleVerifyMessage,
"version": handleVersion,
}
// list of commands that we recognize, but for which btcd has no support because
@ -271,6 +281,7 @@ var rpcLimited = map[string]struct{}{
"submitblock": {},
"validateaddress": {},
"verifymessage": {},
"version": {},
}
// builderScript is a convenience function which is used for hard-coded scripts
@ -3789,6 +3800,22 @@ func handleVerifyMessage(s *rpcServer, cmd interface{}, closeChan <-chan struct{
return address.EncodeAddress() == c.Address, nil
}
// handleVersion implements the version command.
//
// NOTE: This is a btcsuite extension ported from
// github.com/decred/dcrd.
func handleVersion(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
result := map[string]btcjson.VersionResult{
"btcdjsonrpcapi": {
VersionString: jsonrpcSemverString,
Major: jsonrpcSemverMajor,
Minor: jsonrpcSemverMinor,
Patch: jsonrpcSemverPatch,
},
}
return result, nil
}
// rpcServer holds the items the rpc server may need to access (config,
// shutdown, main server, etc.)
type rpcServer struct {

View file

@ -1,4 +1,5 @@
// Copyright (c) 2015 The btcsuite developers
// Copyright (c) 2015-2016 The btcsuite developers
// Copyright (c) 2015-2016 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
@ -605,6 +606,20 @@ var helpDescsEnUS = map[string]string{
"rescan-addresses": "List of addresses to include in the rescan",
"rescan-outpoints": "List of transaction outpoints to include in the rescan",
"rescan-endblock": "Hash of final block to rescan",
// Version help.
"version--synopsis": "Returns the JSON-RPC API version (semver)",
"version--result0--desc": "Version objects keyed by the program or API name",
"version--result0--key": "Program or API name",
"version--result0--value": "Object containing the semantic version",
// VersionResult help.
"versionresult-versionstring": "The JSON-RPC API version (semver)",
"versionresult-major": "The major component of the JSON-RPC API version",
"versionresult-minor": "The minor component of the JSON-RPC API version",
"versionresult-patch": "The patch component of the JSON-RPC API version",
"versionresult-prerelease": "Prerelease info about the current build",
"versionresult-buildmetadata": "Metadata about the current build",
}
// rpcResultTypes specifies the result types that each RPC command can return.
@ -652,6 +667,7 @@ var rpcResultTypes = map[string][]interface{}{
"validateaddress": {(*btcjson.ValidateAddressChainResult)(nil)},
"verifychain": {(*bool)(nil)},
"verifymessage": {(*bool)(nil)},
"version": {(*map[string]btcjson.VersionResult)(nil)},
// Websocket commands.
"session": {(*btcjson.SessionResult)(nil)},