From 8e4b78998e71ce31bdfa501b0dcbeec7a5814ab0 Mon Sep 17 00:00:00 2001 From: Josh Rickmar Date: Wed, 5 Oct 2016 18:46:06 -0400 Subject: [PATCH] Version the JSON-RPC API with semantic versioning. (#387) Start at version 1.0.0. --- dcrjson/dcrdextcmds.go | 8 ++++++++ dcrjson/dcrdextresults.go | 11 +++++++++++ rpcserver.go | 23 +++++++++++++++++++++++ rpcserverhelp.go | 7 +++++++ 4 files changed, 49 insertions(+) diff --git a/dcrjson/dcrdextcmds.go b/dcrjson/dcrdextcmds.go index fc7b6bb9..c9601a9d 100644 --- a/dcrjson/dcrdextcmds.go +++ b/dcrjson/dcrdextcmds.go @@ -210,6 +210,13 @@ func NewTxFeeInfoCmd(blocks *uint32, start *uint32, end *uint32) *TxFeeInfoCmd { } } +// VersionCmd defines the version JSON-RPC command. +type VersionCmd struct{} + +// NewVersionCmd returns a new instance which can be used to issue a JSON-RPC +// version command. +func NewVersionCmd() *VersionCmd { return new(VersionCmd) } + func init() { // No special flags for commands in this file. flags := UsageFlag(0) @@ -231,4 +238,5 @@ func init() { MustRegisterCmd("ticketsforaddress", (*TicketsForAddressCmd)(nil), flags) MustRegisterCmd("ticketvwap", (*TicketVWAPCmd)(nil), flags) MustRegisterCmd("txfeeinfo", (*TxFeeInfoCmd)(nil), flags) + MustRegisterCmd("version", (*VersionCmd)(nil), flags) } diff --git a/dcrjson/dcrdextresults.go b/dcrjson/dcrdextresults.go index 59c6481d..6688475b 100644 --- a/dcrjson/dcrdextresults.go +++ b/dcrjson/dcrdextresults.go @@ -103,3 +103,14 @@ type TxFeeInfoResult struct { FeeInfoBlocks []FeeInfoBlock `json:"feeinfoblocks"` FeeInfoRange FeeInfoRange `json:"feeinforange"` } + +// VersionResult models objects included in the version response. In the actual +// result, these objects are keyed by the program or API name. +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/rpcserver.go b/rpcserver.go index f672bd48..0d24c30c 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -49,6 +49,14 @@ import ( "github.com/decred/dcrutil" ) +// 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 @@ -227,6 +235,7 @@ var rpcHandlersBeforeInit = map[string]commandHandler{ "validateaddress": handleValidateAddress, "verifychain": handleVerifyChain, "verifymessage": handleVerifyMessage, + "version": handleVersion, } // list of commands that we recognize, but for which dcrd has no support because @@ -331,6 +340,7 @@ var rpcLimited = map[string]struct{}{ "submitblock": {}, "validateaddress": {}, "verifymessage": {}, + "version": {}, } // builderScript is a convenience function which is used for hard-coded scripts @@ -5705,6 +5715,19 @@ func handleVerifyMessage(s *rpcServer, cmd interface{}, closeChan <-chan struct{ return address.EncodeAddress() == c.Address, nil } +// handleVersion implements the version command. +func handleVersion(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { + result := map[string]dcrjson.VersionResult{ + "dcrdjsonrpcapi": { + 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 4d923239..388920a7 100644 --- a/rpcserverhelp.go +++ b/rpcserverhelp.go @@ -806,6 +806,12 @@ var helpDescsEnUS = map[string]string{ "feeinforange-mean": "Mean of transaction fees in the window", "feeinforange-median": "Median of transaction fees in the window", "feeinforange-stddev": "Standard deviation of transaction fees in the window", + + // 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", } // rpcResultTypes specifies the result types that each RPC command can return. @@ -873,6 +879,7 @@ var rpcResultTypes = map[string][]interface{}{ "validateaddress": {(*dcrjson.ValidateAddressChainResult)(nil)}, "verifychain": {(*bool)(nil)}, "verifymessage": {(*bool)(nil)}, + "version": {(*map[string]dcrjson.VersionResult)(nil)}, // Websocket commands. "session": {(*dcrjson.SessionResult)(nil)},