Master Core  v0.0.9 - 49a5c0d97abf09ef2911ddfe8d9551df59f9efd3-dirty
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
rpcclient.cpp
Go to the documentation of this file.
1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2013 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 
6 #include "rpcclient.h"
7 
8 #include "rpcprotocol.h"
9 #include "util.h"
10 #include "ui_interface.h"
11 #include "chainparams.h" // for Params().RPCPort()
12 
13 #include <stdint.h>
14 
15 #include <boost/algorithm/string.hpp>
16 #include <boost/asio.hpp>
17 #include <boost/asio/ssl.hpp>
18 #include <boost/bind.hpp>
19 #include <boost/filesystem.hpp>
20 #include <boost/foreach.hpp>
21 #include <boost/iostreams/concepts.hpp>
22 #include <boost/iostreams/stream.hpp>
23 #include <boost/shared_ptr.hpp>
24 #include "json/json_spirit_writer_template.h"
25 
26 using namespace std;
27 using namespace boost;
28 using namespace boost::asio;
29 using namespace json_spirit;
30 
31 Object CallRPC(const string& strMethod, const Array& params)
32 {
33  if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
34  throw runtime_error(strprintf(
35  _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
36  "If the file does not exist, create it with owner-readable-only file permissions."),
37  GetConfigFile().string().c_str()));
38 
39  // Connect to localhost
40  bool fUseSSL = GetBoolArg("-rpcssl", false);
41  asio::io_service io_service;
42  ssl::context context(io_service, ssl::context::sslv23);
43  context.set_options(ssl::context::no_sslv2);
44  asio::ssl::stream<asio::ip::tcp::socket> sslStream(io_service, context);
45  SSLIOStreamDevice<asio::ip::tcp> d(sslStream, fUseSSL);
46  iostreams::stream< SSLIOStreamDevice<asio::ip::tcp> > stream(d);
47 
48  bool fWait = GetBoolArg("-rpcwait", false); // -rpcwait means try until server has started
49  do {
50  bool fConnected = d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", itostr(Params().RPCPort())));
51  if (fConnected) break;
52  if (fWait)
53  MilliSleep(1000);
54  else
55  throw runtime_error("couldn't connect to server");
56  } while (fWait);
57 
58  // HTTP basic authentication
59  string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
60  map<string, string> mapRequestHeaders;
61  mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
62 
63  // Send request
64  string strRequest = JSONRPCRequest(strMethod, params, 1);
65  string strPost = HTTPPost(strRequest, mapRequestHeaders);
66  stream << strPost << std::flush;
67 
68  // Receive HTTP reply status
69  int nProto = 0;
70  int nStatus = ReadHTTPStatus(stream, nProto);
71 
72  // Receive HTTP reply message headers and body
73  map<string, string> mapHeaders;
74  string strReply;
75  ReadHTTPMessage(stream, mapHeaders, strReply, nProto);
76 
77  if (nStatus == HTTP_UNAUTHORIZED)
78  throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
79  else if (nStatus >= 400 && nStatus != HTTP_BAD_REQUEST && nStatus != HTTP_NOT_FOUND && nStatus != HTTP_INTERNAL_SERVER_ERROR)
80  throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
81  else if (strReply.empty())
82  throw runtime_error("no response from server");
83 
84  // Parse reply
85  Value valReply;
86  if (!read_string(strReply, valReply))
87  throw runtime_error("couldn't parse reply from server");
88  const Object& reply = valReply.get_obj();
89  if (reply.empty())
90  throw runtime_error("expected reply to have result, error and id properties");
91 
92  return reply;
93 }
94 
95 template<typename T>
96 void ConvertTo(Value& value, bool fAllowNull=false)
97 {
98  if (fAllowNull && value.type() == null_type)
99  return;
100  if (value.type() == str_type)
101  {
102  // reinterpret string as unquoted json value
103  Value value2;
104  string strJSON = value.get_str();
105  if (!read_string(strJSON, value2))
106  throw runtime_error(string("Error parsing JSON:")+strJSON);
107  ConvertTo<T>(value2, fAllowNull);
108  value = value2;
109  }
110  else
111  {
112  value = value.get_value<T>();
113  }
114 }
115 
116 // Convert strings to command-specific RPC representation
117 Array RPCConvertValues(const std::string &strMethod, const std::vector<std::string> &strParams)
118 {
119  Array params;
120  BOOST_FOREACH(const std::string &param, strParams)
121  params.push_back(param);
122 
123  int n = params.size();
124 
125  //
126  // Special case non-string parameter types
127  //
128  if (strMethod == "stop" && n > 0) ConvertTo<bool>(params[0]);
129  if (strMethod == "getaddednodeinfo" && n > 0) ConvertTo<bool>(params[0]);
130  if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
131  if (strMethod == "setgenerate" && n > 1) ConvertTo<int64_t>(params[1]);
132  if (strMethod == "getnetworkhashps" && n > 0) ConvertTo<int64_t>(params[0]);
133  if (strMethod == "getnetworkhashps" && n > 1) ConvertTo<int64_t>(params[1]);
134  if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
135  if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
136  if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<int64_t>(params[1]);
137  if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo<int64_t>(params[1]);
138  if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo<int64_t>(params[0]);
139  if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo<bool>(params[1]);
140  if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<int64_t>(params[0]);
141  if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
142  if (strMethod == "getbalance" && n > 1) ConvertTo<int64_t>(params[1]);
143  if (strMethod == "getblockhash" && n > 0) ConvertTo<int64_t>(params[0]);
144  if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
145  if (strMethod == "move" && n > 3) ConvertTo<int64_t>(params[3]);
146  if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
147  if (strMethod == "sendfrom" && n > 3) ConvertTo<int64_t>(params[3]);
148  if (strMethod == "listtransactions" && n > 1) ConvertTo<int64_t>(params[1]);
149  if (strMethod == "listtransactions" && n > 2) ConvertTo<int64_t>(params[2]);
150  if (strMethod == "listaccounts" && n > 0) ConvertTo<int64_t>(params[0]);
151  if (strMethod == "walletpassphrase" && n > 1) ConvertTo<int64_t>(params[1]);
152  if (strMethod == "getblocktemplate" && n > 0) ConvertTo<Object>(params[0]);
153  if (strMethod == "listsinceblock" && n > 1) ConvertTo<int64_t>(params[1]);
154  if (strMethod == "sendmany" && n > 1) ConvertTo<Object>(params[1]);
155  if (strMethod == "sendmany" && n > 2) ConvertTo<int64_t>(params[2]);
156  if (strMethod == "addmultisigaddress" && n > 0) ConvertTo<int64_t>(params[0]);
157  if (strMethod == "addmultisigaddress" && n > 1) ConvertTo<Array>(params[1]);
158  if (strMethod == "createmultisig" && n > 0) ConvertTo<int64_t>(params[0]);
159  if (strMethod == "createmultisig" && n > 1) ConvertTo<Array>(params[1]);
160  if (strMethod == "listunspent" && n > 0) ConvertTo<int64_t>(params[0]);
161  if (strMethod == "listunspent" && n > 1) ConvertTo<int64_t>(params[1]);
162  if (strMethod == "listunspent" && n > 2) ConvertTo<Array>(params[2]);
163  if (strMethod == "getblock" && n > 1) ConvertTo<bool>(params[1]);
164  if (strMethod == "getrawtransaction" && n > 1) ConvertTo<int64_t>(params[1]);
165  if (strMethod == "createrawtransaction" && n > 0) ConvertTo<Array>(params[0]);
166  if (strMethod == "createrawtransaction" && n > 1) ConvertTo<Object>(params[1]);
167  if (strMethod == "signrawtransaction" && n > 1) ConvertTo<Array>(params[1], true);
168  if (strMethod == "signrawtransaction" && n > 2) ConvertTo<Array>(params[2], true);
169  if (strMethod == "sendrawtransaction" && n > 1) ConvertTo<bool>(params[1], true);
170  if (strMethod == "gettxout" && n > 1) ConvertTo<int64_t>(params[1]);
171  if (strMethod == "gettxout" && n > 2) ConvertTo<bool>(params[2]);
172  if (strMethod == "lockunspent" && n > 0) ConvertTo<bool>(params[0]);
173  if (strMethod == "lockunspent" && n > 1) ConvertTo<Array>(params[1]);
174  if (strMethod == "importprivkey" && n > 2) ConvertTo<bool>(params[2]);
175  if (strMethod == "verifychain" && n > 0) ConvertTo<int64_t>(params[0]);
176  if (strMethod == "verifychain" && n > 1) ConvertTo<int64_t>(params[1]);
177  if (strMethod == "keypoolrefill" && n > 0) ConvertTo<int64_t>(params[0]);
178  if (strMethod == "getrawmempool" && n > 0) ConvertTo<bool>(params[0]);
179 
180  // master core conversions
181  if (strMethod == "getcrowdsale_MP" && n > 0) ConvertTo<int64_t>(params[0]);
182  if (strMethod == "getcrowdsale_MP" && n > 1) ConvertTo<bool>(params[1]);
183  if (strMethod == "getgrants_MP" && n > 0) ConvertTo<int64_t>(params[0]);
184  if (strMethod == "send_MP" && n > 2) ConvertTo<int64_t>(params[2]);
185  if (strMethod == "getbalance_MP" && n > 1) ConvertTo<int64_t>(params[1]);
186  if (strMethod == "sendtoowners_MP" && n > 1) ConvertTo<int64_t>(params[1]);
187  if (strMethod == "getproperty_MP" && n > 0) ConvertTo<int64_t>(params[0]);
188  if (strMethod == "listtransactions_MP" && n > 1) ConvertTo<int64_t>(params[1]);
189  if (strMethod == "listtransactions_MP" && n > 2) ConvertTo<int64_t>(params[2]);
190  if (strMethod == "listtransactions_MP" && n > 3) ConvertTo<int64_t>(params[3]);
191  if (strMethod == "listtransactions_MP" && n > 4) ConvertTo<int64_t>(params[4]);
192  if (strMethod == "getallbalancesforid_MP" && n > 0) ConvertTo<int64_t>(params[0]);
193  if (strMethod == "listblocktransactions_MP" && n > 0) ConvertTo<int64_t>(params[0]);
194 #if 0
195  if (strMethod == "trade_MP" && n > 2) ConvertTo<int64_t>(params[2]);
196  if (strMethod == "trade_MP" && n > 4) ConvertTo<int64_t>(params[4]);
197  if (strMethod == "trade_MP" && n > 5) ConvertTo<int64_t>(params[5]);
198  if (strMethod == "getorderbook_MP" && n > 0) ConvertTo<int64_t>(params[0]);
199  if (strMethod == "getorderbook_MP" && n > 1) ConvertTo<int64_t>(params[1]);
200  if (strMethod == "gettradessince_MP" && n > 0) ConvertTo<int64_t>(params[0]);
201  if (strMethod == "gettradessince_MP" && n > 1) ConvertTo<int64_t>(params[1]);
202  if (strMethod == "gettradessince_MP" && n > 2) ConvertTo<int64_t>(params[2]);
203  if (strMethod == "gettradehistory_MP" && n > 1) ConvertTo<int64_t>(params[1]);
204  if (strMethod == "gettradehistory_MP" && n > 2) ConvertTo<int64_t>(params[2]);
205 #endif
206 
207  return params;
208 }
209 
210 int CommandLineRPC(int argc, char *argv[])
211 {
212  string strPrint;
213  int nRet = 0;
214  try
215  {
216  // Skip switches
217  while (argc > 1 && IsSwitchChar(argv[1][0]))
218  {
219  argc--;
220  argv++;
221  }
222 
223  // Method
224  if (argc < 2)
225  throw runtime_error("too few parameters");
226  string strMethod = argv[1];
227 
228  // Parameters default to strings
229  std::vector<std::string> strParams(&argv[2], &argv[argc]);
230  Array params = RPCConvertValues(strMethod, strParams);
231 
232  // Execute
233  Object reply = CallRPC(strMethod, params);
234 
235  // Parse reply
236  const Value& result = find_value(reply, "result");
237  const Value& error = find_value(reply, "error");
238 
239  if (error.type() != null_type)
240  {
241  // Error
242  strPrint = "error: " + write_string(error, false);
243  int code = find_value(error.get_obj(), "code").get_int();
244  nRet = abs(code);
245  }
246  else
247  {
248  // Result
249  if (result.type() == null_type)
250  strPrint = "";
251  else if (result.type() == str_type)
252  strPrint = result.get_str();
253  else
254  strPrint = write_string(result, true);
255  }
256  }
257  catch (boost::thread_interrupted) {
258  throw;
259  }
260  catch (std::exception& e) {
261  strPrint = string("error: ") + e.what();
262  nRet = abs(RPC_MISC_ERROR);
263  }
264  catch (...) {
265  PrintExceptionContinue(NULL, "CommandLineRPC()");
266  throw;
267  }
268 
269  if (strPrint != "")
270  {
271  fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
272  }
273  return nRet;
274 }
275 
276 std::string HelpMessageCli(bool mainProgram)
277 {
278  string strUsage;
279  if(mainProgram)
280  {
281  strUsage += _("Options:") + "\n";
282  strUsage += " -? " + _("This help message") + "\n";
283  strUsage += " -conf=<file> " + _("Specify configuration file (default: bitcoin.conf)") + "\n";
284  strUsage += " -datadir=<dir> " + _("Specify data directory") + "\n";
285  strUsage += " -testnet " + _("Use the test network") + "\n";
286  strUsage += " -regtest " + _("Enter regression test mode, which uses a special chain in which blocks can be "
287  "solved instantly. This is intended for regression testing tools and app development.") + "\n";
288  } else {
289  strUsage += _("RPC client options:") + "\n";
290  }
291 
292  strUsage += " -rpcconnect=<ip> " + _("Send commands to node running on <ip> (default: 127.0.0.1)") + "\n";
293  strUsage += " -rpcport=<port> " + _("Connect to JSON-RPC on <port> (default: 8332 or testnet: 18332)") + "\n";
294  strUsage += " -rpcwait " + _("Wait for RPC server to start") + "\n";
295 
296  if(mainProgram)
297  {
298  strUsage += " -rpcuser=<user> " + _("Username for JSON-RPC connections") + "\n";
299  strUsage += " -rpcpassword=<pw> " + _("Password for JSON-RPC connections") + "\n";
300 
301  strUsage += "\n" + _("SSL options: (see the Bitcoin Wiki for SSL setup instructions)") + "\n";
302  strUsage += " -rpcssl " + _("Use OpenSSL (https) for JSON-RPC connections") + "\n";
303  }
304 
305  return strUsage;
306 }
307 
int ReadHTTPStatus(std::basic_istream< char > &stream, int &proto)
std::string HelpMessageCli(bool mainProgram)
Show help message for bitcoin-cli.
Definition: rpcclient.cpp:276
Definition: init.h:13
void MilliSleep(int64_t n)
Definition: util.h:79
void ConvertTo(Value &value, bool fAllowNull=false)
Definition: rpcclient.cpp:96
#define strprintf
Definition: util.h:116
STL namespace.
Object CallRPC(const string &strMethod, const Array &params)
Definition: rpcclient.cpp:31
string EncodeBase64(const unsigned char *pch, size_t len)
Definition: util.cpp:547
bool GetBoolArg(const std::string &strArg, bool fDefault)
Return boolean argument or default value.
Definition: util.cpp:519
int ReadHTTPMessage(std::basic_istream< char > &stream, map< string, string > &mapHeadersRet, string &strMessageRet, int nProto)
std::string itostr(int n)
Definition: util.h:219
static bool error(const char *format)
Definition: util.h:148
void PrintExceptionContinue(std::exception *pex, const char *pszThread)
Definition: util.cpp:933
int CommandLineRPC(int argc, char *argv[])
Definition: rpcclient.cpp:210
bool IsSwitchChar(char c)
Definition: util.h:332
const CChainParams & Params()
Return the currently selected parameters.
std::string _(const char *psz)
Translation function: Call Translate signal on UI interface, which returns a boost::optional result...
Definition: ui_interface.h:105
string HTTPPost(const string &strMsg, const map< string, string > &mapRequestHeaders)
Definition: rpcprotocol.cpp:35
std::string GetArg(const std::string &strArg, const std::string &strDefault)
Return string argument or default value.
Definition: util.cpp:505
string JSONRPCRequest(const string &strMethod, const Array &params, const Value &id)
bool connect(const std::string &server, const std::string &port)
Definition: rpcprotocol.h:104
Array RPCConvertValues(const std::string &strMethod, const std::vector< std::string > &strParams)
Definition: rpcclient.cpp:117
map< string, string > mapArgs
Definition: util.cpp:89
boost::filesystem::path GetConfigFile()
Definition: util.cpp:1012