]> Git Repo - VerusCoin.git/blob - src/rpcclient.cpp
bitcoin-cli: remove unneeded dependencies (only code movement)
[VerusCoin.git] / src / rpcclient.cpp
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/lexical_cast.hpp>
24 #include <boost/shared_ptr.hpp>
25 #include "json/json_spirit_writer_template.h"
26
27 using namespace std;
28 using namespace boost;
29 using namespace boost::asio;
30 using namespace json_spirit;
31
32 Object CallRPC(const string& strMethod, const Array& params)
33 {
34     if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
35         throw runtime_error(strprintf(
36             _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
37               "If the file does not exist, create it with owner-readable-only file permissions."),
38                 GetConfigFile().string().c_str()));
39
40     // Connect to localhost
41     bool fUseSSL = GetBoolArg("-rpcssl", false);
42     asio::io_service io_service;
43     ssl::context context(io_service, ssl::context::sslv23);
44     context.set_options(ssl::context::no_sslv2);
45     asio::ssl::stream<asio::ip::tcp::socket> sslStream(io_service, context);
46     SSLIOStreamDevice<asio::ip::tcp> d(sslStream, fUseSSL);
47     iostreams::stream< SSLIOStreamDevice<asio::ip::tcp> > stream(d);
48
49     bool fWait = GetBoolArg("-rpcwait", false); // -rpcwait means try until server has started
50     do {
51         bool fConnected = d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", itostr(Params().RPCPort())));
52         if (fConnected) break;
53         if (fWait)
54             MilliSleep(1000);
55         else
56             throw runtime_error("couldn't connect to server");
57     } while (fWait);
58
59     // HTTP basic authentication
60     string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
61     map<string, string> mapRequestHeaders;
62     mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
63
64     // Send request
65     string strRequest = JSONRPCRequest(strMethod, params, 1);
66     string strPost = HTTPPost(strRequest, mapRequestHeaders);
67     stream << strPost << std::flush;
68
69     // Receive HTTP reply status
70     int nProto = 0;
71     int nStatus = ReadHTTPStatus(stream, nProto);
72
73     // Receive HTTP reply message headers and body
74     map<string, string> mapHeaders;
75     string strReply;
76     ReadHTTPMessage(stream, mapHeaders, strReply, nProto);
77
78     if (nStatus == HTTP_UNAUTHORIZED)
79         throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
80     else if (nStatus >= 400 && nStatus != HTTP_BAD_REQUEST && nStatus != HTTP_NOT_FOUND && nStatus != HTTP_INTERNAL_SERVER_ERROR)
81         throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
82     else if (strReply.empty())
83         throw runtime_error("no response from server");
84
85     // Parse reply
86     Value valReply;
87     if (!read_string(strReply, valReply))
88         throw runtime_error("couldn't parse reply from server");
89     const Object& reply = valReply.get_obj();
90     if (reply.empty())
91         throw runtime_error("expected reply to have result, error and id properties");
92
93     return reply;
94 }
95
96 template<typename T>
97 void ConvertTo(Value& value, bool fAllowNull=false)
98 {
99     if (fAllowNull && value.type() == null_type)
100         return;
101     if (value.type() == str_type)
102     {
103         // reinterpret string as unquoted json value
104         Value value2;
105         string strJSON = value.get_str();
106         if (!read_string(strJSON, value2))
107             throw runtime_error(string("Error parsing JSON:")+strJSON);
108         ConvertTo<T>(value2, fAllowNull);
109         value = value2;
110     }
111     else
112     {
113         value = value.get_value<T>();
114     }
115 }
116
117 // Convert strings to command-specific RPC representation
118 Array RPCConvertValues(const std::string &strMethod, const std::vector<std::string> &strParams)
119 {
120     Array params;
121     BOOST_FOREACH(const std::string &param, strParams)
122         params.push_back(param);
123
124     int n = params.size();
125
126     //
127     // Special case non-string parameter types
128     //
129     if (strMethod == "stop"                   && n > 0) ConvertTo<bool>(params[0]);
130     if (strMethod == "getaddednodeinfo"       && n > 0) ConvertTo<bool>(params[0]);
131     if (strMethod == "setgenerate"            && n > 0) ConvertTo<bool>(params[0]);
132     if (strMethod == "setgenerate"            && n > 1) ConvertTo<boost::int64_t>(params[1]);
133     if (strMethod == "getnetworkhashps"       && n > 0) ConvertTo<boost::int64_t>(params[0]);
134     if (strMethod == "getnetworkhashps"       && n > 1) ConvertTo<boost::int64_t>(params[1]);
135     if (strMethod == "sendtoaddress"          && n > 1) ConvertTo<double>(params[1]);
136     if (strMethod == "settxfee"               && n > 0) ConvertTo<double>(params[0]);
137     if (strMethod == "getreceivedbyaddress"   && n > 1) ConvertTo<boost::int64_t>(params[1]);
138     if (strMethod == "getreceivedbyaccount"   && n > 1) ConvertTo<boost::int64_t>(params[1]);
139     if (strMethod == "listreceivedbyaddress"  && n > 0) ConvertTo<boost::int64_t>(params[0]);
140     if (strMethod == "listreceivedbyaddress"  && n > 1) ConvertTo<bool>(params[1]);
141     if (strMethod == "listreceivedbyaccount"  && n > 0) ConvertTo<boost::int64_t>(params[0]);
142     if (strMethod == "listreceivedbyaccount"  && n > 1) ConvertTo<bool>(params[1]);
143     if (strMethod == "getbalance"             && n > 1) ConvertTo<boost::int64_t>(params[1]);
144     if (strMethod == "getblockhash"           && n > 0) ConvertTo<boost::int64_t>(params[0]);
145     if (strMethod == "move"                   && n > 2) ConvertTo<double>(params[2]);
146     if (strMethod == "move"                   && n > 3) ConvertTo<boost::int64_t>(params[3]);
147     if (strMethod == "sendfrom"               && n > 2) ConvertTo<double>(params[2]);
148     if (strMethod == "sendfrom"               && n > 3) ConvertTo<boost::int64_t>(params[3]);
149     if (strMethod == "listtransactions"       && n > 1) ConvertTo<boost::int64_t>(params[1]);
150     if (strMethod == "listtransactions"       && n > 2) ConvertTo<boost::int64_t>(params[2]);
151     if (strMethod == "listaccounts"           && n > 0) ConvertTo<boost::int64_t>(params[0]);
152     if (strMethod == "walletpassphrase"       && n > 1) ConvertTo<boost::int64_t>(params[1]);
153     if (strMethod == "getblocktemplate"       && n > 0) ConvertTo<Object>(params[0]);
154     if (strMethod == "listsinceblock"         && n > 1) ConvertTo<boost::int64_t>(params[1]);
155     if (strMethod == "sendmany"               && n > 1) ConvertTo<Object>(params[1]);
156     if (strMethod == "sendmany"               && n > 2) ConvertTo<boost::int64_t>(params[2]);
157     if (strMethod == "addmultisigaddress"     && n > 0) ConvertTo<boost::int64_t>(params[0]);
158     if (strMethod == "addmultisigaddress"     && n > 1) ConvertTo<Array>(params[1]);
159     if (strMethod == "createmultisig"         && n > 0) ConvertTo<boost::int64_t>(params[0]);
160     if (strMethod == "createmultisig"         && n > 1) ConvertTo<Array>(params[1]);
161     if (strMethod == "listunspent"            && n > 0) ConvertTo<boost::int64_t>(params[0]);
162     if (strMethod == "listunspent"            && n > 1) ConvertTo<boost::int64_t>(params[1]);
163     if (strMethod == "listunspent"            && n > 2) ConvertTo<Array>(params[2]);
164     if (strMethod == "getblock"               && n > 1) ConvertTo<bool>(params[1]);
165     if (strMethod == "getrawtransaction"      && n > 1) ConvertTo<boost::int64_t>(params[1]);
166     if (strMethod == "createrawtransaction"   && n > 0) ConvertTo<Array>(params[0]);
167     if (strMethod == "createrawtransaction"   && n > 1) ConvertTo<Object>(params[1]);
168     if (strMethod == "signrawtransaction"     && n > 1) ConvertTo<Array>(params[1], true);
169     if (strMethod == "signrawtransaction"     && n > 2) ConvertTo<Array>(params[2], true);
170     if (strMethod == "sendrawtransaction"     && n > 1) ConvertTo<bool>(params[1], true);
171     if (strMethod == "gettxout"               && n > 1) ConvertTo<boost::int64_t>(params[1]);
172     if (strMethod == "gettxout"               && n > 2) ConvertTo<bool>(params[2]);
173     if (strMethod == "lockunspent"            && n > 0) ConvertTo<bool>(params[0]);
174     if (strMethod == "lockunspent"            && n > 1) ConvertTo<Array>(params[1]);
175     if (strMethod == "importprivkey"          && n > 2) ConvertTo<bool>(params[2]);
176     if (strMethod == "verifychain"            && n > 0) ConvertTo<boost::int64_t>(params[0]);
177     if (strMethod == "verifychain"            && n > 1) ConvertTo<boost::int64_t>(params[1]);
178     if (strMethod == "keypoolrefill"          && n > 0) ConvertTo<boost::int64_t>(params[0]);
179
180     return params;
181 }
182
183 int CommandLineRPC(int argc, char *argv[])
184 {
185     string strPrint;
186     int nRet = 0;
187     try
188     {
189         // Skip switches
190         while (argc > 1 && IsSwitchChar(argv[1][0]))
191         {
192             argc--;
193             argv++;
194         }
195
196         // Method
197         if (argc < 2)
198             throw runtime_error("too few parameters");
199         string strMethod = argv[1];
200
201         // Parameters default to strings
202         std::vector<std::string> strParams(&argv[2], &argv[argc]);
203         Array params = RPCConvertValues(strMethod, strParams);
204
205         // Execute
206         Object reply = CallRPC(strMethod, params);
207
208         // Parse reply
209         const Value& result = find_value(reply, "result");
210         const Value& error  = find_value(reply, "error");
211
212         if (error.type() != null_type)
213         {
214             // Error
215             strPrint = "error: " + write_string(error, false);
216             int code = find_value(error.get_obj(), "code").get_int();
217             nRet = abs(code);
218         }
219         else
220         {
221             // Result
222             if (result.type() == null_type)
223                 strPrint = "";
224             else if (result.type() == str_type)
225                 strPrint = result.get_str();
226             else
227                 strPrint = write_string(result, true);
228         }
229     }
230     catch (boost::thread_interrupted) {
231         throw;
232     }
233     catch (std::exception& e) {
234         strPrint = string("error: ") + e.what();
235         nRet = 87;
236     }
237     catch (...) {
238         PrintException(NULL, "CommandLineRPC()");
239     }
240
241     if (strPrint != "")
242     {
243         fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
244     }
245     return nRet;
246 }
247
248 std::string HelpMessageCli(bool mainProgram)
249 {
250     string strUsage;
251     if(mainProgram)
252     {
253         strUsage += _("Options:") + "\n";
254         strUsage += "  -?                     " + _("This help message") + "\n";
255         strUsage += "  -conf=<file>           " + _("Specify configuration file (default: bitcoin.conf)") + "\n";
256         strUsage += "  -datadir=<dir>         " + _("Specify data directory") + "\n";
257         strUsage += "  -testnet               " + _("Use the test network") + "\n";
258         strUsage += "  -regtest               " + _("Enter regression test mode, which uses a special chain in which blocks can be "
259                                             "solved instantly. This is intended for regression testing tools and app development.") + "\n";
260     } else {
261         strUsage += _("RPC client options:") + "\n";
262     }
263
264     strUsage += "  -rpcconnect=<ip>       " + _("Send commands to node running on <ip> (default: 127.0.0.1)") + "\n";
265     strUsage += "  -rpcport=<port>        " + _("Connect to JSON-RPC on <port> (default: 8332 or testnet: 18332)") + "\n";
266     strUsage += "  -rpcwait               " + _("Wait for RPC server to start") + "\n";
267     strUsage += "  -rpcuser=<user>        " + _("Username for JSON-RPC connections") + "\n";
268     strUsage += "  -rpcpassword=<pw>      " + _("Password for JSON-RPC connections") + "\n";
269
270     if(mainProgram)
271     {
272         strUsage += "\n" + _("SSL options: (see the Bitcoin Wiki for SSL setup instructions)") + "\n";
273         strUsage += "  -rpcssl                " + _("Use OpenSSL (https) for JSON-RPC connections") + "\n";
274     }
275
276     return strUsage;
277 }
278
This page took 0.040451 seconds and 4 git commands to generate.