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.

client.cpp 7.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. // Copyright (c) 2010 Satoshi Nakamoto
  2. // Copyright (c) 2009-2016 The Bitcoin Core developers
  3. // Distributed under the MIT software license, see the accompanying
  4. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
  5. #include "rpc/client.h"
  6. #include "rpc/protocol.h"
  7. #include "util.h"
  8. #include <set>
  9. #include <stdint.h>
  10. #include <boost/algorithm/string/case_conv.hpp> // for to_lower()
  11. #include <univalue.h>
  12. using namespace std;
  13. class CRPCConvertParam
  14. {
  15. public:
  16. std::string methodName; //!< method whose params want conversion
  17. int paramIdx; //!< 0-based idx of param to convert
  18. std::string paramName; //!< parameter name
  19. };
  20. /**
  21. * Specify a (method, idx, name) here if the argument is a non-string RPC
  22. * argument and needs to be converted from JSON.
  23. *
  24. * @note Parameter indexes start from 0.
  25. */
  26. static const CRPCConvertParam vRPCConvertParams[] =
  27. {
  28. { "setmocktime", 0, "timestamp" },
  29. { "generate", 0, "nblocks" },
  30. { "generate", 1, "maxtries" },
  31. { "generatetoaddress", 0, "nblocks" },
  32. { "generatetoaddress", 2, "maxtries" },
  33. { "getnetworkhashps", 0, "nblocks" },
  34. { "getnetworkhashps", 1, "height" },
  35. { "sendtoaddress", 1, "amount" },
  36. { "sendtoaddress", 4, "subtractfeefromamount" },
  37. { "settxfee", 0, "amount" },
  38. { "getreceivedbyaddress", 1, "minconf" },
  39. { "getreceivedbyaccount", 1, "minconf" },
  40. { "listreceivedbyaddress", 0, "minconf" },
  41. { "listreceivedbyaddress", 1, "include_empty" },
  42. { "listreceivedbyaddress", 2, "include_watchonly" },
  43. { "listreceivedbyaccount", 0, "minconf" },
  44. { "listreceivedbyaccount", 1, "include_empty" },
  45. { "listreceivedbyaccount", 2, "include_watchonly" },
  46. { "getbalance", 1, "minconf" },
  47. { "getbalance", 2, "include_watchonly" },
  48. { "getblockhash", 0, "height" },
  49. { "waitforblockheight", 0, "height" },
  50. { "waitforblockheight", 1, "timeout" },
  51. { "waitforblock", 1, "timeout" },
  52. { "waitfornewblock", 0, "timeout" },
  53. { "move", 2, "amount" },
  54. { "move", 3, "minconf" },
  55. { "sendfrom", 2, "amount" },
  56. { "sendfrom", 3, "minconf" },
  57. { "listtransactions", 1, "count" },
  58. { "listtransactions", 2, "skip" },
  59. { "listtransactions", 3, "include_watchonly" },
  60. { "listaccounts", 0, "minconf" },
  61. { "listaccounts", 1, "include_watchonly" },
  62. { "walletpassphrase", 1, "timeout" },
  63. { "getblocktemplate", 0, "template_request" },
  64. { "listsinceblock", 1, "target_confirmations" },
  65. { "listsinceblock", 2, "include_watchonly" },
  66. { "sendmany", 1, "amounts" },
  67. { "sendmany", 2, "minconf" },
  68. { "sendmany", 4, "subtractfeefrom" },
  69. { "addmultisigaddress", 0, "nrequired" },
  70. { "addmultisigaddress", 1, "keys" },
  71. { "createmultisig", 0, "nrequired" },
  72. { "createmultisig", 1, "keys" },
  73. { "listunspent", 0, "minconf" },
  74. { "listunspent", 1, "maxconf" },
  75. { "listunspent", 2, "addresses" },
  76. { "getblock", 1, "verbose" },
  77. { "getblockheader", 1, "verbose" },
  78. { "gettransaction", 1, "include_watchonly" },
  79. { "getrawtransaction", 1, "verbose" },
  80. { "createrawtransaction", 0, "transactions" },
  81. { "createrawtransaction", 1, "outputs" },
  82. { "createrawtransaction", 2, "locktime" },
  83. { "signrawtransaction", 1, "prevtxs" },
  84. { "signrawtransaction", 2, "privkeys" },
  85. { "sendrawtransaction", 1, "allowhighfees" },
  86. { "fundrawtransaction", 1, "options" },
  87. { "gettxout", 1, "n" },
  88. { "gettxout", 2, "include_mempool" },
  89. { "gettxoutproof", 0, "txids" },
  90. { "lockunspent", 0, "unlock" },
  91. { "lockunspent", 1, "transactions" },
  92. { "importprivkey", 2, "rescan" },
  93. { "importaddress", 2, "rescan" },
  94. { "importaddress", 3, "p2sh" },
  95. { "importpubkey", 2, "rescan" },
  96. { "importmulti", 0, "requests" },
  97. { "importmulti", 1, "options" },
  98. { "verifychain", 0, "checklevel" },
  99. { "verifychain", 1, "nblocks" },
  100. { "pruneblockchain", 0, "height" },
  101. { "keypoolrefill", 0, "newsize" },
  102. { "getrawmempool", 0, "verbose" },
  103. { "estimatefee", 0, "nblocks" },
  104. { "estimatesmartfee", 0, "nblocks" },
  105. { "prioritisetransaction", 1, "fee_delta" },
  106. { "setban", 2, "bantime" },
  107. { "setban", 3, "absolute" },
  108. { "setnetworkactive", 0, "state" },
  109. { "getmempoolancestors", 1, "verbose" },
  110. { "getmempooldescendants", 1, "verbose" },
  111. { "bumpfee", 1, "options" },
  112. // Echo with conversion (For testing only)
  113. { "echojson", 0, "arg0" },
  114. { "echojson", 1, "arg1" },
  115. { "echojson", 2, "arg2" },
  116. { "echojson", 3, "arg3" },
  117. { "echojson", 4, "arg4" },
  118. { "echojson", 5, "arg5" },
  119. { "echojson", 6, "arg6" },
  120. { "echojson", 7, "arg7" },
  121. { "echojson", 8, "arg8" },
  122. { "echojson", 9, "arg9" },
  123. };
  124. class CRPCConvertTable
  125. {
  126. private:
  127. std::set<std::pair<std::string, int>> members;
  128. std::set<std::pair<std::string, std::string>> membersByName;
  129. public:
  130. CRPCConvertTable();
  131. bool convert(const std::string& method, int idx) {
  132. return (members.count(std::make_pair(method, idx)) > 0);
  133. }
  134. bool convert(const std::string& method, const std::string& name) {
  135. return (membersByName.count(std::make_pair(method, name)) > 0);
  136. }
  137. };
  138. CRPCConvertTable::CRPCConvertTable()
  139. {
  140. const unsigned int n_elem =
  141. (sizeof(vRPCConvertParams) / sizeof(vRPCConvertParams[0]));
  142. for (unsigned int i = 0; i < n_elem; i++) {
  143. members.insert(std::make_pair(vRPCConvertParams[i].methodName,
  144. vRPCConvertParams[i].paramIdx));
  145. membersByName.insert(std::make_pair(vRPCConvertParams[i].methodName,
  146. vRPCConvertParams[i].paramName));
  147. }
  148. }
  149. static CRPCConvertTable rpcCvtTable;
  150. /** Non-RFC4627 JSON parser, accepts internal values (such as numbers, true, false, null)
  151. * as well as objects and arrays.
  152. */
  153. UniValue ParseNonRFCJSONValue(const std::string& strVal)
  154. {
  155. UniValue jVal;
  156. if (!jVal.read(std::string("[")+strVal+std::string("]")) ||
  157. !jVal.isArray() || jVal.size()!=1)
  158. throw runtime_error(string("Error parsing JSON:")+strVal);
  159. return jVal[0];
  160. }
  161. UniValue RPCConvertValues(const std::string &strMethod, const std::vector<std::string> &strParams)
  162. {
  163. UniValue params(UniValue::VARR);
  164. for (unsigned int idx = 0; idx < strParams.size(); idx++) {
  165. const std::string& strVal = strParams[idx];
  166. if (!rpcCvtTable.convert(strMethod, idx)) {
  167. // insert string value directly
  168. params.push_back(strVal);
  169. } else {
  170. // parse string as JSON, insert bool/number/object/etc. value
  171. params.push_back(ParseNonRFCJSONValue(strVal));
  172. }
  173. }
  174. return params;
  175. }
  176. UniValue RPCConvertNamedValues(const std::string &strMethod, const std::vector<std::string> &strParams)
  177. {
  178. UniValue params(UniValue::VOBJ);
  179. for (const std::string &s: strParams) {
  180. size_t pos = s.find("=");
  181. if (pos == std::string::npos) {
  182. throw(std::runtime_error("No '=' in named argument '"+s+"', this needs to be present for every argument (even if it is empty)"));
  183. }
  184. std::string name = s.substr(0, pos);
  185. std::string value = s.substr(pos+1);
  186. if (!rpcCvtTable.convert(strMethod, name)) {
  187. // insert string value directly
  188. params.pushKV(name, value);
  189. } else {
  190. // parse string as JSON, insert bool/number/object/etc. value
  191. params.pushKV(name, ParseNonRFCJSONValue(value));
  192. }
  193. }
  194. return params;
  195. }