From b69302960fbfd241a6d40caf7486541a84a16cb3 Mon Sep 17 00:00:00 2001 From: Donald Adu-Poku Date: Wed, 14 Aug 2019 15:16:34 +0000 Subject: [PATCH] multi: add getnetworkinfo rpc. --- addrmgr/addrmanager.go | 28 +++++++++++++++++- docs/json_rpc_api.mediawiki | 43 ++++++++++++++++++++++++++++ rpc/jsonrpc/types/chainsvrresults.go | 2 ++ rpcserver.go | 32 ++++++++++++++++++++- rpcserverhelp.go | 27 +++++++++++++++++ 5 files changed, 130 insertions(+), 2 deletions(-) diff --git a/addrmgr/addrmanager.go b/addrmgr/addrmanager.go index 2487ae53..cf97a905 100644 --- a/addrmgr/addrmanager.go +++ b/addrmgr/addrmanager.go @@ -74,6 +74,13 @@ type localAddress struct { score AddressPriority } +// LocalAddr represents network address information for a local address. +type LocalAddr struct { + Address string + Port uint16 + Score int32 +} + // AddressPriority type is used to describe the hierarchy of local address // discovery methods. type AddressPriority int @@ -536,7 +543,7 @@ func (a *AddrManager) deserializePeers(filePath string) error { if v.refs > 0 && v.tried { return fmt.Errorf("address %s after serialisation "+ - "which is both new and tried!", k) + "which is both new and tried", k) } } @@ -1022,6 +1029,25 @@ func (a *AddrManager) HasLocalAddress(na *wire.NetAddress) bool { return ok } +// FetchLocalAddresses fetches a summary of local addresses information for +// the getnetworkinfo rpc. +func (a *AddrManager) FetchLocalAddresses() []LocalAddr { + a.lamtx.Lock() + defer a.lamtx.Unlock() + + addrs := make([]LocalAddr, 0, len(a.localAddresses)) + for _, addr := range a.localAddresses { + la := LocalAddr{ + Address: addr.na.IP.String(), + Port: addr.na.Port, + } + + addrs = append(addrs, la) + } + + return addrs +} + const ( // Unreachable represents a publicly unreachable connection state // between two addresses. diff --git a/docs/json_rpc_api.mediawiki b/docs/json_rpc_api.mediawiki index 033fba88..196bd05d 100644 --- a/docs/json_rpc_api.mediawiki +++ b/docs/json_rpc_api.mediawiki @@ -202,6 +202,10 @@ the method name for further details such as parameter and return information. |Y |Returns the estimated network hashes per second for the block heights provided by the parameters. |- +|[[#getnetworkinfo|getnetworkinfo]] +|Y +|Returns a JSON object containing network-related information. +|- |[[#getpeerinfo|getpeerinfo]] |N |Returns information about each connected network peer as an array of json objects. @@ -950,6 +954,45 @@ the method name for further details such as parameter and return information. ---- +====getnetworkinfo==== +{| +!Method +|getnetworkinfo +|- +!Parameters +|None +|- +!Description +|Returns a JSON object containing network-related information. +|- +!Returns +|(json object) +: address: (string) The local address being listened on. +: port: (numeric) The port being listened on for the associated local address. +: score: (numeric) Reserved. +: name: (string) The name of the network interface. +: limited: (boolean) True if only connections to the network are allowed. +: proxy: (string) The proxy set for the network. +: proxyrandomizecredentials: (boolean) True if randomized credentials are set for the proxy. +: reachable: (boolean) True if connections can be made to or from the network. +: version: (numeric) The version of the node as a numeric. +: subversion: (string) The subversion of the node, as advertised to peers. +: protocolversion: (numeric) The protocol version of the node. +: timeoffset: (numeric) The node clock offset in seconds. +: connections: (numeric) The total number of open connections for the node. +: networks: (json array) An array of objects describing IPV4, IPV6 and Onion network interface states. +: relayfee: (numeric) The minimum required transaction fee for the node. +: localaddresses: (json array) An array of objects describing local addresses being listened on by the node. +: localservices: (string) The services supported by the node, as advertised in its version message. + +{"version": n, "subversion": "major.minor.patch", "protocolversion": n, "timeoffset": n, "connections": n, "networks": [{"name": "network", "limited": true or false, "reachable": true or false, "proxy": "host:port","proxyrandomizecredentials": true or false }, ...], "relayfee": n.nn., "localaddresses": [{ "address": "ip", "port": n, "score": n }, ...], "localservices": "services"} +|- +!Example Return +|{"version": 1050000, "subversion": "1.5.0", "protocolversion": 6, "timeoffset": 0, "connections": 4, "networks": [{"name": "IPV4", "limited": true, "reachable": true, "proxy": "127.0.0.1:9050", "proxyrandomizecredentials": false}, {"name": "IPV6", "limited": false, "reachable": false, "proxy": "", "proxyrandomizecredentials": false}, {"name": "Onion", "limited": false, "reachable": false, "proxy": "", "proxyrandomizecredentials": false}], "relayfee": 0.0001, "localaddresses": [{"address": "fd87:d87e:eb43:d208:593b:4305:c8e5:2e77", "port": 9108, "score": 0}], "localservices": "0000000000000005"} +|} + +---- + ====getpeerinfo==== {| !Method diff --git a/rpc/jsonrpc/types/chainsvrresults.go b/rpc/jsonrpc/types/chainsvrresults.go index 010c448f..1cc268ee 100644 --- a/rpc/jsonrpc/types/chainsvrresults.go +++ b/rpc/jsonrpc/types/chainsvrresults.go @@ -287,12 +287,14 @@ type NetworksResult struct { // command. type GetNetworkInfoResult struct { Version int32 `json:"version"` + SubVersion string `json:"subversion"` ProtocolVersion int32 `json:"protocolversion"` TimeOffset int64 `json:"timeoffset"` Connections int32 `json:"connections"` Networks []NetworksResult `json:"networks"` RelayFee float64 `json:"relayfee"` LocalAddresses []LocalAddressesResult `json:"localaddresses"` + LocalServices string `json:"localservices"` } // GetNetTotalsResult models the data returned from the getnettotals command. diff --git a/rpcserver.go b/rpcserver.go index 000e006c..9e53efba 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -210,6 +210,7 @@ var rpcHandlersBeforeInit = map[types.Method]commandHandler{ "getmininginfo": handleGetMiningInfo, "getnettotals": handleGetNetTotals, "getnetworkhashps": handleGetNetworkHashPS, + "getnetworkinfo": handleGetNetworkInfo, "getpeerinfo": handleGetPeerInfo, "getrawmempool": handleGetRawMempool, "getrawtransaction": handleGetRawTransaction, @@ -299,7 +300,6 @@ var rpcAskWallet = map[string]struct{}{ var rpcUnimplemented = map[string]struct{}{ "estimatepriority": {}, "getblocktemplate": {}, - "getnetworkinfo": {}, } // Commands that are available to a limited user @@ -331,6 +331,7 @@ var rpcLimited = map[string]struct{}{ "getinfo": {}, "getnettotals": {}, "getnetworkhashps": {}, + "getnetworkinfo": {}, "getrawmempool": {}, "getrawtransaction": {}, "gettxout": {}, @@ -3359,6 +3360,35 @@ func handleGetNetworkHashPS(s *rpcServer, cmd interface{}, closeChan <-chan stru return hashesPerSec.Int64(), nil } +// handleGetNetworkInfo implements the getnetworkinfo command. +func handleGetNetworkInfo(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { + networks := cfg.generateNetworkInfo() + lAddrs := s.server.addrManager.FetchLocalAddresses() + localAddrs := make([]types.LocalAddressesResult, len(lAddrs)) + for idx, entry := range lAddrs { + addr := types.LocalAddressesResult{ + Address: entry.Address, + Port: entry.Port, + } + localAddrs[idx] = addr + } + + info := types.GetNetworkInfoResult{ + Version: int32(1000000*version.Major + 10000*version.Minor + + 100*version.Patch), + SubVersion: userAgentVersion, + ProtocolVersion: int32(maxProtocolVersion), + TimeOffset: int64(s.server.timeSource.Offset().Seconds()), + Connections: s.server.ConnectedCount(), + RelayFee: cfg.minRelayTxFee.ToCoin(), + Networks: networks, + LocalAddresses: localAddrs, + LocalServices: fmt.Sprintf("%016x", uint64(s.server.services)), + } + + return info, nil +} + // handleGetPeerInfo implements the getpeerinfo command. func handleGetPeerInfo(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { peers := s.server.Peers() diff --git a/rpcserverhelp.go b/rpcserverhelp.go index 654c6d86..4a155a96 100644 --- a/rpcserverhelp.go +++ b/rpcserverhelp.go @@ -609,6 +609,32 @@ var helpDescsEnUS = map[string]string{ "getnetworkhashps-height": "Perform estimate ending with this height or -1 for current best chain block height", "getnetworkhashps--result0": "Estimated hashes per second", + // GetNetworkInfoCmd help. + "getnetworkinfo--synopsis": "Returns a JSON object containing network-related information.", + + // LocalAddressesResult help. + "localaddressesresult-address": "The local address being listened on", + "localaddressesresult-port": "The port being listened on for the associated local address", + "localaddressesresult-score": "Reserved", + + // NetworksResult help. + "networksresult-name": "The name of the network interface", + "networksresult-limited": "True if only connections to the network are allowed", + "networksresult-proxy": "The proxy set for the network", + "networksresult-proxyrandomizecredentials": "True if randomized credentials are set for the proxy", + "networksresult-reachable": "True if connections can be made to or from the network", + + // GetNetworkInfoResult help. + "getnetworkinforesult-version": "The version of the node as a numeric", + "getnetworkinforesult-subversion": "The subversion of the node, as advertised to peers", + "getnetworkinforesult-protocolversion": "The protocol version of the node", + "getnetworkinforesult-timeoffset": "The node clock offset in seconds", + "getnetworkinforesult-connections": "The total number of open connections for the node", + "getnetworkinforesult-networks": "An array of objects describing IPV4, IPV6 and Onion network interface states", + "getnetworkinforesult-relayfee": "The minimum required transaction fee for the node.", + "getnetworkinforesult-localaddresses": "An array of objects describing local addresses being listened on by the node", + "getnetworkinforesult-localservices": "The services supported by the node, as advertised in its version message", + // GetNetTotalsCmd help. "getnettotals--synopsis": "Returns a JSON object containing network traffic statistics.", @@ -990,6 +1016,7 @@ var rpcResultTypes = map[types.Method][]interface{}{ "getmininginfo": {(*types.GetMiningInfoResult)(nil)}, "getnettotals": {(*types.GetNetTotalsResult)(nil)}, "getnetworkhashps": {(*int64)(nil)}, + "getnetworkinfo": {(*[]types.GetNetworkInfoResult)(nil)}, "getpeerinfo": {(*[]types.GetPeerInfoResult)(nil)}, "getrawmempool": {(*[]string)(nil), (*types.GetRawMempoolVerboseResult)(nil)}, "getrawtransaction": {(*string)(nil), (*types.TxRawResult)(nil)},