1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2013 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.
6 #include "chainparamsbase.h"
7 #include "clientversion.h"
9 #include "rpcprotocol.h"
11 #include "utilstrencodings.h"
13 #include <boost/filesystem/operations.hpp>
16 using namespace json_spirit;
17 int64_t MAX_MONEY = 200000000 * 100000000LL;
18 uint64_t komodo_maxallowed(int32_t baseid) { return(100000000LL * 1000000); } // stub
20 std::string HelpMessageCli()
23 strUsage += HelpMessageGroup(_("Options:"));
24 strUsage += HelpMessageOpt("-?", _("This help message"));
25 strUsage += HelpMessageOpt("-conf=<file>", strprintf(_("Specify configuration file (default: %s)"), "komodo.conf"));
26 strUsage += HelpMessageOpt("-datadir=<dir>", _("Specify data directory"));
27 strUsage += HelpMessageOpt("-testnet", _("Use the test network"));
28 strUsage += HelpMessageOpt("-regtest", _("Enter regression test mode, which uses a special chain in which blocks can be "
29 "solved instantly. This is intended for regression testing tools and app development."));
30 strUsage += HelpMessageOpt("-rpcconnect=<ip>", strprintf(_("Send commands to node running on <ip> (default: %s)"), "127.0.0.1"));
31 strUsage += HelpMessageOpt("-rpcport=<port>", strprintf(_("Connect to JSON-RPC on <port> (default: %u or testnet: %u)"), 8232, 18232));
32 strUsage += HelpMessageOpt("-rpcwait", _("Wait for RPC server to start"));
33 strUsage += HelpMessageOpt("-rpcuser=<user>", _("Username for JSON-RPC connections"));
34 strUsage += HelpMessageOpt("-rpcpassword=<pw>", _("Password for JSON-RPC connections"));
36 strUsage += HelpMessageGroup(_("SSL options: (see the Bitcoin Wiki for SSL setup instructions)"));
37 strUsage += HelpMessageOpt("-rpcssl", _("Use OpenSSL (https) for JSON-RPC connections"));
42 //////////////////////////////////////////////////////////////////////////////
48 // Exception thrown on connection error. This error is used to determine
49 // when to wait if -rpcwait is given.
51 class CConnectionFailed : public std::runtime_error
55 explicit inline CConnectionFailed(const std::string& msg) :
56 std::runtime_error(msg)
62 #include "arith_uint256.h"
64 #include "komodo_structs.h"
66 #include "komodo_globals.h"
67 #include "komodo_utils.h"
69 #include "komodo_notary.h"
71 void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotaries,uint8_t notaryid,uint256 txhash,uint64_t voutmask,uint8_t numvouts,uint32_t *pvals,uint8_t numpvals,int32_t KMDheight,uint32_t KMDtimestamp,uint64_t opretvalue,uint8_t *opretbuf,uint16_t opretlen,uint16_t vout)
76 static bool AppInitRPC(int argc, char* argv[])
81 ParseParameters(argc, argv);
83 if (argc<2 || mapArgs.count("-?") || mapArgs.count("-h") || mapArgs.count("-help") || mapArgs.count("-version")) {
84 std::string strUsage = _("Komodo RPC client version") + " " + FormatFullVersion() + "\n";
85 if (!mapArgs.count("-version")) {
86 strUsage += "\n" + _("Usage:") + "\n" +
87 " komodo-cli [options] <command> [params] " + _("Send command to Komodo") + "\n" +
88 " komodo-cli [options] help " + _("List commands") + "\n" +
89 " komodo-cli [options] help <command> " + _("Get help for a command") + "\n";
91 strUsage += "\n" + HelpMessageCli();
93 strUsage += LicenseInfo();
96 fprintf(stdout, "%s", strUsage.c_str());
99 if (!boost::filesystem::is_directory(GetDataDir(false))) {
100 fprintf(stderr, "Error: Specified data directory \"%s\" does not exist.\n", mapArgs["-datadir"].c_str());
104 ReadConfigFile(mapArgs, mapMultiArgs);
105 } catch (const std::exception& e) {
106 fprintf(stderr,"Error reading configuration file: %s\n", e.what());
109 // Check for -testnet or -regtest parameter (BaseParams() calls are only valid after this clause)
110 if (!SelectBaseParamsFromCommandLine()) {
111 fprintf(stderr, "Error: Invalid combination of -regtest and -testnet.\n");
117 Object CallRPC(const string& strMethod, const Array& params)
119 // Connect to localhost
120 bool fUseSSL = GetBoolArg("-rpcssl", false);
121 boost::asio::io_service io_service;
122 boost::asio::ssl::context context(io_service, boost::asio::ssl::context::sslv23);
123 context.set_options(boost::asio::ssl::context::no_sslv2 | boost::asio::ssl::context::no_sslv3);
124 boost::asio::ssl::stream<boost::asio::ip::tcp::socket> sslStream(io_service, context);
125 SSLIOStreamDevice<boost::asio::ip::tcp> d(sslStream, fUseSSL);
126 boost::iostreams::stream< SSLIOStreamDevice<boost::asio::ip::tcp> > stream(d);
128 const bool fConnected = d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", itostr(BaseParams().RPCPort())));
130 throw CConnectionFailed("couldn't connect to server");
132 // Find credentials to use
133 std::string strRPCUserColonPass;
134 if (mapArgs["-rpcpassword"] == "") {
135 // Try fall back to cookie-based authentication if no password is provided
136 if (!GetAuthCookie(&strRPCUserColonPass)) {
137 throw runtime_error(strprintf(
138 _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
139 "If the file does not exist, create it with owner-readable-only file permissions."),
140 GetConfigFile().string().c_str()));
144 strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
147 // HTTP basic authentication
148 map<string, string> mapRequestHeaders;
149 mapRequestHeaders["Authorization"] = string("Basic ") + EncodeBase64(strRPCUserColonPass);
152 string strRequest = JSONRPCRequest(strMethod, params, 1);
153 string strPost = HTTPPost(strRequest, mapRequestHeaders);
154 stream << strPost << std::flush;
156 // Receive HTTP reply status
158 int nStatus = ReadHTTPStatus(stream, nProto);
160 // Receive HTTP reply message headers and body
161 map<string, string> mapHeaders;
163 ReadHTTPMessage(stream, mapHeaders, strReply, nProto, std::numeric_limits<size_t>::max());
165 if (nStatus == HTTP_UNAUTHORIZED)
166 throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
167 else if (nStatus >= 400 && nStatus != HTTP_BAD_REQUEST && nStatus != HTTP_NOT_FOUND && nStatus != HTTP_INTERNAL_SERVER_ERROR)
168 throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
169 else if (strReply.empty())
170 throw runtime_error("no response from server");
174 if (!read_string(strReply, valReply))
175 throw runtime_error("couldn't parse reply from server");
176 const Object& reply = valReply.get_obj();
178 throw runtime_error("expected reply to have result, error and id properties");
183 int CommandLineRPC(int argc, char *argv[])
189 while (argc > 1 && IsSwitchChar(argv[1][0])) {
196 throw runtime_error("too few parameters");
197 string strMethod = argv[1];
199 // Parameters default to strings
200 std::vector<std::string> strParams(&argv[2], &argv[argc]);
201 Array params = RPCConvertValues(strMethod, strParams);
203 // Execute and handle connection failures with -rpcwait
204 const bool fWait = GetBoolArg("-rpcwait", false);
207 const Object reply = CallRPC(strMethod, params);
210 const Value& result = find_value(reply, "result");
211 const Value& error = find_value(reply, "error");
213 if (error.type() != null_type) {
215 const int code = find_value(error.get_obj(), "code").get_int();
216 if (fWait && code == RPC_IN_WARMUP)
217 throw CConnectionFailed("server in warmup");
218 strPrint = "error: " + write_string(error, false);
222 if (result.type() == null_type)
224 else if (result.type() == str_type)
225 strPrint = result.get_str();
227 strPrint = write_string(result, true);
230 // Connection succeeded, no need to retry.
233 catch (const CConnectionFailed&) {
241 catch (const boost::thread_interrupted&) {
244 catch (const std::exception& e) {
245 strPrint = string("error: ") + e.what();
249 PrintExceptionContinue(NULL, "CommandLineRPC()");
253 if (strPrint != "") {
254 fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
259 int main(int argc, char* argv[])
264 if(!AppInitRPC(argc, argv))
267 catch (const std::exception& e) {
268 PrintExceptionContinue(&e, "AppInitRPC()");
271 PrintExceptionContinue(NULL, "AppInitRPC()");
275 int ret = EXIT_FAILURE;
277 ret = CommandLineRPC(argc, argv);
279 catch (const std::exception& e) {
280 PrintExceptionContinue(&e, "CommandLineRPC()");
282 PrintExceptionContinue(NULL, "CommandLineRPC()");