You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

bitcoinrpc.cpp 46KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305
  1. // Copyright (c) 2010 Satoshi Nakamoto
  2. // Copyright (c) 2009-2012 The Bitcoin developers
  3. // Distributed under the MIT/X11 software license, see the accompanying
  4. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
  5. #include "chainparams.h"
  6. #include "init.h"
  7. #include "util.h"
  8. #include "sync.h"
  9. #include "ui_interface.h"
  10. #include "base58.h"
  11. #include "bitcoinrpc.h"
  12. #include "db.h"
  13. #include <boost/algorithm/string.hpp>
  14. #include <boost/asio.hpp>
  15. #include <boost/asio/ip/v6_only.hpp>
  16. #include <boost/asio/ssl.hpp>
  17. #include <boost/bind.hpp>
  18. #include <boost/filesystem.hpp>
  19. #include <boost/filesystem/fstream.hpp>
  20. #include <boost/foreach.hpp>
  21. #include <boost/iostreams/concepts.hpp>
  22. #include <boost/iostreams/stream.hpp>
  23. #include <boost/lexical_cast.hpp>
  24. #include <boost/shared_ptr.hpp>
  25. #include <list>
  26. using namespace std;
  27. using namespace boost;
  28. using namespace boost::asio;
  29. using namespace json_spirit;
  30. static std::string strRPCUserColonPass;
  31. // These are created by StartRPCThreads, destroyed in StopRPCThreads
  32. static asio::io_service* rpc_io_service = NULL;
  33. static map<string, boost::shared_ptr<deadline_timer> > deadlineTimers;
  34. static ssl::context* rpc_ssl_context = NULL;
  35. static boost::thread_group* rpc_worker_group = NULL;
  36. Object JSONRPCError(int code, const string& message)
  37. {
  38. Object error;
  39. error.push_back(Pair("code", code));
  40. error.push_back(Pair("message", message));
  41. return error;
  42. }
  43. void RPCTypeCheck(const Array& params,
  44. const list<Value_type>& typesExpected,
  45. bool fAllowNull)
  46. {
  47. unsigned int i = 0;
  48. BOOST_FOREACH(Value_type t, typesExpected)
  49. {
  50. if (params.size() <= i)
  51. break;
  52. const Value& v = params[i];
  53. if (!((v.type() == t) || (fAllowNull && (v.type() == null_type))))
  54. {
  55. string err = strprintf("Expected type %s, got %s",
  56. Value_type_name[t], Value_type_name[v.type()]);
  57. throw JSONRPCError(RPC_TYPE_ERROR, err);
  58. }
  59. i++;
  60. }
  61. }
  62. void RPCTypeCheck(const Object& o,
  63. const map<string, Value_type>& typesExpected,
  64. bool fAllowNull)
  65. {
  66. BOOST_FOREACH(const PAIRTYPE(string, Value_type)& t, typesExpected)
  67. {
  68. const Value& v = find_value(o, t.first);
  69. if (!fAllowNull && v.type() == null_type)
  70. throw JSONRPCError(RPC_TYPE_ERROR, strprintf("Missing %s", t.first.c_str()));
  71. if (!((v.type() == t.second) || (fAllowNull && (v.type() == null_type))))
  72. {
  73. string err = strprintf("Expected type %s for %s, got %s",
  74. Value_type_name[t.second], t.first.c_str(), Value_type_name[v.type()]);
  75. throw JSONRPCError(RPC_TYPE_ERROR, err);
  76. }
  77. }
  78. }
  79. int64 AmountFromValue(const Value& value)
  80. {
  81. double dAmount = value.get_real();
  82. if (dAmount <= 0.0 || dAmount > 21000000.0)
  83. throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount");
  84. int64 nAmount = roundint64(dAmount * COIN);
  85. if (!MoneyRange(nAmount))
  86. throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount");
  87. return nAmount;
  88. }
  89. Value ValueFromAmount(int64 amount)
  90. {
  91. return (double)amount / (double)COIN;
  92. }
  93. std::string HexBits(unsigned int nBits)
  94. {
  95. union {
  96. int32_t nBits;
  97. char cBits[4];
  98. } uBits;
  99. uBits.nBits = htonl((int32_t)nBits);
  100. return HexStr(BEGIN(uBits.cBits), END(uBits.cBits));
  101. }
  102. ///
  103. /// Note: This interface may still be subject to change.
  104. ///
  105. string CRPCTable::help(string strCommand) const
  106. {
  107. string strRet;
  108. set<rpcfn_type> setDone;
  109. for (map<string, const CRPCCommand*>::const_iterator mi = mapCommands.begin(); mi != mapCommands.end(); ++mi)
  110. {
  111. const CRPCCommand *pcmd = mi->second;
  112. string strMethod = mi->first;
  113. // We already filter duplicates, but these deprecated screw up the sort order
  114. if (strMethod.find("label") != string::npos)
  115. continue;
  116. if (strCommand != "" && strMethod != strCommand)
  117. continue;
  118. try
  119. {
  120. Array params;
  121. rpcfn_type pfn = pcmd->actor;
  122. if (setDone.insert(pfn).second)
  123. (*pfn)(params, true);
  124. }
  125. catch (std::exception& e)
  126. {
  127. // Help text is returned in an exception
  128. string strHelp = string(e.what());
  129. if (strCommand == "")
  130. if (strHelp.find('\n') != string::npos)
  131. strHelp = strHelp.substr(0, strHelp.find('\n'));
  132. strRet += strHelp + "\n";
  133. }
  134. }
  135. if (strRet == "")
  136. strRet = strprintf("help: unknown command: %s\n", strCommand.c_str());
  137. strRet = strRet.substr(0,strRet.size()-1);
  138. return strRet;
  139. }
  140. Value help(const Array& params, bool fHelp)
  141. {
  142. if (fHelp || params.size() > 1)
  143. throw runtime_error(
  144. "help [command]\n"
  145. "List commands, or get help for a command.");
  146. string strCommand;
  147. if (params.size() > 0)
  148. strCommand = params[0].get_str();
  149. return tableRPC.help(strCommand);
  150. }
  151. Value stop(const Array& params, bool fHelp)
  152. {
  153. // Accept the deprecated and ignored 'detach' boolean argument
  154. if (fHelp || params.size() > 1)
  155. throw runtime_error(
  156. "stop\n"
  157. "Stop Bitcoin server.");
  158. // Shutdown will take long enough that the response should get back
  159. StartShutdown();
  160. return "Bitcoin server stopping";
  161. }
  162. //
  163. // Call Table
  164. //
  165. static const CRPCCommand vRPCCommands[] =
  166. { // name actor (function) okSafeMode threadSafe
  167. // ------------------------ ----------------------- ---------- ----------
  168. { "help", &help, true, true },
  169. { "stop", &stop, true, true },
  170. { "getblockcount", &getblockcount, true, false },
  171. { "getconnectioncount", &getconnectioncount, true, false },
  172. { "getpeerinfo", &getpeerinfo, true, false },
  173. { "addnode", &addnode, true, true },
  174. { "getaddednodeinfo", &getaddednodeinfo, true, true },
  175. { "getdifficulty", &getdifficulty, true, false },
  176. { "getgenerate", &getgenerate, true, false },
  177. { "setgenerate", &setgenerate, true, false },
  178. { "gethashespersec", &gethashespersec, true, false },
  179. { "getinfo", &getinfo, true, false },
  180. { "getmininginfo", &getmininginfo, true, false },
  181. { "getnewaddress", &getnewaddress, true, false },
  182. { "getaccountaddress", &getaccountaddress, true, false },
  183. { "setaccount", &setaccount, true, false },
  184. { "getaccount", &getaccount, false, false },
  185. { "getaddressesbyaccount", &getaddressesbyaccount, true, false },
  186. { "sendtoaddress", &sendtoaddress, false, false },
  187. { "getreceivedbyaddress", &getreceivedbyaddress, false, false },
  188. { "getreceivedbyaccount", &getreceivedbyaccount, false, false },
  189. { "listreceivedbyaddress", &listreceivedbyaddress, false, false },
  190. { "listreceivedbyaccount", &listreceivedbyaccount, false, false },
  191. { "backupwallet", &backupwallet, true, false },
  192. { "keypoolrefill", &keypoolrefill, true, false },
  193. { "walletpassphrase", &walletpassphrase, true, false },
  194. { "walletpassphrasechange", &walletpassphrasechange, false, false },
  195. { "walletlock", &walletlock, true, false },
  196. { "encryptwallet", &encryptwallet, false, false },
  197. { "validateaddress", &validateaddress, true, false },
  198. { "getbalance", &getbalance, false, false },
  199. { "move", &movecmd, false, false },
  200. { "sendfrom", &sendfrom, false, false },
  201. { "sendmany", &sendmany, false, false },
  202. { "addmultisigaddress", &addmultisigaddress, false, false },
  203. { "createmultisig", &createmultisig, true, true },
  204. { "getrawmempool", &getrawmempool, true, false },
  205. { "getblock", &getblock, false, false },
  206. { "getblockhash", &getblockhash, false, false },
  207. { "gettransaction", &gettransaction, false, false },
  208. { "listtransactions", &listtransactions, false, false },
  209. { "listaddressgroupings", &listaddressgroupings, false, false },
  210. { "signmessage", &signmessage, false, false },
  211. { "verifymessage", &verifymessage, false, false },
  212. { "getwork", &getwork, true, false },
  213. { "listaccounts", &listaccounts, false, false },
  214. { "settxfee", &settxfee, false, false },
  215. { "getblocktemplate", &getblocktemplate, true, false },
  216. { "submitblock", &submitblock, false, false },
  217. { "listsinceblock", &listsinceblock, false, false },
  218. { "dumpprivkey", &dumpprivkey, true, false },
  219. { "importprivkey", &importprivkey, false, false },
  220. { "listunspent", &listunspent, false, false },
  221. { "getrawtransaction", &getrawtransaction, false, false },
  222. { "createrawtransaction", &createrawtransaction, false, false },
  223. { "decoderawtransaction", &decoderawtransaction, false, false },
  224. { "signrawtransaction", &signrawtransaction, false, false },
  225. { "sendrawtransaction", &sendrawtransaction, false, false },
  226. { "gettxoutsetinfo", &gettxoutsetinfo, true, false },
  227. { "gettxout", &gettxout, true, false },
  228. { "lockunspent", &lockunspent, false, false },
  229. { "listlockunspent", &listlockunspent, false, false },
  230. };
  231. CRPCTable::CRPCTable()
  232. {
  233. unsigned int vcidx;
  234. for (vcidx = 0; vcidx < (sizeof(vRPCCommands) / sizeof(vRPCCommands[0])); vcidx++)
  235. {
  236. const CRPCCommand *pcmd;
  237. pcmd = &vRPCCommands[vcidx];
  238. mapCommands[pcmd->name] = pcmd;
  239. }
  240. }
  241. const CRPCCommand *CRPCTable::operator[](string name) const
  242. {
  243. map<string, const CRPCCommand*>::const_iterator it = mapCommands.find(name);
  244. if (it == mapCommands.end())
  245. return NULL;
  246. return (*it).second;
  247. }
  248. //
  249. // HTTP protocol
  250. //
  251. // This ain't Apache. We're just using HTTP header for the length field
  252. // and to be compatible with other JSON-RPC implementations.
  253. //
  254. string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
  255. {
  256. ostringstream s;
  257. s << "POST / HTTP/1.1\r\n"
  258. << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
  259. << "Host: 127.0.0.1\r\n"
  260. << "Content-Type: application/json\r\n"
  261. << "Content-Length: " << strMsg.size() << "\r\n"
  262. << "Connection: close\r\n"
  263. << "Accept: application/json\r\n";
  264. BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
  265. s << item.first << ": " << item.second << "\r\n";
  266. s << "\r\n" << strMsg;
  267. return s.str();
  268. }
  269. string rfc1123Time()
  270. {
  271. char buffer[64];
  272. time_t now;
  273. time(&now);
  274. struct tm* now_gmt = gmtime(&now);
  275. string locale(setlocale(LC_TIME, NULL));
  276. setlocale(LC_TIME, "C"); // we want POSIX (aka "C") weekday/month strings
  277. strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
  278. setlocale(LC_TIME, locale.c_str());
  279. return string(buffer);
  280. }
  281. static string HTTPReply(int nStatus, const string& strMsg, bool keepalive)
  282. {
  283. if (nStatus == HTTP_UNAUTHORIZED)
  284. return strprintf("HTTP/1.0 401 Authorization Required\r\n"
  285. "Date: %s\r\n"
  286. "Server: bitcoin-json-rpc/%s\r\n"
  287. "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
  288. "Content-Type: text/html\r\n"
  289. "Content-Length: 296\r\n"
  290. "\r\n"
  291. "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
  292. "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
  293. "<HTML>\r\n"
  294. "<HEAD>\r\n"
  295. "<TITLE>Error</TITLE>\r\n"
  296. "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
  297. "</HEAD>\r\n"
  298. "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
  299. "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
  300. const char *cStatus;
  301. if (nStatus == HTTP_OK) cStatus = "OK";
  302. else if (nStatus == HTTP_BAD_REQUEST) cStatus = "Bad Request";
  303. else if (nStatus == HTTP_FORBIDDEN) cStatus = "Forbidden";
  304. else if (nStatus == HTTP_NOT_FOUND) cStatus = "Not Found";
  305. else if (nStatus == HTTP_INTERNAL_SERVER_ERROR) cStatus = "Internal Server Error";
  306. else cStatus = "";
  307. return strprintf(
  308. "HTTP/1.1 %d %s\r\n"
  309. "Date: %s\r\n"
  310. "Connection: %s\r\n"
  311. "Content-Length: %"PRIszu"\r\n"
  312. "Content-Type: application/json\r\n"
  313. "Server: bitcoin-json-rpc/%s\r\n"
  314. "\r\n"
  315. "%s",
  316. nStatus,
  317. cStatus,
  318. rfc1123Time().c_str(),
  319. keepalive ? "keep-alive" : "close",
  320. strMsg.size(),
  321. FormatFullVersion().c_str(),
  322. strMsg.c_str());
  323. }
  324. bool ReadHTTPRequestLine(std::basic_istream<char>& stream, int &proto,
  325. string& http_method, string& http_uri)
  326. {
  327. string str;
  328. getline(stream, str);
  329. // HTTP request line is space-delimited
  330. vector<string> vWords;
  331. boost::split(vWords, str, boost::is_any_of(" "));
  332. if (vWords.size() < 2)
  333. return false;
  334. // HTTP methods permitted: GET, POST
  335. http_method = vWords[0];
  336. if (http_method != "GET" && http_method != "POST")
  337. return false;
  338. // HTTP URI must be an absolute path, relative to current host
  339. http_uri = vWords[1];
  340. if (http_uri.size() == 0 || http_uri[0] != '/')
  341. return false;
  342. // parse proto, if present
  343. string strProto = "";
  344. if (vWords.size() > 2)
  345. strProto = vWords[2];
  346. proto = 0;
  347. const char *ver = strstr(strProto.c_str(), "HTTP/1.");
  348. if (ver != NULL)
  349. proto = atoi(ver+7);
  350. return true;
  351. }
  352. int ReadHTTPStatus(std::basic_istream<char>& stream, int &proto)
  353. {
  354. string str;
  355. getline(stream, str);
  356. vector<string> vWords;
  357. boost::split(vWords, str, boost::is_any_of(" "));
  358. if (vWords.size() < 2)
  359. return HTTP_INTERNAL_SERVER_ERROR;
  360. proto = 0;
  361. const char *ver = strstr(str.c_str(), "HTTP/1.");
  362. if (ver != NULL)
  363. proto = atoi(ver+7);
  364. return atoi(vWords[1].c_str());
  365. }
  366. int ReadHTTPHeaders(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
  367. {
  368. int nLen = 0;
  369. loop
  370. {
  371. string str;
  372. std::getline(stream, str);
  373. if (str.empty() || str == "\r")
  374. break;
  375. string::size_type nColon = str.find(":");
  376. if (nColon != string::npos)
  377. {
  378. string strHeader = str.substr(0, nColon);
  379. boost::trim(strHeader);
  380. boost::to_lower(strHeader);
  381. string strValue = str.substr(nColon+1);
  382. boost::trim(strValue);
  383. mapHeadersRet[strHeader] = strValue;
  384. if (strHeader == "content-length")
  385. nLen = atoi(strValue.c_str());
  386. }
  387. }
  388. return nLen;
  389. }
  390. int ReadHTTPMessage(std::basic_istream<char>& stream, map<string,
  391. string>& mapHeadersRet, string& strMessageRet,
  392. int nProto)
  393. {
  394. mapHeadersRet.clear();
  395. strMessageRet = "";
  396. // Read header
  397. int nLen = ReadHTTPHeaders(stream, mapHeadersRet);
  398. if (nLen < 0 || nLen > (int)MAX_SIZE)
  399. return HTTP_INTERNAL_SERVER_ERROR;
  400. // Read message
  401. if (nLen > 0)
  402. {
  403. vector<char> vch(nLen);
  404. stream.read(&vch[0], nLen);
  405. strMessageRet = string(vch.begin(), vch.end());
  406. }
  407. string sConHdr = mapHeadersRet["connection"];
  408. if ((sConHdr != "close") && (sConHdr != "keep-alive"))
  409. {
  410. if (nProto >= 1)
  411. mapHeadersRet["connection"] = "keep-alive";
  412. else
  413. mapHeadersRet["connection"] = "close";
  414. }
  415. return HTTP_OK;
  416. }
  417. bool HTTPAuthorized(map<string, string>& mapHeaders)
  418. {
  419. string strAuth = mapHeaders["authorization"];
  420. if (strAuth.substr(0,6) != "Basic ")
  421. return false;
  422. string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
  423. string strUserPass = DecodeBase64(strUserPass64);
  424. return strUserPass == strRPCUserColonPass;
  425. }
  426. //
  427. // JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
  428. // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
  429. // unspecified (HTTP errors and contents of 'error').
  430. //
  431. // 1.0 spec: http://json-rpc.org/wiki/specification
  432. // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
  433. // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
  434. //
  435. string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
  436. {
  437. Object request;
  438. request.push_back(Pair("method", strMethod));
  439. request.push_back(Pair("params", params));
  440. request.push_back(Pair("id", id));
  441. return write_string(Value(request), false) + "\n";
  442. }
  443. Object JSONRPCReplyObj(const Value& result, const Value& error, const Value& id)
  444. {
  445. Object reply;
  446. if (error.type() != null_type)
  447. reply.push_back(Pair("result", Value::null));
  448. else
  449. reply.push_back(Pair("result", result));
  450. reply.push_back(Pair("error", error));
  451. reply.push_back(Pair("id", id));
  452. return reply;
  453. }
  454. string JSONRPCReply(const Value& result, const Value& error, const Value& id)
  455. {
  456. Object reply = JSONRPCReplyObj(result, error, id);
  457. return write_string(Value(reply), false) + "\n";
  458. }
  459. void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
  460. {
  461. // Send error reply from json-rpc error object
  462. int nStatus = HTTP_INTERNAL_SERVER_ERROR;
  463. int code = find_value(objError, "code").get_int();
  464. if (code == RPC_INVALID_REQUEST) nStatus = HTTP_BAD_REQUEST;
  465. else if (code == RPC_METHOD_NOT_FOUND) nStatus = HTTP_NOT_FOUND;
  466. string strReply = JSONRPCReply(Value::null, objError, id);
  467. stream << HTTPReply(nStatus, strReply, false) << std::flush;
  468. }
  469. bool ClientAllowed(const boost::asio::ip::address& address)
  470. {
  471. // Make sure that IPv4-compatible and IPv4-mapped IPv6 addresses are treated as IPv4 addresses
  472. if (address.is_v6()
  473. && (address.to_v6().is_v4_compatible()
  474. || address.to_v6().is_v4_mapped()))
  475. return ClientAllowed(address.to_v6().to_v4());
  476. if (address == asio::ip::address_v4::loopback()
  477. || address == asio::ip::address_v6::loopback()
  478. || (address.is_v4()
  479. // Check whether IPv4 addresses match 127.0.0.0/8 (loopback subnet)
  480. && (address.to_v4().to_ulong() & 0xff000000) == 0x7f000000))
  481. return true;
  482. const string strAddress = address.to_string();
  483. const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
  484. BOOST_FOREACH(string strAllow, vAllow)
  485. if (WildcardMatch(strAddress, strAllow))
  486. return true;
  487. return false;
  488. }
  489. //
  490. // IOStream device that speaks SSL but can also speak non-SSL
  491. //
  492. template <typename Protocol>
  493. class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
  494. public:
  495. SSLIOStreamDevice(asio::ssl::stream<typename Protocol::socket> &streamIn, bool fUseSSLIn) : stream(streamIn)
  496. {
  497. fUseSSL = fUseSSLIn;
  498. fNeedHandshake = fUseSSLIn;
  499. }
  500. void handshake(ssl::stream_base::handshake_type role)
  501. {
  502. if (!fNeedHandshake) return;
  503. fNeedHandshake = false;
  504. stream.handshake(role);
  505. }
  506. std::streamsize read(char* s, std::streamsize n)
  507. {
  508. handshake(ssl::stream_base::server); // HTTPS servers read first
  509. if (fUseSSL) return stream.read_some(asio::buffer(s, n));
  510. return stream.next_layer().read_some(asio::buffer(s, n));
  511. }
  512. std::streamsize write(const char* s, std::streamsize n)
  513. {
  514. handshake(ssl::stream_base::client); // HTTPS clients write first
  515. if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
  516. return asio::write(stream.next_layer(), asio::buffer(s, n));
  517. }
  518. bool connect(const std::string& server, const std::string& port)
  519. {
  520. ip::tcp::resolver resolver(stream.get_io_service());
  521. ip::tcp::resolver::query query(server.c_str(), port.c_str());
  522. ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
  523. ip::tcp::resolver::iterator end;
  524. boost::system::error_code error = asio::error::host_not_found;
  525. while (error && endpoint_iterator != end)
  526. {
  527. stream.lowest_layer().close();
  528. stream.lowest_layer().connect(*endpoint_iterator++, error);
  529. }
  530. if (error)
  531. return false;
  532. return true;
  533. }
  534. private:
  535. bool fNeedHandshake;
  536. bool fUseSSL;
  537. asio::ssl::stream<typename Protocol::socket>& stream;
  538. };
  539. class AcceptedConnection
  540. {
  541. public:
  542. virtual ~AcceptedConnection() {}
  543. virtual std::iostream& stream() = 0;
  544. virtual std::string peer_address_to_string() const = 0;
  545. virtual void close() = 0;
  546. };
  547. template <typename Protocol>
  548. class AcceptedConnectionImpl : public AcceptedConnection
  549. {
  550. public:
  551. AcceptedConnectionImpl(
  552. asio::io_service& io_service,
  553. ssl::context &context,
  554. bool fUseSSL) :
  555. sslStream(io_service, context),
  556. _d(sslStream, fUseSSL),
  557. _stream(_d)
  558. {
  559. }
  560. virtual std::iostream& stream()
  561. {
  562. return _stream;
  563. }
  564. virtual std::string peer_address_to_string() const
  565. {
  566. return peer.address().to_string();
  567. }
  568. virtual void close()
  569. {
  570. _stream.close();
  571. }
  572. typename Protocol::endpoint peer;
  573. asio::ssl::stream<typename Protocol::socket> sslStream;
  574. private:
  575. SSLIOStreamDevice<Protocol> _d;
  576. iostreams::stream< SSLIOStreamDevice<Protocol> > _stream;
  577. };
  578. void ServiceConnection(AcceptedConnection *conn);
  579. // Forward declaration required for RPCListen
  580. template <typename Protocol, typename SocketAcceptorService>
  581. static void RPCAcceptHandler(boost::shared_ptr< basic_socket_acceptor<Protocol, SocketAcceptorService> > acceptor,
  582. ssl::context& context,
  583. bool fUseSSL,
  584. AcceptedConnection* conn,
  585. const boost::system::error_code& error);
  586. /**
  587. * Sets up I/O resources to accept and handle a new connection.
  588. */
  589. template <typename Protocol, typename SocketAcceptorService>
  590. static void RPCListen(boost::shared_ptr< basic_socket_acceptor<Protocol, SocketAcceptorService> > acceptor,
  591. ssl::context& context,
  592. const bool fUseSSL)
  593. {
  594. // Accept connection
  595. AcceptedConnectionImpl<Protocol>* conn = new AcceptedConnectionImpl<Protocol>(acceptor->get_io_service(), context, fUseSSL);
  596. acceptor->async_accept(
  597. conn->sslStream.lowest_layer(),
  598. conn->peer,
  599. boost::bind(&RPCAcceptHandler<Protocol, SocketAcceptorService>,
  600. acceptor,
  601. boost::ref(context),
  602. fUseSSL,
  603. conn,
  604. boost::asio::placeholders::error));
  605. }
  606. /**
  607. * Accept and handle incoming connection.
  608. */
  609. template <typename Protocol, typename SocketAcceptorService>
  610. static void RPCAcceptHandler(boost::shared_ptr< basic_socket_acceptor<Protocol, SocketAcceptorService> > acceptor,
  611. ssl::context& context,
  612. const bool fUseSSL,
  613. AcceptedConnection* conn,
  614. const boost::system::error_code& error)
  615. {
  616. // Immediately start accepting new connections, except when we're cancelled or our socket is closed.
  617. if (error != asio::error::operation_aborted && acceptor->is_open())
  618. RPCListen(acceptor, context, fUseSSL);
  619. AcceptedConnectionImpl<ip::tcp>* tcp_conn = dynamic_cast< AcceptedConnectionImpl<ip::tcp>* >(conn);
  620. // TODO: Actually handle errors
  621. if (error)
  622. {
  623. delete conn;
  624. }
  625. // Restrict callers by IP. It is important to
  626. // do this before starting client thread, to filter out
  627. // certain DoS and misbehaving clients.
  628. else if (tcp_conn && !ClientAllowed(tcp_conn->peer.address()))
  629. {
  630. // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
  631. if (!fUseSSL)
  632. conn->stream() << HTTPReply(HTTP_FORBIDDEN, "", false) << std::flush;
  633. delete conn;
  634. }
  635. else {
  636. ServiceConnection(conn);
  637. conn->close();
  638. delete conn;
  639. }
  640. }
  641. void StartRPCThreads()
  642. {
  643. strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
  644. if (((mapArgs["-rpcpassword"] == "") ||
  645. (mapArgs["-rpcuser"] == mapArgs["-rpcpassword"])) && Params().RequireRPCPassword())
  646. {
  647. unsigned char rand_pwd[32];
  648. RAND_bytes(rand_pwd, 32);
  649. string strWhatAmI = "To use bitcoind";
  650. if (mapArgs.count("-server"))
  651. strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
  652. else if (mapArgs.count("-daemon"))
  653. strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
  654. uiInterface.ThreadSafeMessageBox(strprintf(
  655. _("%s, you must set a rpcpassword in the configuration file:\n"
  656. "%s\n"
  657. "It is recommended you use the following random password:\n"
  658. "rpcuser=bitcoinrpc\n"
  659. "rpcpassword=%s\n"
  660. "(you do not need to remember this password)\n"
  661. "The username and password MUST NOT be the same.\n"
  662. "If the file does not exist, create it with owner-readable-only file permissions.\n"
  663. "It is also recommended to set alertnotify so you are notified of problems;\n"
  664. "for example: alertnotify=echo %%s | mail -s \"Bitcoin Alert\" admin@foo.com\n"),
  665. strWhatAmI.c_str(),
  666. GetConfigFile().string().c_str(),
  667. EncodeBase58(&rand_pwd[0],&rand_pwd[0]+32).c_str()),
  668. "", CClientUIInterface::MSG_ERROR);
  669. StartShutdown();
  670. return;
  671. }
  672. assert(rpc_io_service == NULL);
  673. rpc_io_service = new asio::io_service();
  674. rpc_ssl_context = new ssl::context(*rpc_io_service, ssl::context::sslv23);
  675. const bool fUseSSL = GetBoolArg("-rpcssl", false);
  676. if (fUseSSL)
  677. {
  678. rpc_ssl_context->set_options(ssl::context::no_sslv2);
  679. filesystem::path pathCertFile(GetArg("-rpcsslcertificatechainfile", "server.cert"));
  680. if (!pathCertFile.is_complete()) pathCertFile = filesystem::path(GetDataDir()) / pathCertFile;
  681. if (filesystem::exists(pathCertFile)) rpc_ssl_context->use_certificate_chain_file(pathCertFile.string());
  682. else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", pathCertFile.string().c_str());
  683. filesystem::path pathPKFile(GetArg("-rpcsslprivatekeyfile", "server.pem"));
  684. if (!pathPKFile.is_complete()) pathPKFile = filesystem::path(GetDataDir()) / pathPKFile;
  685. if (filesystem::exists(pathPKFile)) rpc_ssl_context->use_private_key_file(pathPKFile.string(), ssl::context::pem);
  686. else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pathPKFile.string().c_str());
  687. string strCiphers = GetArg("-rpcsslciphers", "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
  688. SSL_CTX_set_cipher_list(rpc_ssl_context->impl(), strCiphers.c_str());
  689. }
  690. // Try a dual IPv6/IPv4 socket, falling back to separate IPv4 and IPv6 sockets
  691. const bool loopback = !mapArgs.count("-rpcallowip");
  692. asio::ip::address bindAddress = loopback ? asio::ip::address_v6::loopback() : asio::ip::address_v6::any();
  693. ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", Params().RPCPort()));
  694. boost::system::error_code v6_only_error;
  695. boost::shared_ptr<ip::tcp::acceptor> acceptor(new ip::tcp::acceptor(*rpc_io_service));
  696. bool fListening = false;
  697. std::string strerr;
  698. try
  699. {
  700. acceptor->open(endpoint.protocol());
  701. acceptor->set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
  702. // Try making the socket dual IPv6/IPv4 (if listening on the "any" address)
  703. acceptor->set_option(boost::asio::ip::v6_only(loopback), v6_only_error);
  704. acceptor->bind(endpoint);
  705. acceptor->listen(socket_base::max_connections);
  706. RPCListen(acceptor, *rpc_ssl_context, fUseSSL);
  707. fListening = true;
  708. }
  709. catch(boost::system::system_error &e)
  710. {
  711. strerr = strprintf(_("An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s"), endpoint.port(), e.what());
  712. }
  713. try {
  714. // If dual IPv6/IPv4 failed (or we're opening loopback interfaces only), open IPv4 separately
  715. if (!fListening || loopback || v6_only_error)
  716. {
  717. bindAddress = loopback ? asio::ip::address_v4::loopback() : asio::ip::address_v4::any();
  718. endpoint.address(bindAddress);
  719. acceptor.reset(new ip::tcp::acceptor(*rpc_io_service));
  720. acceptor->open(endpoint.protocol());
  721. acceptor->set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
  722. acceptor->bind(endpoint);
  723. acceptor->listen(socket_base::max_connections);
  724. RPCListen(acceptor, *rpc_ssl_context, fUseSSL);
  725. fListening = true;
  726. }
  727. }
  728. catch(boost::system::system_error &e)
  729. {
  730. strerr = strprintf(_("An error occurred while setting up the RPC port %u for listening on IPv4: %s"), endpoint.port(), e.what());
  731. }
  732. if (!fListening) {
  733. uiInterface.ThreadSafeMessageBox(strerr, "", CClientUIInterface::MSG_ERROR);
  734. StartShutdown();
  735. return;
  736. }
  737. rpc_worker_group = new boost::thread_group();
  738. for (int i = 0; i < GetArg("-rpcthreads", 4); i++)
  739. rpc_worker_group->create_thread(boost::bind(&asio::io_service::run, rpc_io_service));
  740. }
  741. void StopRPCThreads()
  742. {
  743. if (rpc_io_service == NULL) return;
  744. deadlineTimers.clear();
  745. rpc_io_service->stop();
  746. rpc_worker_group->join_all();
  747. delete rpc_worker_group; rpc_worker_group = NULL;
  748. delete rpc_ssl_context; rpc_ssl_context = NULL;
  749. delete rpc_io_service; rpc_io_service = NULL;
  750. }
  751. void RPCRunHandler(const boost::system::error_code& err, boost::function<void(void)> func)
  752. {
  753. if (!err)
  754. func();
  755. }
  756. void RPCRunLater(const std::string& name, boost::function<void(void)> func, int64 nSeconds)
  757. {
  758. assert(rpc_io_service != NULL);
  759. if (deadlineTimers.count(name) == 0)
  760. {
  761. deadlineTimers.insert(make_pair(name,
  762. boost::shared_ptr<deadline_timer>(new deadline_timer(*rpc_io_service))));
  763. }
  764. deadlineTimers[name]->expires_from_now(posix_time::seconds(nSeconds));
  765. deadlineTimers[name]->async_wait(boost::bind(RPCRunHandler, _1, func));
  766. }
  767. class JSONRequest
  768. {
  769. public:
  770. Value id;
  771. string strMethod;
  772. Array params;
  773. JSONRequest() { id = Value::null; }
  774. void parse(const Value& valRequest);
  775. };
  776. void JSONRequest::parse(const Value& valRequest)
  777. {
  778. // Parse request
  779. if (valRequest.type() != obj_type)
  780. throw JSONRPCError(RPC_INVALID_REQUEST, "Invalid Request object");
  781. const Object& request = valRequest.get_obj();
  782. // Parse id now so errors from here on will have the id
  783. id = find_value(request, "id");
  784. // Parse method
  785. Value valMethod = find_value(request, "method");
  786. if (valMethod.type() == null_type)
  787. throw JSONRPCError(RPC_INVALID_REQUEST, "Missing method");
  788. if (valMethod.type() != str_type)
  789. throw JSONRPCError(RPC_INVALID_REQUEST, "Method must be a string");
  790. strMethod = valMethod.get_str();
  791. if (strMethod != "getwork" && strMethod != "getblocktemplate")
  792. printf("ThreadRPCServer method=%s\n", strMethod.c_str());
  793. // Parse params
  794. Value valParams = find_value(request, "params");
  795. if (valParams.type() == array_type)
  796. params = valParams.get_array();
  797. else if (valParams.type() == null_type)
  798. params = Array();
  799. else
  800. throw JSONRPCError(RPC_INVALID_REQUEST, "Params must be an array");
  801. }
  802. static Object JSONRPCExecOne(const Value& req)
  803. {
  804. Object rpc_result;
  805. JSONRequest jreq;
  806. try {
  807. jreq.parse(req);
  808. Value result = tableRPC.execute(jreq.strMethod, jreq.params);
  809. rpc_result = JSONRPCReplyObj(result, Value::null, jreq.id);
  810. }
  811. catch (Object& objError)
  812. {
  813. rpc_result = JSONRPCReplyObj(Value::null, objError, jreq.id);
  814. }
  815. catch (std::exception& e)
  816. {
  817. rpc_result = JSONRPCReplyObj(Value::null,
  818. JSONRPCError(RPC_PARSE_ERROR, e.what()), jreq.id);
  819. }
  820. return rpc_result;
  821. }
  822. static string JSONRPCExecBatch(const Array& vReq)
  823. {
  824. Array ret;
  825. for (unsigned int reqIdx = 0; reqIdx < vReq.size(); reqIdx++)
  826. ret.push_back(JSONRPCExecOne(vReq[reqIdx]));
  827. return write_string(Value(ret), false) + "\n";
  828. }
  829. void ServiceConnection(AcceptedConnection *conn)
  830. {
  831. bool fRun = true;
  832. while (fRun)
  833. {
  834. int nProto = 0;
  835. map<string, string> mapHeaders;
  836. string strRequest, strMethod, strURI;
  837. // Read HTTP request line
  838. if (!ReadHTTPRequestLine(conn->stream(), nProto, strMethod, strURI))
  839. break;
  840. // Read HTTP message headers and body
  841. ReadHTTPMessage(conn->stream(), mapHeaders, strRequest, nProto);
  842. if (strURI != "/") {
  843. conn->stream() << HTTPReply(HTTP_NOT_FOUND, "", false) << std::flush;
  844. break;
  845. }
  846. // Check authorization
  847. if (mapHeaders.count("authorization") == 0)
  848. {
  849. conn->stream() << HTTPReply(HTTP_UNAUTHORIZED, "", false) << std::flush;
  850. break;
  851. }
  852. if (!HTTPAuthorized(mapHeaders))
  853. {
  854. printf("ThreadRPCServer incorrect password attempt from %s\n", conn->peer_address_to_string().c_str());
  855. /* Deter brute-forcing short passwords.
  856. If this results in a DOS the user really
  857. shouldn't have their RPC port exposed.*/
  858. if (mapArgs["-rpcpassword"].size() < 20)
  859. MilliSleep(250);
  860. conn->stream() << HTTPReply(HTTP_UNAUTHORIZED, "", false) << std::flush;
  861. break;
  862. }
  863. if (mapHeaders["connection"] == "close")
  864. fRun = false;
  865. JSONRequest jreq;
  866. try
  867. {
  868. // Parse request
  869. Value valRequest;
  870. if (!read_string(strRequest, valRequest))
  871. throw JSONRPCError(RPC_PARSE_ERROR, "Parse error");
  872. string strReply;
  873. // singleton request
  874. if (valRequest.type() == obj_type) {
  875. jreq.parse(valRequest);
  876. Value result = tableRPC.execute(jreq.strMethod, jreq.params);
  877. // Send reply
  878. strReply = JSONRPCReply(result, Value::null, jreq.id);
  879. // array of requests
  880. } else if (valRequest.type() == array_type)
  881. strReply = JSONRPCExecBatch(valRequest.get_array());
  882. else
  883. throw JSONRPCError(RPC_PARSE_ERROR, "Top-level object parse error");
  884. conn->stream() << HTTPReply(HTTP_OK, strReply, fRun) << std::flush;
  885. }
  886. catch (Object& objError)
  887. {
  888. ErrorReply(conn->stream(), objError, jreq.id);
  889. break;
  890. }
  891. catch (std::exception& e)
  892. {
  893. ErrorReply(conn->stream(), JSONRPCError(RPC_PARSE_ERROR, e.what()), jreq.id);
  894. break;
  895. }
  896. }
  897. }
  898. json_spirit::Value CRPCTable::execute(const std::string &strMethod, const json_spirit::Array &params) const
  899. {
  900. // Find method
  901. const CRPCCommand *pcmd = tableRPC[strMethod];
  902. if (!pcmd)
  903. throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found");
  904. // Observe safe mode
  905. string strWarning = GetWarnings("rpc");
  906. if (strWarning != "" && !GetBoolArg("-disablesafemode", false) &&
  907. !pcmd->okSafeMode)
  908. throw JSONRPCError(RPC_FORBIDDEN_BY_SAFE_MODE, string("Safe mode: ") + strWarning);
  909. try
  910. {
  911. // Execute
  912. Value result;
  913. {
  914. if (pcmd->threadSafe)
  915. result = pcmd->actor(params, false);
  916. else {
  917. LOCK2(cs_main, pwalletMain->cs_wallet);
  918. result = pcmd->actor(params, false);
  919. }
  920. }
  921. return result;
  922. }
  923. catch (std::exception& e)
  924. {
  925. throw JSONRPCError(RPC_MISC_ERROR, e.what());
  926. }
  927. }
  928. Object CallRPC(const string& strMethod, const Array& params)
  929. {
  930. if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
  931. throw runtime_error(strprintf(
  932. _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
  933. "If the file does not exist, create it with owner-readable-only file permissions."),
  934. GetConfigFile().string().c_str()));
  935. // Connect to localhost
  936. bool fUseSSL = GetBoolArg("-rpcssl", false);
  937. asio::io_service io_service;
  938. ssl::context context(io_service, ssl::context::sslv23);
  939. context.set_options(ssl::context::no_sslv2);
  940. asio::ssl::stream<asio::ip::tcp::socket> sslStream(io_service, context);
  941. SSLIOStreamDevice<asio::ip::tcp> d(sslStream, fUseSSL);
  942. iostreams::stream< SSLIOStreamDevice<asio::ip::tcp> > stream(d);
  943. if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", itostr(Params().RPCPort()))))
  944. throw runtime_error("couldn't connect to server");
  945. // HTTP basic authentication
  946. string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
  947. map<string, string> mapRequestHeaders;
  948. mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
  949. // Send request
  950. string strRequest = JSONRPCRequest(strMethod, params, 1);
  951. string strPost = HTTPPost(strRequest, mapRequestHeaders);
  952. stream << strPost << std::flush;
  953. // Receive HTTP reply status
  954. int nProto = 0;
  955. int nStatus = ReadHTTPStatus(stream, nProto);
  956. // Receive HTTP reply message headers and body
  957. map<string, string> mapHeaders;
  958. string strReply;
  959. ReadHTTPMessage(stream, mapHeaders, strReply, nProto);
  960. if (nStatus == HTTP_UNAUTHORIZED)
  961. throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
  962. else if (nStatus >= 400 && nStatus != HTTP_BAD_REQUEST && nStatus != HTTP_NOT_FOUND && nStatus != HTTP_INTERNAL_SERVER_ERROR)
  963. throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
  964. else if (strReply.empty())
  965. throw runtime_error("no response from server");
  966. // Parse reply
  967. Value valReply;
  968. if (!read_string(strReply, valReply))
  969. throw runtime_error("couldn't parse reply from server");
  970. const Object& reply = valReply.get_obj();
  971. if (reply.empty())
  972. throw runtime_error("expected reply to have result, error and id properties");
  973. return reply;
  974. }
  975. template<typename T>
  976. void ConvertTo(Value& value, bool fAllowNull=false)
  977. {
  978. if (fAllowNull && value.type() == null_type)
  979. return;
  980. if (value.type() == str_type)
  981. {
  982. // reinterpret string as unquoted json value
  983. Value value2;
  984. string strJSON = value.get_str();
  985. if (!read_string(strJSON, value2))
  986. throw runtime_error(string("Error parsing JSON:")+strJSON);
  987. ConvertTo<T>(value2, fAllowNull);
  988. value = value2;
  989. }
  990. else
  991. {
  992. value = value.get_value<T>();
  993. }
  994. }
  995. // Convert strings to command-specific RPC representation
  996. Array RPCConvertValues(const std::string &strMethod, const std::vector<std::string> &strParams)
  997. {
  998. Array params;
  999. BOOST_FOREACH(const std::string &param, strParams)
  1000. params.push_back(param);
  1001. int n = params.size();
  1002. //
  1003. // Special case non-string parameter types
  1004. //
  1005. if (strMethod == "stop" && n > 0) ConvertTo<bool>(params[0]);
  1006. if (strMethod == "getaddednodeinfo" && n > 0) ConvertTo<bool>(params[0]);
  1007. if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
  1008. if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
  1009. if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
  1010. if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
  1011. if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
  1012. if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo<boost::int64_t>(params[1]);
  1013. if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
  1014. if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo<bool>(params[1]);
  1015. if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]);
  1016. if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
  1017. if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]);
  1018. if (strMethod == "getblockhash" && n > 0) ConvertTo<boost::int64_t>(params[0]);
  1019. if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
  1020. if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
  1021. if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
  1022. if (strMethod == "sendfrom" && n > 3) ConvertTo<boost::int64_t>(params[3]);
  1023. if (strMethod == "listtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
  1024. if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
  1025. if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
  1026. if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]);
  1027. if (strMethod == "getblocktemplate" && n > 0) ConvertTo<Object>(params[0]);
  1028. if (strMethod == "listsinceblock" && n > 1) ConvertTo<boost::int64_t>(params[1]);
  1029. if (strMethod == "sendmany" && n > 1) ConvertTo<Object>(params[1]);
  1030. if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
  1031. if (strMethod == "addmultisigaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
  1032. if (strMethod == "addmultisigaddress" && n > 1) ConvertTo<Array>(params[1]);
  1033. if (strMethod == "createmultisig" && n > 0) ConvertTo<boost::int64_t>(params[0]);
  1034. if (strMethod == "createmultisig" && n > 1) ConvertTo<Array>(params[1]);
  1035. if (strMethod == "listunspent" && n > 0) ConvertTo<boost::int64_t>(params[0]);
  1036. if (strMethod == "listunspent" && n > 1) ConvertTo<boost::int64_t>(params[1]);
  1037. if (strMethod == "listunspent" && n > 2) ConvertTo<Array>(params[2]);
  1038. if (strMethod == "getblock" && n > 1) ConvertTo<bool>(params[1]);
  1039. if (strMethod == "getrawtransaction" && n > 1) ConvertTo<boost::int64_t>(params[1]);
  1040. if (strMethod == "createrawtransaction" && n > 0) ConvertTo<Array>(params[0]);
  1041. if (strMethod == "createrawtransaction" && n > 1) ConvertTo<Object>(params[1]);
  1042. if (strMethod == "signrawtransaction" && n > 1) ConvertTo<Array>(params[1], true);
  1043. if (strMethod == "signrawtransaction" && n > 2) ConvertTo<Array>(params[2], true);
  1044. if (strMethod == "gettxout" && n > 1) ConvertTo<boost::int64_t>(params[1]);
  1045. if (strMethod == "gettxout" && n > 2) ConvertTo<bool>(params[2]);
  1046. if (strMethod == "lockunspent" && n > 0) ConvertTo<bool>(params[0]);
  1047. if (strMethod == "lockunspent" && n > 1) ConvertTo<Array>(params[1]);
  1048. if (strMethod == "importprivkey" && n > 2) ConvertTo<bool>(params[2]);
  1049. return params;
  1050. }
  1051. int CommandLineRPC(int argc, char *argv[])
  1052. {
  1053. string strPrint;
  1054. int nRet = 0;
  1055. try
  1056. {
  1057. // Skip switches
  1058. while (argc > 1 && IsSwitchChar(argv[1][0]))
  1059. {
  1060. argc--;
  1061. argv++;
  1062. }
  1063. // Method
  1064. if (argc < 2)
  1065. throw runtime_error("too few parameters");
  1066. string strMethod = argv[1];
  1067. // Parameters default to strings
  1068. std::vector<std::string> strParams(&argv[2], &argv[argc]);
  1069. Array params = RPCConvertValues(strMethod, strParams);
  1070. // Execute
  1071. Object reply = CallRPC(strMethod, params);
  1072. // Parse reply
  1073. const Value& result = find_value(reply, "result");
  1074. const Value& error = find_value(reply, "error");
  1075. if (error.type() != null_type)
  1076. {
  1077. // Error
  1078. strPrint = "error: " + write_string(error, false);
  1079. int code = find_value(error.get_obj(), "code").get_int();
  1080. nRet = abs(code);
  1081. }
  1082. else
  1083. {
  1084. // Result
  1085. if (result.type() == null_type)
  1086. strPrint = "";
  1087. else if (result.type() == str_type)
  1088. strPrint = result.get_str();
  1089. else
  1090. strPrint = write_string(result, true);
  1091. }
  1092. }
  1093. catch (boost::thread_interrupted) {
  1094. throw;
  1095. }
  1096. catch (std::exception& e) {
  1097. strPrint = string("error: ") + e.what();
  1098. nRet = 87;
  1099. }
  1100. catch (...) {
  1101. PrintException(NULL, "CommandLineRPC()");
  1102. }
  1103. if (strPrint != "")
  1104. {
  1105. fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
  1106. }
  1107. return nRet;
  1108. }
  1109. #ifdef TEST
  1110. int main(int argc, char *argv[])
  1111. {
  1112. #ifdef _MSC_VER
  1113. // Turn off Microsoft heap dump noise
  1114. _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
  1115. _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
  1116. #endif
  1117. setbuf(stdin, NULL);
  1118. setbuf(stdout, NULL);
  1119. setbuf(stderr, NULL);
  1120. try
  1121. {
  1122. if (argc >= 2 && string(argv[1]) == "-server")
  1123. {
  1124. printf("server ready\n");
  1125. ThreadRPCServer(NULL);
  1126. }
  1127. else
  1128. {
  1129. return CommandLineRPC(argc, argv);
  1130. }
  1131. }
  1132. catch (boost::thread_interrupted) {
  1133. throw;
  1134. }
  1135. catch (std::exception& e) {
  1136. PrintException(&e, "main()");
  1137. } catch (...) {
  1138. PrintException(NULL, "main()");
  1139. }
  1140. return 0;
  1141. }
  1142. #endif
  1143. const CRPCTable tableRPC;