1 // Copyright (c) 2009-2014 The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
7 #include "clientversion.h"
17 #include <boost/foreach.hpp>
19 #include "json/json_spirit_value.h"
21 using namespace json_spirit;
24 Value getconnectioncount(const Array& params, bool fHelp)
26 if (fHelp || params.size() != 0)
28 "getconnectioncount\n"
29 "\nReturns the number of connections to other nodes.\n"
31 "n (numeric) The connection count\n"
33 + HelpExampleCli("getconnectioncount", "")
34 + HelpExampleRpc("getconnectioncount", "")
37 LOCK2(cs_main, cs_vNodes);
39 return (int)vNodes.size();
42 Value ping(const Array& params, bool fHelp)
44 if (fHelp || params.size() != 0)
47 "\nRequests that a ping be sent to all other nodes, to measure ping time.\n"
48 "Results provided in getpeerinfo, pingtime and pingwait fields are decimal seconds.\n"
49 "Ping command is handled in queue with all other commands, so it measures processing backlog, not just network ping.\n"
51 + HelpExampleCli("ping", "")
52 + HelpExampleRpc("ping", "")
55 // Request that each node send a ping during next message processing pass
56 LOCK2(cs_main, cs_vNodes);
58 BOOST_FOREACH(CNode* pNode, vNodes) {
59 pNode->fPingQueued = true;
65 static void CopyNodeStats(std::vector<CNodeStats>& vstats)
70 vstats.reserve(vNodes.size());
71 BOOST_FOREACH(CNode* pnode, vNodes) {
73 pnode->copyStats(stats);
74 vstats.push_back(stats);
78 Value getpeerinfo(const Array& params, bool fHelp)
80 if (fHelp || params.size() != 0)
83 "\nReturns data about each connected network node as a json array of objects.\n"
87 " \"id\": n, (numeric) Peer index\n"
88 " \"addr\":\"host:port\", (string) The ip address and port of the peer\n"
89 " \"addrlocal\":\"ip:port\", (string) local address\n"
90 " \"services\":\"xxxxxxxxxxxxxxxx\", (string) The services offered\n"
91 " \"lastsend\": ttt, (numeric) The time in seconds since epoch (Jan 1 1970 GMT) of the last send\n"
92 " \"lastrecv\": ttt, (numeric) The time in seconds since epoch (Jan 1 1970 GMT) of the last receive\n"
93 " \"bytessent\": n, (numeric) The total bytes sent\n"
94 " \"bytesrecv\": n, (numeric) The total bytes received\n"
95 " \"conntime\": ttt, (numeric) The connection time in seconds since epoch (Jan 1 1970 GMT)\n"
96 " \"timeoffset\": ttt, (numeric) The time offset in seconds\n"
97 " \"pingtime\": n, (numeric) ping time\n"
98 " \"pingwait\": n, (numeric) ping wait\n"
99 " \"version\": v, (numeric) The peer version, such as 170002\n"
100 " \"subver\": \"/MagicBean:x.y.z[-v]/\", (string) The string version\n"
101 " \"inbound\": true|false, (boolean) Inbound (true) or Outbound (false)\n"
102 " \"startingheight\": n, (numeric) The starting height (block) of the peer\n"
103 " \"banscore\": n, (numeric) The ban score\n"
104 " \"synced_headers\": n, (numeric) The last header we have in common with this peer\n"
105 " \"synced_blocks\": n, (numeric) The last block we have in common with this peer\n"
107 " n, (numeric) The heights of blocks we're currently asking from this peer\n"
114 + HelpExampleCli("getpeerinfo", "")
115 + HelpExampleRpc("getpeerinfo", "")
120 vector<CNodeStats> vstats;
121 CopyNodeStats(vstats);
125 BOOST_FOREACH(const CNodeStats& stats, vstats) {
127 CNodeStateStats statestats;
128 bool fStateStats = GetNodeStateStats(stats.nodeid, statestats);
129 obj.push_back(Pair("id", stats.nodeid));
130 obj.push_back(Pair("addr", stats.addrName));
131 if (!(stats.addrLocal.empty()))
132 obj.push_back(Pair("addrlocal", stats.addrLocal));
133 obj.push_back(Pair("services", strprintf("%016x", stats.nServices)));
134 obj.push_back(Pair("lastsend", stats.nLastSend));
135 obj.push_back(Pair("lastrecv", stats.nLastRecv));
136 obj.push_back(Pair("bytessent", stats.nSendBytes));
137 obj.push_back(Pair("bytesrecv", stats.nRecvBytes));
138 obj.push_back(Pair("conntime", stats.nTimeConnected));
139 obj.push_back(Pair("timeoffset", stats.nTimeOffset));
140 obj.push_back(Pair("pingtime", stats.dPingTime));
141 if (stats.dPingWait > 0.0)
142 obj.push_back(Pair("pingwait", stats.dPingWait));
143 obj.push_back(Pair("version", stats.nVersion));
144 // Use the sanitized form of subver here, to avoid tricksy remote peers from
145 // corrupting or modifiying the JSON output by putting special characters in
146 // their ver message.
147 obj.push_back(Pair("subver", stats.cleanSubVer));
148 obj.push_back(Pair("inbound", stats.fInbound));
149 obj.push_back(Pair("startingheight", stats.nStartingHeight));
151 obj.push_back(Pair("banscore", statestats.nMisbehavior));
152 obj.push_back(Pair("synced_headers", statestats.nSyncHeight));
153 obj.push_back(Pair("synced_blocks", statestats.nCommonHeight));
155 BOOST_FOREACH(int height, statestats.vHeightInFlight) {
156 heights.push_back(height);
158 obj.push_back(Pair("inflight", heights));
160 obj.push_back(Pair("whitelisted", stats.fWhitelisted));
168 int32_t komodo_longestchain()
170 int32_t ht,n=0,num=0,maxheight=0,height = 0;
172 vector<CNodeStats> vstats;
173 CopyNodeStats(vstats);
174 BOOST_FOREACH(const CNodeStats& stats, vstats)
176 CNodeStateStats statestats;
177 bool fStateStats = GetNodeStateStats(stats.nodeid,statestats);
179 if ( stats.nStartingHeight > ht )
180 ht = stats.nStartingHeight;
181 if ( statestats.nSyncHeight > ht )
182 ht = statestats.nSyncHeight;
183 if ( statestats.nCommonHeight > ht )
184 ht = statestats.nCommonHeight;
185 if ( maxheight == 0 || ht > maxheight*1.01 )
186 maxheight = ht, num = 1;
187 else if ( ht > maxheight*0.99 )
193 if ( num > (n >> 1) )
198 Value addnode(const Array& params, bool fHelp)
201 if (params.size() == 2)
202 strCommand = params[1].get_str();
203 if (fHelp || params.size() != 2 ||
204 (strCommand != "onetry" && strCommand != "add" && strCommand != "remove"))
206 "addnode \"node\" \"add|remove|onetry\"\n"
207 "\nAttempts add or remove a node from the addnode list.\n"
208 "Or try a connection to a node once.\n"
210 "1. \"node\" (string, required) The node (see getpeerinfo for nodes)\n"
211 "2. \"command\" (string, required) 'add' to add a node to the list, 'remove' to remove a node from the list, 'onetry' to try a connection to the node once\n"
213 + HelpExampleCli("addnode", "\"192.168.0.6:8233\" \"onetry\"")
214 + HelpExampleRpc("addnode", "\"192.168.0.6:8233\", \"onetry\"")
217 string strNode = params[0].get_str();
219 if (strCommand == "onetry")
222 OpenNetworkConnection(addr, NULL, strNode.c_str());
226 LOCK(cs_vAddedNodes);
227 vector<string>::iterator it = vAddedNodes.begin();
228 for(; it != vAddedNodes.end(); it++)
232 if (strCommand == "add")
234 if (it != vAddedNodes.end())
235 throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: Node already added");
236 vAddedNodes.push_back(strNode);
238 else if(strCommand == "remove")
240 if (it == vAddedNodes.end())
241 throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node has not been added.");
242 vAddedNodes.erase(it);
248 Value getaddednodeinfo(const Array& params, bool fHelp)
250 if (fHelp || params.size() < 1 || params.size() > 2)
252 "getaddednodeinfo dns ( \"node\" )\n"
253 "\nReturns information about the given added node, or all added nodes\n"
254 "(note that onetry addnodes are not listed here)\n"
255 "If dns is false, only a list of added nodes will be provided,\n"
256 "otherwise connected information will also be available.\n"
258 "1. dns (boolean, required) If false, only a list of added nodes will be provided, otherwise connected information will also be available.\n"
259 "2. \"node\" (string, optional) If provided, return information about this specific node, otherwise all nodes are returned.\n"
263 " \"addednode\" : \"192.168.0.201\", (string) The node ip address\n"
264 " \"connected\" : true|false, (boolean) If connected\n"
265 " \"addresses\" : [\n"
267 " \"address\" : \"192.168.0.201:8233\", (string) The bitcoin server host and port\n"
268 " \"connected\" : \"outbound\" (string) connection, inbound or outbound\n"
276 + HelpExampleCli("getaddednodeinfo", "true")
277 + HelpExampleCli("getaddednodeinfo", "true \"192.168.0.201\"")
278 + HelpExampleRpc("getaddednodeinfo", "true, \"192.168.0.201\"")
281 bool fDns = params[0].get_bool();
283 list<string> laddedNodes(0);
284 if (params.size() == 1)
286 LOCK(cs_vAddedNodes);
287 BOOST_FOREACH(string& strAddNode, vAddedNodes)
288 laddedNodes.push_back(strAddNode);
292 string strNode = params[1].get_str();
293 LOCK(cs_vAddedNodes);
294 BOOST_FOREACH(string& strAddNode, vAddedNodes)
295 if (strAddNode == strNode)
297 laddedNodes.push_back(strAddNode);
300 if (laddedNodes.size() == 0)
301 throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node has not been added.");
307 BOOST_FOREACH(string& strAddNode, laddedNodes)
310 obj.push_back(Pair("addednode", strAddNode));
316 list<pair<string, vector<CService> > > laddedAddreses(0);
317 BOOST_FOREACH(string& strAddNode, laddedNodes)
319 vector<CService> vservNode(0);
320 if(Lookup(strAddNode.c_str(), vservNode, Params().GetDefaultPort(), fNameLookup, 0))
321 laddedAddreses.push_back(make_pair(strAddNode, vservNode));
325 obj.push_back(Pair("addednode", strAddNode));
326 obj.push_back(Pair("connected", false));
328 obj.push_back(Pair("addresses", addresses));
333 for (list<pair<string, vector<CService> > >::iterator it = laddedAddreses.begin(); it != laddedAddreses.end(); it++)
336 obj.push_back(Pair("addednode", it->first));
339 bool fConnected = false;
340 BOOST_FOREACH(CService& addrNode, it->second)
344 node.push_back(Pair("address", addrNode.ToString()));
345 BOOST_FOREACH(CNode* pnode, vNodes)
346 if (pnode->addr == addrNode)
350 node.push_back(Pair("connected", pnode->fInbound ? "inbound" : "outbound"));
354 node.push_back(Pair("connected", "false"));
355 addresses.push_back(node);
357 obj.push_back(Pair("connected", fConnected));
358 obj.push_back(Pair("addresses", addresses));
365 Value getnettotals(const Array& params, bool fHelp)
367 if (fHelp || params.size() > 0)
370 "\nReturns information about network traffic, including bytes in, bytes out,\n"
371 "and current time.\n"
374 " \"totalbytesrecv\": n, (numeric) Total bytes received\n"
375 " \"totalbytessent\": n, (numeric) Total bytes sent\n"
376 " \"timemillis\": t (numeric) Total cpu time\n"
379 + HelpExampleCli("getnettotals", "")
380 + HelpExampleRpc("getnettotals", "")
384 obj.push_back(Pair("totalbytesrecv", CNode::GetTotalBytesRecv()));
385 obj.push_back(Pair("totalbytessent", CNode::GetTotalBytesSent()));
386 obj.push_back(Pair("timemillis", GetTimeMillis()));
390 static Array GetNetworksInfo()
393 for(int n=0; n<NET_MAX; ++n)
395 enum Network network = static_cast<enum Network>(n);
396 if(network == NET_UNROUTABLE)
400 GetProxy(network, proxy);
401 obj.push_back(Pair("name", GetNetworkName(network)));
402 obj.push_back(Pair("limited", IsLimited(network)));
403 obj.push_back(Pair("reachable", IsReachable(network)));
404 obj.push_back(Pair("proxy", proxy.IsValid() ? proxy.proxy.ToStringIPPort() : string()));
405 obj.push_back(Pair("proxy_randomize_credentials", proxy.randomize_credentials));
406 networks.push_back(obj);
411 Value getnetworkinfo(const Array& params, bool fHelp)
413 if (fHelp || params.size() != 0)
416 "Returns an object containing various state info regarding P2P networking.\n"
419 " \"version\": xxxxx, (numeric) the server version\n"
420 " \"subversion\": \"/MagicBean:x.y.z[-v]/\", (string) the server subversion string\n"
421 " \"protocolversion\": xxxxx, (numeric) the protocol version\n"
422 " \"localservices\": \"xxxxxxxxxxxxxxxx\", (string) the services we offer to the network\n"
423 " \"timeoffset\": xxxxx, (numeric) the time offset\n"
424 " \"connections\": xxxxx, (numeric) the number of connections\n"
425 " \"networks\": [ (array) information per network\n"
427 " \"name\": \"xxx\", (string) network (ipv4, ipv6 or onion)\n"
428 " \"limited\": true|false, (boolean) is the network limited using -onlynet?\n"
429 " \"reachable\": true|false, (boolean) is the network reachable?\n"
430 " \"proxy\": \"host:port\" (string) the proxy that is used for this network, or empty if none\n"
434 " \"relayfee\": x.xxxxxxxx, (numeric) minimum relay fee for non-free transactions in btc/kb\n"
435 " \"localaddresses\": [ (array) list of local addresses\n"
437 " \"address\": \"xxxx\", (string) network address\n"
438 " \"port\": xxx, (numeric) network port\n"
439 " \"score\": xxx (numeric) relative score\n"
445 + HelpExampleCli("getnetworkinfo", "")
446 + HelpExampleRpc("getnetworkinfo", "")
452 obj.push_back(Pair("version", CLIENT_VERSION));
453 obj.push_back(Pair("subversion",
454 FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<string>())));
455 obj.push_back(Pair("protocolversion",PROTOCOL_VERSION));
456 obj.push_back(Pair("localservices", strprintf("%016x", nLocalServices)));
457 obj.push_back(Pair("timeoffset", GetTimeOffset()));
458 obj.push_back(Pair("connections", (int)vNodes.size()));
459 obj.push_back(Pair("networks", GetNetworksInfo()));
460 obj.push_back(Pair("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK())));
461 Array localAddresses;
463 LOCK(cs_mapLocalHost);
464 BOOST_FOREACH(const PAIRTYPE(CNetAddr, LocalServiceInfo) &item, mapLocalHost)
467 rec.push_back(Pair("address", item.first.ToString()));
468 rec.push_back(Pair("port", item.second.nPort));
469 rec.push_back(Pair("score", item.second.nScore));
470 localAddresses.push_back(rec);
473 obj.push_back(Pair("localaddresses", localAddresses));