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"
16 #include "deprecation.h"
18 #include <boost/foreach.hpp>
24 UniValue getconnectioncount(const UniValue& 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 UniValue ping(const UniValue& 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 UniValue getpeerinfo(const UniValue& 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);
123 UniValue ret(UniValue::VARR);
125 BOOST_FOREACH(const CNodeStats& stats, vstats) {
126 UniValue obj(UniValue::VOBJ);
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 modifying 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));
154 UniValue heights(UniValue::VARR);
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;
169 int32_t komodo_longestchain()
171 int32_t ht,n=0,num=0,maxheight=0,height = 0;
173 vector<CNodeStats> vstats;
174 CopyNodeStats(vstats);
175 BOOST_FOREACH(const CNodeStats& stats, vstats)
177 CNodeStateStats statestats;
178 bool fStateStats = GetNodeStateStats(stats.nodeid,statestats);
180 if ( stats.nStartingHeight > ht )
181 ht = stats.nStartingHeight;
182 if ( statestats.nSyncHeight > ht )
183 ht = statestats.nSyncHeight;
184 if ( statestats.nCommonHeight > ht )
185 ht = statestats.nCommonHeight;
186 if ( maxheight == 0 || ht > maxheight*1.01 )
187 maxheight = ht, num = 1;
188 else if ( ht > maxheight*0.99 )
194 if ( num > (n >> 1) )
196 KOMODO_LONGESTCHAIN = height;
199 KOMODO_LONGESTCHAIN = 0;
203 UniValue addnode(const UniValue& params, bool fHelp)
206 if (params.size() == 2)
207 strCommand = params[1].get_str();
208 if (fHelp || params.size() != 2 ||
209 (strCommand != "onetry" && strCommand != "add" && strCommand != "remove"))
211 "addnode \"node\" \"add|remove|onetry\"\n"
212 "\nAttempts add or remove a node from the addnode list.\n"
213 "Or try a connection to a node once.\n"
215 "1. \"node\" (string, required) The node (see getpeerinfo for nodes)\n"
216 "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"
218 + HelpExampleCli("addnode", "\"192.168.0.6:8233\" \"onetry\"")
219 + HelpExampleRpc("addnode", "\"192.168.0.6:8233\", \"onetry\"")
222 string strNode = params[0].get_str();
224 if (strCommand == "onetry")
227 OpenNetworkConnection(addr, NULL, strNode.c_str());
231 LOCK(cs_vAddedNodes);
232 vector<string>::iterator it = vAddedNodes.begin();
233 for(; it != vAddedNodes.end(); it++)
237 if (strCommand == "add")
239 if (it != vAddedNodes.end())
240 throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: Node already added");
241 vAddedNodes.push_back(strNode);
243 else if(strCommand == "remove")
245 if (it == vAddedNodes.end())
246 throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node has not been added.");
247 vAddedNodes.erase(it);
253 UniValue disconnectnode(const UniValue& params, bool fHelp)
255 if (fHelp || params.size() != 1)
257 "disconnectnode \"node\" \n"
258 "\nImmediately disconnects from the specified node.\n"
260 "1. \"node\" (string, required) The node (see getpeerinfo for nodes)\n"
262 + HelpExampleCli("disconnectnode", "\"192.168.0.6:8233\"")
263 + HelpExampleRpc("disconnectnode", "\"192.168.0.6:8233\"")
266 CNode* pNode = FindNode(params[0].get_str());
268 throw JSONRPCError(RPC_CLIENT_NODE_NOT_CONNECTED, "Node not found in connected nodes");
270 pNode->fDisconnect = true;
275 UniValue getaddednodeinfo(const UniValue& params, bool fHelp)
277 if (fHelp || params.size() < 1 || params.size() > 2)
279 "getaddednodeinfo dns ( \"node\" )\n"
280 "\nReturns information about the given added node, or all added nodes\n"
281 "(note that onetry addnodes are not listed here)\n"
282 "If dns is false, only a list of added nodes will be provided,\n"
283 "otherwise connected information will also be available.\n"
285 "1. dns (boolean, required) If false, only a list of added nodes will be provided, otherwise connected information will also be available.\n"
286 "2. \"node\" (string, optional) If provided, return information about this specific node, otherwise all nodes are returned.\n"
290 " \"addednode\" : \"192.168.0.201\", (string) The node ip address\n"
291 " \"connected\" : true|false, (boolean) If connected\n"
292 " \"addresses\" : [\n"
294 " \"address\" : \"192.168.0.201:8233\", (string) The Zcash server host and port\n"
295 " \"connected\" : \"outbound\" (string) connection, inbound or outbound\n"
303 + HelpExampleCli("getaddednodeinfo", "true")
304 + HelpExampleCli("getaddednodeinfo", "true \"192.168.0.201\"")
305 + HelpExampleRpc("getaddednodeinfo", "true, \"192.168.0.201\"")
308 bool fDns = params[0].get_bool();
310 list<string> laddedNodes(0);
311 if (params.size() == 1)
313 LOCK(cs_vAddedNodes);
314 BOOST_FOREACH(const std::string& strAddNode, vAddedNodes)
315 laddedNodes.push_back(strAddNode);
319 string strNode = params[1].get_str();
320 LOCK(cs_vAddedNodes);
321 BOOST_FOREACH(const std::string& strAddNode, vAddedNodes) {
322 if (strAddNode == strNode)
324 laddedNodes.push_back(strAddNode);
328 if (laddedNodes.size() == 0)
329 throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node has not been added.");
332 UniValue ret(UniValue::VARR);
335 BOOST_FOREACH (const std::string& strAddNode, laddedNodes) {
336 UniValue obj(UniValue::VOBJ);
337 obj.push_back(Pair("addednode", strAddNode));
343 list<pair<string, vector<CService> > > laddedAddreses(0);
344 BOOST_FOREACH(const std::string& strAddNode, laddedNodes) {
345 vector<CService> vservNode(0);
346 if(Lookup(strAddNode.c_str(), vservNode, Params().GetDefaultPort(), fNameLookup, 0))
347 laddedAddreses.push_back(make_pair(strAddNode, vservNode));
350 UniValue obj(UniValue::VOBJ);
351 obj.push_back(Pair("addednode", strAddNode));
352 obj.push_back(Pair("connected", false));
353 UniValue addresses(UniValue::VARR);
354 obj.push_back(Pair("addresses", addresses));
359 for (list<pair<string, vector<CService> > >::iterator it = laddedAddreses.begin(); it != laddedAddreses.end(); it++)
361 UniValue obj(UniValue::VOBJ);
362 obj.push_back(Pair("addednode", it->first));
364 UniValue addresses(UniValue::VARR);
365 bool fConnected = false;
366 BOOST_FOREACH(const CService& addrNode, it->second) {
368 UniValue node(UniValue::VOBJ);
369 node.push_back(Pair("address", addrNode.ToString()));
370 BOOST_FOREACH(CNode* pnode, vNodes) {
371 if (pnode->addr == addrNode)
375 node.push_back(Pair("connected", pnode->fInbound ? "inbound" : "outbound"));
380 node.push_back(Pair("connected", "false"));
381 addresses.push_back(node);
383 obj.push_back(Pair("connected", fConnected));
384 obj.push_back(Pair("addresses", addresses));
391 UniValue getnettotals(const UniValue& params, bool fHelp)
393 if (fHelp || params.size() > 0)
396 "\nReturns information about network traffic, including bytes in, bytes out,\n"
397 "and current time.\n"
400 " \"totalbytesrecv\": n, (numeric) Total bytes received\n"
401 " \"totalbytessent\": n, (numeric) Total bytes sent\n"
402 " \"timemillis\": t (numeric) Total cpu time\n"
405 + HelpExampleCli("getnettotals", "")
406 + HelpExampleRpc("getnettotals", "")
409 UniValue obj(UniValue::VOBJ);
410 obj.push_back(Pair("totalbytesrecv", CNode::GetTotalBytesRecv()));
411 obj.push_back(Pair("totalbytessent", CNode::GetTotalBytesSent()));
412 obj.push_back(Pair("timemillis", GetTimeMillis()));
416 static UniValue GetNetworksInfo()
418 UniValue networks(UniValue::VARR);
419 for(int n=0; n<NET_MAX; ++n)
421 enum Network network = static_cast<enum Network>(n);
422 if(network == NET_UNROUTABLE)
425 UniValue obj(UniValue::VOBJ);
426 GetProxy(network, proxy);
427 obj.push_back(Pair("name", GetNetworkName(network)));
428 obj.push_back(Pair("limited", IsLimited(network)));
429 obj.push_back(Pair("reachable", IsReachable(network)));
430 obj.push_back(Pair("proxy", proxy.IsValid() ? proxy.proxy.ToStringIPPort() : string()));
431 obj.push_back(Pair("proxy_randomize_credentials", proxy.randomize_credentials));
432 networks.push_back(obj);
437 UniValue getdeprecationinfo(const UniValue& params, bool fHelp)
439 const CChainParams& chainparams = Params();
440 if (fHelp || params.size() != 0 || chainparams.NetworkIDString() != "main")
442 "getdeprecationinfo\n"
443 "Returns an object containing current version and deprecation block height. Applicable only on mainnet.\n"
446 " \"version\": xxxxx, (numeric) the server version\n"
447 " \"subversion\": \"/MagicBean:x.y.z[-v]/\", (string) the server subversion string\n"
448 " \"deprecationheight\": xxxxx, (numeric) the block height at which this version will deprecate and shut down (unless -disabledeprecation is set)\n"
451 + HelpExampleCli("getdeprecationinfo", "")
452 + HelpExampleRpc("getdeprecationinfo", "")
455 UniValue obj(UniValue::VOBJ);
456 obj.push_back(Pair("version", CLIENT_VERSION));
457 obj.push_back(Pair("subversion",
458 FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<string>())));
459 obj.push_back(Pair("deprecationheight", DEPRECATION_HEIGHT));
464 UniValue getnetworkinfo(const UniValue& params, bool fHelp)
466 if (fHelp || params.size() != 0)
469 "Returns an object containing various state info regarding P2P networking.\n"
472 " \"version\": xxxxx, (numeric) the server version\n"
473 " \"subversion\": \"/MagicBean:x.y.z[-v]/\", (string) the server subversion string\n"
474 " \"protocolversion\": xxxxx, (numeric) the protocol version\n"
475 " \"localservices\": \"xxxxxxxxxxxxxxxx\", (string) the services we offer to the network\n"
476 " \"timeoffset\": xxxxx, (numeric) the time offset\n"
477 " \"connections\": xxxxx, (numeric) the number of connections\n"
478 " \"networks\": [ (array) information per network\n"
480 " \"name\": \"xxx\", (string) network (ipv4, ipv6 or onion)\n"
481 " \"limited\": true|false, (boolean) is the network limited using -onlynet?\n"
482 " \"reachable\": true|false, (boolean) is the network reachable?\n"
483 " \"proxy\": \"host:port\" (string) the proxy that is used for this network, or empty if none\n"
487 " \"relayfee\": x.xxxxxxxx, (numeric) minimum relay fee for non-free transactions in " + CURRENCY_UNIT + "/kB\n"
488 " \"localaddresses\": [ (array) list of local addresses\n"
490 " \"address\": \"xxxx\", (string) network address\n"
491 " \"port\": xxx, (numeric) network port\n"
492 " \"score\": xxx (numeric) relative score\n"
496 " \"warnings\": \"...\" (string) any network warnings (such as alert messages) \n"
499 + HelpExampleCli("getnetworkinfo", "")
500 + HelpExampleRpc("getnetworkinfo", "")
505 UniValue obj(UniValue::VOBJ);
506 obj.push_back(Pair("version", CLIENT_VERSION));
507 obj.push_back(Pair("subversion",
508 FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<string>())));
509 obj.push_back(Pair("protocolversion",PROTOCOL_VERSION));
510 obj.push_back(Pair("localservices", strprintf("%016x", nLocalServices)));
511 obj.push_back(Pair("timeoffset", GetTimeOffset()));
512 obj.push_back(Pair("connections", (int)vNodes.size()));
513 obj.push_back(Pair("networks", GetNetworksInfo()));
514 obj.push_back(Pair("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK())));
515 UniValue localAddresses(UniValue::VARR);
517 LOCK(cs_mapLocalHost);
518 BOOST_FOREACH(const PAIRTYPE(CNetAddr, LocalServiceInfo) &item, mapLocalHost)
520 UniValue rec(UniValue::VOBJ);
521 rec.push_back(Pair("address", item.first.ToString()));
522 rec.push_back(Pair("port", item.second.nPort));
523 rec.push_back(Pair("score", item.second.nScore));
524 localAddresses.push_back(rec);
527 obj.push_back(Pair("localaddresses", localAddresses));
528 obj.push_back(Pair("warnings", GetWarnings("statusbar")));
532 UniValue setban(const UniValue& params, bool fHelp)
535 if (params.size() >= 2)
536 strCommand = params[1].get_str();
537 if (fHelp || params.size() < 2 ||
538 (strCommand != "add" && strCommand != "remove"))
540 "setban \"ip(/netmask)\" \"add|remove\" (bantime) (absolute)\n"
541 "\nAttempts add or remove a IP/Subnet from the banned list.\n"
543 "1. \"ip(/netmask)\" (string, required) The IP/Subnet (see getpeerinfo for nodes ip) with a optional netmask (default is /32 = single ip)\n"
544 "2. \"command\" (string, required) 'add' to add a IP/Subnet to the list, 'remove' to remove a IP/Subnet from the list\n"
545 "3. \"bantime\" (numeric, optional) time in seconds how long (or until when if [absolute] is set) the ip is banned (0 or empty means using the default time of 24h which can also be overwritten by the -bantime startup argument)\n"
546 "4. \"absolute\" (boolean, optional) If set, the bantime must be a absolute timestamp in seconds since epoch (Jan 1 1970 GMT)\n"
548 + HelpExampleCli("setban", "\"192.168.0.6\" \"add\" 86400")
549 + HelpExampleCli("setban", "\"192.168.0.0/24\" \"add\"")
550 + HelpExampleRpc("setban", "\"192.168.0.6\", \"add\" 86400")
555 bool isSubnet = false;
557 if (params[0].get_str().find("/") != string::npos)
561 netAddr = CNetAddr(params[0].get_str());
563 subNet = CSubNet(params[0].get_str());
565 if (! (isSubnet ? subNet.IsValid() : netAddr.IsValid()) )
566 throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: Invalid IP/Subnet");
568 if (strCommand == "add")
570 if (isSubnet ? CNode::IsBanned(subNet) : CNode::IsBanned(netAddr))
571 throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: IP/Subnet already banned");
573 int64_t banTime = 0; //use standard bantime if not specified
574 if (params.size() >= 3 && !params[2].isNull())
575 banTime = params[2].get_int64();
577 bool absolute = false;
578 if (params.size() == 4 && params[3].isTrue())
581 isSubnet ? CNode::Ban(subNet, banTime, absolute) : CNode::Ban(netAddr, banTime, absolute);
583 //disconnect possible nodes
584 while(CNode *bannedNode = (isSubnet ? FindNode(subNet) : FindNode(netAddr)))
585 bannedNode->fDisconnect = true;
587 else if(strCommand == "remove")
589 if (!( isSubnet ? CNode::Unban(subNet) : CNode::Unban(netAddr) ))
590 throw JSONRPCError(RPC_MISC_ERROR, "Error: Unban failed");
596 UniValue listbanned(const UniValue& params, bool fHelp)
598 if (fHelp || params.size() != 0)
601 "\nList all banned IPs/Subnets.\n"
603 + HelpExampleCli("listbanned", "")
604 + HelpExampleRpc("listbanned", "")
607 std::map<CSubNet, int64_t> banMap;
608 CNode::GetBanned(banMap);
610 UniValue bannedAddresses(UniValue::VARR);
611 for (std::map<CSubNet, int64_t>::iterator it = banMap.begin(); it != banMap.end(); it++)
613 UniValue rec(UniValue::VOBJ);
614 rec.push_back(Pair("address", (*it).first.ToString()));
615 rec.push_back(Pair("banned_until", (*it).second));
616 bannedAddresses.push_back(rec);
619 return bannedAddresses;
622 UniValue clearbanned(const UniValue& params, bool fHelp)
624 if (fHelp || params.size() != 0)
627 "\nClear all banned IPs.\n"
629 + HelpExampleCli("clearbanned", "")
630 + HelpExampleRpc("clearbanned", "")
633 CNode::ClearBanned();