[trivial] Fix recently introduced typos in comments
[bitcoinplatinum.git] / src / rpc / misc.cpp
blob45a5896da1b78ca44c2476cf701456b3b1755ae7
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.
6 #include "base58.h"
7 #include "clientversion.h"
8 #include "init.h"
9 #include "validation.h"
10 #include "net.h"
11 #include "netbase.h"
12 #include "rpc/server.h"
13 #include "timedata.h"
14 #include "util.h"
15 #include "utilstrencodings.h"
16 #ifdef ENABLE_WALLET
17 #include "wallet/wallet.h"
18 #include "wallet/walletdb.h"
19 #endif
21 #include <stdint.h>
23 #include <boost/assign/list_of.hpp>
25 #include <univalue.h>
27 using namespace std;
29 /**
30 * @note Do not add or change anything in the information returned by this
31 * method. `getinfo` exists for backwards-compatibility only. It combines
32 * information from wildly different sources in the program, which is a mess,
33 * and is thus planned to be deprecated eventually.
35 * Based on the source of the information, new information should be added to:
36 * - `getblockchaininfo`,
37 * - `getnetworkinfo` or
38 * - `getwalletinfo`
40 * Or alternatively, create a specific query method for the information.
41 **/
42 UniValue getinfo(const JSONRPCRequest& request)
44 if (request.fHelp || request.params.size() != 0)
45 throw runtime_error(
46 "getinfo\n"
47 "\nDEPRECATED. Returns an object containing various state info.\n"
48 "\nResult:\n"
49 "{\n"
50 " \"version\": xxxxx, (numeric) the server version\n"
51 " \"protocolversion\": xxxxx, (numeric) the protocol version\n"
52 " \"walletversion\": xxxxx, (numeric) the wallet version\n"
53 " \"balance\": xxxxxxx, (numeric) the total bitcoin balance of the wallet\n"
54 " \"blocks\": xxxxxx, (numeric) the current number of blocks processed in the server\n"
55 " \"timeoffset\": xxxxx, (numeric) the time offset\n"
56 " \"connections\": xxxxx, (numeric) the number of connections\n"
57 " \"proxy\": \"host:port\", (string, optional) the proxy used by the server\n"
58 " \"difficulty\": xxxxxx, (numeric) the current difficulty\n"
59 " \"testnet\": true|false, (boolean) if the server is using testnet or not\n"
60 " \"keypoololdest\": xxxxxx, (numeric) the timestamp (seconds since Unix epoch) of the oldest pre-generated key in the key pool\n"
61 " \"keypoolsize\": xxxx, (numeric) how many new keys are pre-generated\n"
62 " \"unlocked_until\": ttt, (numeric) the timestamp in seconds since epoch (midnight Jan 1 1970 GMT) that the wallet is unlocked for transfers, or 0 if the wallet is locked\n"
63 " \"paytxfee\": x.xxxx, (numeric) the transaction fee set in " + CURRENCY_UNIT + "/kB\n"
64 " \"relayfee\": x.xxxx, (numeric) minimum relay fee for non-free transactions in " + CURRENCY_UNIT + "/kB\n"
65 " \"errors\": \"...\" (string) any error messages\n"
66 "}\n"
67 "\nExamples:\n"
68 + HelpExampleCli("getinfo", "")
69 + HelpExampleRpc("getinfo", "")
72 #ifdef ENABLE_WALLET
73 LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL);
74 #else
75 LOCK(cs_main);
76 #endif
78 proxyType proxy;
79 GetProxy(NET_IPV4, proxy);
81 UniValue obj(UniValue::VOBJ);
82 obj.push_back(Pair("version", CLIENT_VERSION));
83 obj.push_back(Pair("protocolversion", PROTOCOL_VERSION));
84 #ifdef ENABLE_WALLET
85 if (pwalletMain) {
86 obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
87 obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
89 #endif
90 obj.push_back(Pair("blocks", (int)chainActive.Height()));
91 obj.push_back(Pair("timeoffset", GetTimeOffset()));
92 if(g_connman)
93 obj.push_back(Pair("connections", (int)g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL)));
94 obj.push_back(Pair("proxy", (proxy.IsValid() ? proxy.proxy.ToStringIPPort() : string())));
95 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
96 obj.push_back(Pair("testnet", Params().NetworkIDString() == CBaseChainParams::TESTNET));
97 #ifdef ENABLE_WALLET
98 if (pwalletMain) {
99 obj.push_back(Pair("keypoololdest", pwalletMain->GetOldestKeyPoolTime()));
100 obj.push_back(Pair("keypoolsize", (int)pwalletMain->GetKeyPoolSize()));
102 if (pwalletMain && pwalletMain->IsCrypted())
103 obj.push_back(Pair("unlocked_until", nWalletUnlockTime));
104 obj.push_back(Pair("paytxfee", ValueFromAmount(payTxFee.GetFeePerK())));
105 #endif
106 obj.push_back(Pair("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK())));
107 obj.push_back(Pair("errors", GetWarnings("statusbar")));
108 return obj;
111 #ifdef ENABLE_WALLET
112 class DescribeAddressVisitor : public boost::static_visitor<UniValue>
114 public:
115 UniValue operator()(const CNoDestination &dest) const { return UniValue(UniValue::VOBJ); }
117 UniValue operator()(const CKeyID &keyID) const {
118 UniValue obj(UniValue::VOBJ);
119 CPubKey vchPubKey;
120 obj.push_back(Pair("isscript", false));
121 if (pwalletMain && pwalletMain->GetPubKey(keyID, vchPubKey)) {
122 obj.push_back(Pair("pubkey", HexStr(vchPubKey)));
123 obj.push_back(Pair("iscompressed", vchPubKey.IsCompressed()));
125 return obj;
128 UniValue operator()(const CScriptID &scriptID) const {
129 UniValue obj(UniValue::VOBJ);
130 CScript subscript;
131 obj.push_back(Pair("isscript", true));
132 if (pwalletMain && pwalletMain->GetCScript(scriptID, subscript)) {
133 std::vector<CTxDestination> addresses;
134 txnouttype whichType;
135 int nRequired;
136 ExtractDestinations(subscript, whichType, addresses, nRequired);
137 obj.push_back(Pair("script", GetTxnOutputType(whichType)));
138 obj.push_back(Pair("hex", HexStr(subscript.begin(), subscript.end())));
139 UniValue a(UniValue::VARR);
140 BOOST_FOREACH(const CTxDestination& addr, addresses)
141 a.push_back(CBitcoinAddress(addr).ToString());
142 obj.push_back(Pair("addresses", a));
143 if (whichType == TX_MULTISIG)
144 obj.push_back(Pair("sigsrequired", nRequired));
146 return obj;
149 #endif
151 UniValue validateaddress(const JSONRPCRequest& request)
153 if (request.fHelp || request.params.size() != 1)
154 throw runtime_error(
155 "validateaddress \"address\"\n"
156 "\nReturn information about the given bitcoin address.\n"
157 "\nArguments:\n"
158 "1. \"address\" (string, required) The bitcoin address to validate\n"
159 "\nResult:\n"
160 "{\n"
161 " \"isvalid\" : true|false, (boolean) If the address is valid or not. If not, this is the only property returned.\n"
162 " \"address\" : \"address\", (string) The bitcoin address validated\n"
163 " \"scriptPubKey\" : \"hex\", (string) The hex encoded scriptPubKey generated by the address\n"
164 " \"ismine\" : true|false, (boolean) If the address is yours or not\n"
165 " \"iswatchonly\" : true|false, (boolean) If the address is watchonly\n"
166 " \"isscript\" : true|false, (boolean) If the key is a script\n"
167 " \"pubkey\" : \"publickeyhex\", (string) The hex value of the raw public key\n"
168 " \"iscompressed\" : true|false, (boolean) If the address is compressed\n"
169 " \"account\" : \"account\" (string) DEPRECATED. The account associated with the address, \"\" is the default account\n"
170 " \"hdkeypath\" : \"keypath\" (string, optional) The HD keypath if the key is HD and available\n"
171 " \"hdmasterkeyid\" : \"<hash160>\" (string, optional) The Hash160 of the HD master pubkey\n"
172 "}\n"
173 "\nExamples:\n"
174 + HelpExampleCli("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
175 + HelpExampleRpc("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
178 #ifdef ENABLE_WALLET
179 LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL);
180 #else
181 LOCK(cs_main);
182 #endif
184 CBitcoinAddress address(request.params[0].get_str());
185 bool isValid = address.IsValid();
187 UniValue ret(UniValue::VOBJ);
188 ret.push_back(Pair("isvalid", isValid));
189 if (isValid)
191 CTxDestination dest = address.Get();
192 string currentAddress = address.ToString();
193 ret.push_back(Pair("address", currentAddress));
195 CScript scriptPubKey = GetScriptForDestination(dest);
196 ret.push_back(Pair("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end())));
198 #ifdef ENABLE_WALLET
199 isminetype mine = pwalletMain ? IsMine(*pwalletMain, dest) : ISMINE_NO;
200 ret.push_back(Pair("ismine", (mine & ISMINE_SPENDABLE) ? true : false));
201 ret.push_back(Pair("iswatchonly", (mine & ISMINE_WATCH_ONLY) ? true: false));
202 UniValue detail = boost::apply_visitor(DescribeAddressVisitor(), dest);
203 ret.pushKVs(detail);
204 if (pwalletMain && pwalletMain->mapAddressBook.count(dest))
205 ret.push_back(Pair("account", pwalletMain->mapAddressBook[dest].name));
206 CKeyID keyID;
207 if (pwalletMain && address.GetKeyID(keyID) && pwalletMain->mapKeyMetadata.count(keyID) && !pwalletMain->mapKeyMetadata[keyID].hdKeypath.empty())
209 ret.push_back(Pair("hdkeypath", pwalletMain->mapKeyMetadata[keyID].hdKeypath));
210 ret.push_back(Pair("hdmasterkeyid", pwalletMain->mapKeyMetadata[keyID].hdMasterKeyID.GetHex()));
212 #endif
214 return ret;
218 * Used by addmultisigaddress / createmultisig:
220 CScript _createmultisig_redeemScript(const UniValue& params)
222 int nRequired = params[0].get_int();
223 const UniValue& keys = params[1].get_array();
225 // Gather public keys
226 if (nRequired < 1)
227 throw runtime_error("a multisignature address must require at least one key to redeem");
228 if ((int)keys.size() < nRequired)
229 throw runtime_error(
230 strprintf("not enough keys supplied "
231 "(got %u keys, but need at least %d to redeem)", keys.size(), nRequired));
232 if (keys.size() > 16)
233 throw runtime_error("Number of addresses involved in the multisignature address creation > 16\nReduce the number");
234 std::vector<CPubKey> pubkeys;
235 pubkeys.resize(keys.size());
236 for (unsigned int i = 0; i < keys.size(); i++)
238 const std::string& ks = keys[i].get_str();
239 #ifdef ENABLE_WALLET
240 // Case 1: Bitcoin address and we have full public key:
241 CBitcoinAddress address(ks);
242 if (pwalletMain && address.IsValid())
244 CKeyID keyID;
245 if (!address.GetKeyID(keyID))
246 throw runtime_error(
247 strprintf("%s does not refer to a key",ks));
248 CPubKey vchPubKey;
249 if (!pwalletMain->GetPubKey(keyID, vchPubKey))
250 throw runtime_error(
251 strprintf("no full public key for address %s",ks));
252 if (!vchPubKey.IsFullyValid())
253 throw runtime_error(" Invalid public key: "+ks);
254 pubkeys[i] = vchPubKey;
257 // Case 2: hex public key
258 else
259 #endif
260 if (IsHex(ks))
262 CPubKey vchPubKey(ParseHex(ks));
263 if (!vchPubKey.IsFullyValid())
264 throw runtime_error(" Invalid public key: "+ks);
265 pubkeys[i] = vchPubKey;
267 else
269 throw runtime_error(" Invalid public key: "+ks);
272 CScript result = GetScriptForMultisig(nRequired, pubkeys);
274 if (result.size() > MAX_SCRIPT_ELEMENT_SIZE)
275 throw runtime_error(
276 strprintf("redeemScript exceeds size limit: %d > %d", result.size(), MAX_SCRIPT_ELEMENT_SIZE));
278 return result;
281 UniValue createmultisig(const JSONRPCRequest& request)
283 if (request.fHelp || request.params.size() < 2 || request.params.size() > 2)
285 string msg = "createmultisig nrequired [\"key\",...]\n"
286 "\nCreates a multi-signature address with n signature of m keys required.\n"
287 "It returns a json object with the address and redeemScript.\n"
289 "\nArguments:\n"
290 "1. nrequired (numeric, required) The number of required signatures out of the n keys or addresses.\n"
291 "2. \"keys\" (string, required) A json array of keys which are bitcoin addresses or hex-encoded public keys\n"
292 " [\n"
293 " \"key\" (string) bitcoin address or hex-encoded public key\n"
294 " ,...\n"
295 " ]\n"
297 "\nResult:\n"
298 "{\n"
299 " \"address\":\"multisigaddress\", (string) The value of the new multisig address.\n"
300 " \"redeemScript\":\"script\" (string) The string value of the hex-encoded redemption script.\n"
301 "}\n"
303 "\nExamples:\n"
304 "\nCreate a multisig address from 2 addresses\n"
305 + HelpExampleCli("createmultisig", "2 \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"") +
306 "\nAs a json rpc call\n"
307 + HelpExampleRpc("createmultisig", "2, \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"")
309 throw runtime_error(msg);
312 // Construct using pay-to-script-hash:
313 CScript inner = _createmultisig_redeemScript(request.params);
314 CScriptID innerID(inner);
315 CBitcoinAddress address(innerID);
317 UniValue result(UniValue::VOBJ);
318 result.push_back(Pair("address", address.ToString()));
319 result.push_back(Pair("redeemScript", HexStr(inner.begin(), inner.end())));
321 return result;
324 UniValue verifymessage(const JSONRPCRequest& request)
326 if (request.fHelp || request.params.size() != 3)
327 throw runtime_error(
328 "verifymessage \"address\" \"signature\" \"message\"\n"
329 "\nVerify a signed message\n"
330 "\nArguments:\n"
331 "1. \"address\" (string, required) The bitcoin address to use for the signature.\n"
332 "2. \"signature\" (string, required) The signature provided by the signer in base 64 encoding (see signmessage).\n"
333 "3. \"message\" (string, required) The message that was signed.\n"
334 "\nResult:\n"
335 "true|false (boolean) If the signature is verified or not.\n"
336 "\nExamples:\n"
337 "\nUnlock the wallet for 30 seconds\n"
338 + HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") +
339 "\nCreate the signature\n"
340 + HelpExampleCli("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"my message\"") +
341 "\nVerify the signature\n"
342 + HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"signature\" \"my message\"") +
343 "\nAs json rpc\n"
344 + HelpExampleRpc("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"signature\", \"my message\"")
347 LOCK(cs_main);
349 string strAddress = request.params[0].get_str();
350 string strSign = request.params[1].get_str();
351 string strMessage = request.params[2].get_str();
353 CBitcoinAddress addr(strAddress);
354 if (!addr.IsValid())
355 throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address");
357 CKeyID keyID;
358 if (!addr.GetKeyID(keyID))
359 throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
361 bool fInvalid = false;
362 vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
364 if (fInvalid)
365 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Malformed base64 encoding");
367 CHashWriter ss(SER_GETHASH, 0);
368 ss << strMessageMagic;
369 ss << strMessage;
371 CPubKey pubkey;
372 if (!pubkey.RecoverCompact(ss.GetHash(), vchSig))
373 return false;
375 return (pubkey.GetID() == keyID);
378 UniValue signmessagewithprivkey(const JSONRPCRequest& request)
380 if (request.fHelp || request.params.size() != 2)
381 throw runtime_error(
382 "signmessagewithprivkey \"privkey\" \"message\"\n"
383 "\nSign a message with the private key of an address\n"
384 "\nArguments:\n"
385 "1. \"privkey\" (string, required) The private key to sign the message with.\n"
386 "2. \"message\" (string, required) The message to create a signature of.\n"
387 "\nResult:\n"
388 "\"signature\" (string) The signature of the message encoded in base 64\n"
389 "\nExamples:\n"
390 "\nCreate the signature\n"
391 + HelpExampleCli("signmessagewithprivkey", "\"privkey\" \"my message\"") +
392 "\nVerify the signature\n"
393 + HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"signature\" \"my message\"") +
394 "\nAs json rpc\n"
395 + HelpExampleRpc("signmessagewithprivkey", "\"privkey\", \"my message\"")
398 string strPrivkey = request.params[0].get_str();
399 string strMessage = request.params[1].get_str();
401 CBitcoinSecret vchSecret;
402 bool fGood = vchSecret.SetString(strPrivkey);
403 if (!fGood)
404 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key");
405 CKey key = vchSecret.GetKey();
406 if (!key.IsValid())
407 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Private key outside allowed range");
409 CHashWriter ss(SER_GETHASH, 0);
410 ss << strMessageMagic;
411 ss << strMessage;
413 vector<unsigned char> vchSig;
414 if (!key.SignCompact(ss.GetHash(), vchSig))
415 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Sign failed");
417 return EncodeBase64(&vchSig[0], vchSig.size());
420 UniValue setmocktime(const JSONRPCRequest& request)
422 if (request.fHelp || request.params.size() != 1)
423 throw runtime_error(
424 "setmocktime timestamp\n"
425 "\nSet the local time to given timestamp (-regtest only)\n"
426 "\nArguments:\n"
427 "1. timestamp (integer, required) Unix seconds-since-epoch timestamp\n"
428 " Pass 0 to go back to using the system time."
431 if (!Params().MineBlocksOnDemand())
432 throw runtime_error("setmocktime for regression testing (-regtest mode) only");
434 // For now, don't change mocktime if we're in the middle of validation, as
435 // this could have an effect on mempool time-based eviction, as well as
436 // IsCurrentForFeeEstimation() and IsInitialBlockDownload().
437 // TODO: figure out the right way to synchronize around mocktime, and
438 // ensure all call sites of GetTime() are accessing this safely.
439 LOCK(cs_main);
441 RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VNUM));
442 SetMockTime(request.params[0].get_int64());
444 return NullUniValue;
447 static UniValue RPCLockedMemoryInfo()
449 LockedPool::Stats stats = LockedPoolManager::Instance().stats();
450 UniValue obj(UniValue::VOBJ);
451 obj.push_back(Pair("used", uint64_t(stats.used)));
452 obj.push_back(Pair("free", uint64_t(stats.free)));
453 obj.push_back(Pair("total", uint64_t(stats.total)));
454 obj.push_back(Pair("locked", uint64_t(stats.locked)));
455 obj.push_back(Pair("chunks_used", uint64_t(stats.chunks_used)));
456 obj.push_back(Pair("chunks_free", uint64_t(stats.chunks_free)));
457 return obj;
460 UniValue getmemoryinfo(const JSONRPCRequest& request)
462 /* Please, avoid using the word "pool" here in the RPC interface or help,
463 * as users will undoubtedly confuse it with the other "memory pool"
465 if (request.fHelp || request.params.size() != 0)
466 throw runtime_error(
467 "getmemoryinfo\n"
468 "Returns an object containing information about memory usage.\n"
469 "\nResult:\n"
470 "{\n"
471 " \"locked\": { (json object) Information about locked memory manager\n"
472 " \"used\": xxxxx, (numeric) Number of bytes used\n"
473 " \"free\": xxxxx, (numeric) Number of bytes available in current arenas\n"
474 " \"total\": xxxxxxx, (numeric) Total number of bytes managed\n"
475 " \"locked\": xxxxxx, (numeric) Amount of bytes that succeeded locking. If this number is smaller than total, locking pages failed at some point and key data could be swapped to disk.\n"
476 " \"chunks_used\": xxxxx, (numeric) Number allocated chunks\n"
477 " \"chunks_free\": xxxxx, (numeric) Number unused chunks\n"
478 " }\n"
479 "}\n"
480 "\nExamples:\n"
481 + HelpExampleCli("getmemoryinfo", "")
482 + HelpExampleRpc("getmemoryinfo", "")
484 UniValue obj(UniValue::VOBJ);
485 obj.push_back(Pair("locked", RPCLockedMemoryInfo()));
486 return obj;
489 UniValue echo(const JSONRPCRequest& request)
491 if (request.fHelp)
492 throw runtime_error(
493 "echo|echojson \"message\" ...\n"
494 "\nSimply echo back the input arguments. This command is for testing.\n"
495 "\nThe difference between echo and echojson is that echojson has argument conversion enabled in the client-side table in"
496 "bitcoin-cli and the GUI. There is no server-side difference."
499 return request.params;
502 static const CRPCCommand commands[] =
503 { // category name actor (function) okSafeMode
504 // --------------------- ------------------------ ----------------------- ----------
505 { "control", "getinfo", &getinfo, true, {} }, /* uses wallet if enabled */
506 { "control", "getmemoryinfo", &getmemoryinfo, true, {} },
507 { "util", "validateaddress", &validateaddress, true, {"address"} }, /* uses wallet if enabled */
508 { "util", "createmultisig", &createmultisig, true, {"nrequired","keys"} },
509 { "util", "verifymessage", &verifymessage, true, {"address","signature","message"} },
510 { "util", "signmessagewithprivkey", &signmessagewithprivkey, true, {"privkey","message"} },
512 /* Not shown in help */
513 { "hidden", "setmocktime", &setmocktime, true, {"timestamp"}},
514 { "hidden", "echo", &echo, true, {"arg0","arg1","arg2","arg3","arg4","arg5","arg6","arg7","arg8","arg9"}},
515 { "hidden", "echojson", &echo, true, {"arg0","arg1","arg2","arg3","arg4","arg5","arg6","arg7","arg8","arg9"}},
518 void RegisterMiscRPCCommands(CRPCTable &t)
520 for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
521 t.appendCommand(commands[vcidx].name, &commands[vcidx]);