diff --git a/LICENSE b/LICENSE
index 49de9195..684c6004 100644
--- a/LICENSE
+++ b/LICENSE
@@ -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
diff --git a/btcjson/btcdextcmds.go b/btcjson/btcdextcmds.go
index 7d416395..25af8d21 100644
--- a/btcjson/btcdextcmds.go
+++ b/btcjson/btcdextcmds.go
@@ -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)
}
diff --git a/btcjson/btcdextcmds_test.go b/btcjson/btcdextcmds_test.go
index c4d8d498..1d87f7c4 100644
--- a/btcjson/btcdextcmds_test.go
+++ b/btcjson/btcdextcmds_test.go
@@ -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))
diff --git a/btcjson/btcdextresults.go b/btcjson/btcdextresults.go
new file mode 100644
index 00000000..86cda258
--- /dev/null
+++ b/btcjson/btcdextresults.go
@@ -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"`
+}
diff --git a/btcjson/btcdextresults_test.go b/btcjson/btcdextresults_test.go
new file mode 100644
index 00000000..c4d7462b
--- /dev/null
+++ b/btcjson/btcdextresults_test.go
@@ -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
+ }
+ }
+}
diff --git a/docs/json_rpc_api.md b/docs/json_rpc_api.md
index 103f4ce1..27d36caf 100644
--- a/docs/json_rpc_api.md
+++ b/docs/json_rpc_api.md
@@ -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.|
@@ -664,6 +665,19 @@ The following is an overview of the RPC methods which are implemented by btcd, b
***
+
+
+| | |
+|---|---|
+|Method|version|
+|Parameters|None|
+|Description|Returns the version of the JSON-RPC API built into this release of btcd.|
+|Returns|`{ (json object)`
`"btcdjsonrpcapi": {`
`"versionstring": "x.y.z", (string) the version of the JSON-RPC API`
`"major": x, (numeric) the major version of the JSON-RPC API`
`"minor": y, (numeric) the minor version of the JSON-RPC API`
`"patch": z, (numeric) the patch version of the JSON-RPC API`
`"prerelease": "", (string) prerelease info for the JSON-RPC API`
`"buildmetadata": "" (string) metadata about the server build`
`}`
`}`|
+|Example Return|`{`
`"btcdjsonrpcapi": {`
`"versionstring": "1.0.0",`
`"major": 1, `
`"minor": 0,`
`"patch": 0,`
`"prerelease": "",`
`"buildmetadata": ""`
`}`
`}`|
+[Return to Overview](#MethodOverview)
+
+***
+
### 7. Websocket Extension Methods (Websocket-specific)
diff --git a/rpcserver.go b/rpcserver.go
index 77bc7f08..c34af5c1 100644
--- a/rpcserver.go
+++ b/rpcserver.go
@@ -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 {
diff --git a/rpcserverhelp.go b/rpcserverhelp.go
index 213f3cd6..80dfb3a5 100644
--- a/rpcserverhelp.go
+++ b/rpcserverhelp.go
@@ -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)},