Merge #12079: Improve prioritisetransaction test coverage
[bitcoinplatinum.git] / src / rpc / misc.cpp
blob1c8a24ed36eb2ed8f6ede2420e76ece9782c745b
1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2017 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 <chain.h>
8 #include <clientversion.h>
9 #include <core_io.h>
10 #include <crypto/ripemd160.h>
11 #include <init.h>
12 #include <validation.h>
13 #include <httpserver.h>
14 #include <net.h>
15 #include <netbase.h>
16 #include <rpc/blockchain.h>
17 #include <rpc/server.h>
18 #include <timedata.h>
19 #include <util.h>
20 #include <utilstrencodings.h>
21 #ifdef ENABLE_WALLET
22 #include <wallet/rpcwallet.h>
23 #include <wallet/wallet.h>
24 #include <wallet/walletdb.h>
25 #endif
26 #include <warnings.h>
28 #include <stdint.h>
29 #ifdef HAVE_MALLOC_INFO
30 #include <malloc.h>
31 #endif
33 #include <univalue.h>
35 #ifdef ENABLE_WALLET
36 class DescribeAddressVisitor : public boost::static_visitor<UniValue>
38 public:
39 CWallet * const pwallet;
41 explicit DescribeAddressVisitor(CWallet *_pwallet) : pwallet(_pwallet) {}
43 UniValue operator()(const CNoDestination &dest) const { return UniValue(UniValue::VOBJ); }
45 UniValue operator()(const CKeyID &keyID) const {
46 UniValue obj(UniValue::VOBJ);
47 CPubKey vchPubKey;
48 obj.push_back(Pair("isscript", false));
49 obj.push_back(Pair("iswitness", false));
50 if (pwallet && pwallet->GetPubKey(keyID, vchPubKey)) {
51 obj.push_back(Pair("pubkey", HexStr(vchPubKey)));
52 obj.push_back(Pair("iscompressed", vchPubKey.IsCompressed()));
54 return obj;
57 UniValue operator()(const CScriptID &scriptID) const {
58 UniValue obj(UniValue::VOBJ);
59 CScript subscript;
60 obj.push_back(Pair("isscript", true));
61 obj.push_back(Pair("iswitness", false));
62 if (pwallet && pwallet->GetCScript(scriptID, subscript)) {
63 std::vector<CTxDestination> addresses;
64 txnouttype whichType;
65 int nRequired;
66 ExtractDestinations(subscript, whichType, addresses, nRequired);
67 obj.push_back(Pair("script", GetTxnOutputType(whichType)));
68 obj.push_back(Pair("hex", HexStr(subscript.begin(), subscript.end())));
69 UniValue a(UniValue::VARR);
70 for (const CTxDestination& addr : addresses) {
71 a.push_back(EncodeDestination(addr));
73 obj.push_back(Pair("addresses", a));
74 if (whichType == TX_MULTISIG)
75 obj.push_back(Pair("sigsrequired", nRequired));
77 return obj;
80 UniValue operator()(const WitnessV0KeyHash& id) const
82 UniValue obj(UniValue::VOBJ);
83 CPubKey pubkey;
84 obj.push_back(Pair("isscript", false));
85 obj.push_back(Pair("iswitness", true));
86 obj.push_back(Pair("witness_version", 0));
87 obj.push_back(Pair("witness_program", HexStr(id.begin(), id.end())));
88 if (pwallet && pwallet->GetPubKey(CKeyID(id), pubkey)) {
89 obj.push_back(Pair("pubkey", HexStr(pubkey)));
91 return obj;
94 UniValue operator()(const WitnessV0ScriptHash& id) const
96 UniValue obj(UniValue::VOBJ);
97 CScript subscript;
98 obj.push_back(Pair("isscript", true));
99 obj.push_back(Pair("iswitness", true));
100 obj.push_back(Pair("witness_version", 0));
101 obj.push_back(Pair("witness_program", HexStr(id.begin(), id.end())));
102 CRIPEMD160 hasher;
103 uint160 hash;
104 hasher.Write(id.begin(), 32).Finalize(hash.begin());
105 if (pwallet && pwallet->GetCScript(CScriptID(hash), subscript)) {
106 obj.push_back(Pair("hex", HexStr(subscript.begin(), subscript.end())));
108 return obj;
111 UniValue operator()(const WitnessUnknown& id) const
113 UniValue obj(UniValue::VOBJ);
114 CScript subscript;
115 obj.push_back(Pair("iswitness", true));
116 obj.push_back(Pair("witness_version", (int)id.version));
117 obj.push_back(Pair("witness_program", HexStr(id.program, id.program + id.length)));
118 return obj;
121 #endif
123 UniValue validateaddress(const JSONRPCRequest& request)
125 if (request.fHelp || request.params.size() != 1)
126 throw std::runtime_error(
127 "validateaddress \"address\"\n"
128 "\nReturn information about the given bitcoin address.\n"
129 "\nArguments:\n"
130 "1. \"address\" (string, required) The bitcoin address to validate\n"
131 "\nResult:\n"
132 "{\n"
133 " \"isvalid\" : true|false, (boolean) If the address is valid or not. If not, this is the only property returned.\n"
134 " \"address\" : \"address\", (string) The bitcoin address validated\n"
135 " \"scriptPubKey\" : \"hex\", (string) The hex encoded scriptPubKey generated by the address\n"
136 " \"ismine\" : true|false, (boolean) If the address is yours or not\n"
137 " \"iswatchonly\" : true|false, (boolean) If the address is watchonly\n"
138 " \"isscript\" : true|false, (boolean) If the key is a script\n"
139 " \"script\" : \"type\" (string, optional) The output script type. Possible types: nonstandard, pubkey, pubkeyhash, scripthash, multisig, nulldata, witness_v0_keyhash, witness_v0_scripthash\n"
140 " \"hex\" : \"hex\", (string, optional) The redeemscript for the p2sh address\n"
141 " \"addresses\" (string, optional) Array of addresses associated with the known redeemscript\n"
142 " [\n"
143 " \"address\"\n"
144 " ,...\n"
145 " ]\n"
146 " \"sigsrequired\" : xxxxx (numeric, optional) Number of signatures required to spend multisig output\n"
147 " \"pubkey\" : \"publickeyhex\", (string) The hex value of the raw public key\n"
148 " \"iscompressed\" : true|false, (boolean) If the address is compressed\n"
149 " \"account\" : \"account\" (string) DEPRECATED. The account associated with the address, \"\" is the default account\n"
150 " \"timestamp\" : timestamp, (number, optional) The creation time of the key if available in seconds since epoch (Jan 1 1970 GMT)\n"
151 " \"hdkeypath\" : \"keypath\" (string, optional) The HD keypath if the key is HD and available\n"
152 " \"hdmasterkeyid\" : \"<hash160>\" (string, optional) The Hash160 of the HD master pubkey\n"
153 "}\n"
154 "\nExamples:\n"
155 + HelpExampleCli("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
156 + HelpExampleRpc("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
159 #ifdef ENABLE_WALLET
160 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
162 LOCK2(cs_main, pwallet ? &pwallet->cs_wallet : nullptr);
163 #else
164 LOCK(cs_main);
165 #endif
167 CTxDestination dest = DecodeDestination(request.params[0].get_str());
168 bool isValid = IsValidDestination(dest);
170 UniValue ret(UniValue::VOBJ);
171 ret.push_back(Pair("isvalid", isValid));
172 if (isValid)
174 std::string currentAddress = EncodeDestination(dest);
175 ret.push_back(Pair("address", currentAddress));
177 CScript scriptPubKey = GetScriptForDestination(dest);
178 ret.push_back(Pair("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end())));
180 #ifdef ENABLE_WALLET
181 isminetype mine = pwallet ? IsMine(*pwallet, dest) : ISMINE_NO;
182 ret.push_back(Pair("ismine", bool(mine & ISMINE_SPENDABLE)));
183 ret.push_back(Pair("iswatchonly", bool(mine & ISMINE_WATCH_ONLY)));
184 UniValue detail = boost::apply_visitor(DescribeAddressVisitor(pwallet), dest);
185 ret.pushKVs(detail);
186 if (pwallet && pwallet->mapAddressBook.count(dest)) {
187 ret.push_back(Pair("account", pwallet->mapAddressBook[dest].name));
189 if (pwallet) {
190 const CKeyMetadata* meta = nullptr;
191 if (const CKeyID* key_id = boost::get<CKeyID>(&dest)) {
192 auto it = pwallet->mapKeyMetadata.find(*key_id);
193 if (it != pwallet->mapKeyMetadata.end()) {
194 meta = &it->second;
197 if (!meta) {
198 auto it = pwallet->m_script_metadata.find(CScriptID(scriptPubKey));
199 if (it != pwallet->m_script_metadata.end()) {
200 meta = &it->second;
203 if (meta) {
204 ret.push_back(Pair("timestamp", meta->nCreateTime));
205 if (!meta->hdKeypath.empty()) {
206 ret.push_back(Pair("hdkeypath", meta->hdKeypath));
207 ret.push_back(Pair("hdmasterkeyid", meta->hdMasterKeyID.GetHex()));
211 #endif
213 return ret;
216 // Needed even with !ENABLE_WALLET, to pass (ignored) pointers around
217 class CWallet;
220 * Used by addmultisigaddress / createmultisig:
222 CScript _createmultisig_redeemScript(CWallet * const pwallet, const UniValue& params)
224 int nRequired = params[0].get_int();
225 const UniValue& keys = params[1].get_array();
227 // Gather public keys
228 if (nRequired < 1)
229 throw std::runtime_error("a multisignature address must require at least one key to redeem");
230 if ((int)keys.size() < nRequired)
231 throw std::runtime_error(
232 strprintf("not enough keys supplied "
233 "(got %u keys, but need at least %d to redeem)", keys.size(), nRequired));
234 if (keys.size() > 16)
235 throw std::runtime_error("Number of addresses involved in the multisignature address creation > 16\nReduce the number");
236 std::vector<CPubKey> pubkeys;
237 pubkeys.resize(keys.size());
238 for (unsigned int i = 0; i < keys.size(); i++)
240 const std::string& ks = keys[i].get_str();
241 #ifdef ENABLE_WALLET
242 // Case 1: Bitcoin address and we have full public key:
243 CTxDestination dest = DecodeDestination(ks);
244 if (pwallet && IsValidDestination(dest)) {
245 const CKeyID *keyID = boost::get<CKeyID>(&dest);
246 if (!keyID) {
247 throw std::runtime_error(strprintf("%s does not refer to a key", ks));
249 CPubKey vchPubKey;
250 if (!pwallet->GetPubKey(*keyID, vchPubKey)) {
251 throw std::runtime_error(strprintf("no full public key for address %s", ks));
253 if (!vchPubKey.IsFullyValid())
254 throw std::runtime_error(" Invalid public key: "+ks);
255 pubkeys[i] = vchPubKey;
258 // Case 2: hex public key
259 else
260 #endif
261 if (IsHex(ks))
263 CPubKey vchPubKey(ParseHex(ks));
264 if (!vchPubKey.IsFullyValid())
265 throw std::runtime_error(" Invalid public key: "+ks);
266 pubkeys[i] = vchPubKey;
268 else
270 throw std::runtime_error(" Invalid public key: "+ks);
273 CScript result = GetScriptForMultisig(nRequired, pubkeys);
275 if (result.size() > MAX_SCRIPT_ELEMENT_SIZE)
276 throw std::runtime_error(
277 strprintf("redeemScript exceeds size limit: %d > %d", result.size(), MAX_SCRIPT_ELEMENT_SIZE));
279 return result;
282 UniValue createmultisig(const JSONRPCRequest& request)
284 #ifdef ENABLE_WALLET
285 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
286 #else
287 CWallet * const pwallet = nullptr;
288 #endif
290 if (request.fHelp || request.params.size() < 2 || request.params.size() > 2)
292 std::string msg = "createmultisig nrequired [\"key\",...]\n"
293 "\nCreates a multi-signature address with n signature of m keys required.\n"
294 "It returns a json object with the address and redeemScript.\n"
296 "\nArguments:\n"
297 "1. nrequired (numeric, required) The number of required signatures out of the n keys or addresses.\n"
298 "2. \"keys\" (string, required) A json array of keys which are bitcoin addresses or hex-encoded public keys\n"
299 " [\n"
300 " \"key\" (string) bitcoin address or hex-encoded public key\n"
301 " ,...\n"
302 " ]\n"
304 "\nResult:\n"
305 "{\n"
306 " \"address\":\"multisigaddress\", (string) The value of the new multisig address.\n"
307 " \"redeemScript\":\"script\" (string) The string value of the hex-encoded redemption script.\n"
308 "}\n"
310 "\nExamples:\n"
311 "\nCreate a multisig address from 2 addresses\n"
312 + HelpExampleCli("createmultisig", "2 \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"") +
313 "\nAs a json rpc call\n"
314 + HelpExampleRpc("createmultisig", "2, \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"")
316 throw std::runtime_error(msg);
319 // Construct using pay-to-script-hash:
320 CScript inner = _createmultisig_redeemScript(pwallet, request.params);
321 CScriptID innerID(inner);
323 UniValue result(UniValue::VOBJ);
324 result.push_back(Pair("address", EncodeDestination(innerID)));
325 result.push_back(Pair("redeemScript", HexStr(inner.begin(), inner.end())));
327 return result;
330 UniValue verifymessage(const JSONRPCRequest& request)
332 if (request.fHelp || request.params.size() != 3)
333 throw std::runtime_error(
334 "verifymessage \"address\" \"signature\" \"message\"\n"
335 "\nVerify a signed message\n"
336 "\nArguments:\n"
337 "1. \"address\" (string, required) The bitcoin address to use for the signature.\n"
338 "2. \"signature\" (string, required) The signature provided by the signer in base 64 encoding (see signmessage).\n"
339 "3. \"message\" (string, required) The message that was signed.\n"
340 "\nResult:\n"
341 "true|false (boolean) If the signature is verified or not.\n"
342 "\nExamples:\n"
343 "\nUnlock the wallet for 30 seconds\n"
344 + HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") +
345 "\nCreate the signature\n"
346 + HelpExampleCli("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"my message\"") +
347 "\nVerify the signature\n"
348 + HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"signature\" \"my message\"") +
349 "\nAs json rpc\n"
350 + HelpExampleRpc("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\", \"signature\", \"my message\"")
353 LOCK(cs_main);
355 std::string strAddress = request.params[0].get_str();
356 std::string strSign = request.params[1].get_str();
357 std::string strMessage = request.params[2].get_str();
359 CTxDestination destination = DecodeDestination(strAddress);
360 if (!IsValidDestination(destination)) {
361 throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address");
364 const CKeyID *keyID = boost::get<CKeyID>(&destination);
365 if (!keyID) {
366 throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
369 bool fInvalid = false;
370 std::vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
372 if (fInvalid)
373 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Malformed base64 encoding");
375 CHashWriter ss(SER_GETHASH, 0);
376 ss << strMessageMagic;
377 ss << strMessage;
379 CPubKey pubkey;
380 if (!pubkey.RecoverCompact(ss.GetHash(), vchSig))
381 return false;
383 return (pubkey.GetID() == *keyID);
386 UniValue signmessagewithprivkey(const JSONRPCRequest& request)
388 if (request.fHelp || request.params.size() != 2)
389 throw std::runtime_error(
390 "signmessagewithprivkey \"privkey\" \"message\"\n"
391 "\nSign a message with the private key of an address\n"
392 "\nArguments:\n"
393 "1. \"privkey\" (string, required) The private key to sign the message with.\n"
394 "2. \"message\" (string, required) The message to create a signature of.\n"
395 "\nResult:\n"
396 "\"signature\" (string) The signature of the message encoded in base 64\n"
397 "\nExamples:\n"
398 "\nCreate the signature\n"
399 + HelpExampleCli("signmessagewithprivkey", "\"privkey\" \"my message\"") +
400 "\nVerify the signature\n"
401 + HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"signature\" \"my message\"") +
402 "\nAs json rpc\n"
403 + HelpExampleRpc("signmessagewithprivkey", "\"privkey\", \"my message\"")
406 std::string strPrivkey = request.params[0].get_str();
407 std::string strMessage = request.params[1].get_str();
409 CBitcoinSecret vchSecret;
410 bool fGood = vchSecret.SetString(strPrivkey);
411 if (!fGood)
412 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key");
413 CKey key = vchSecret.GetKey();
414 if (!key.IsValid())
415 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Private key outside allowed range");
417 CHashWriter ss(SER_GETHASH, 0);
418 ss << strMessageMagic;
419 ss << strMessage;
421 std::vector<unsigned char> vchSig;
422 if (!key.SignCompact(ss.GetHash(), vchSig))
423 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Sign failed");
425 return EncodeBase64(vchSig.data(), vchSig.size());
428 UniValue setmocktime(const JSONRPCRequest& request)
430 if (request.fHelp || request.params.size() != 1)
431 throw std::runtime_error(
432 "setmocktime timestamp\n"
433 "\nSet the local time to given timestamp (-regtest only)\n"
434 "\nArguments:\n"
435 "1. timestamp (integer, required) Unix seconds-since-epoch timestamp\n"
436 " Pass 0 to go back to using the system time."
439 if (!Params().MineBlocksOnDemand())
440 throw std::runtime_error("setmocktime for regression testing (-regtest mode) only");
442 // For now, don't change mocktime if we're in the middle of validation, as
443 // this could have an effect on mempool time-based eviction, as well as
444 // IsCurrentForFeeEstimation() and IsInitialBlockDownload().
445 // TODO: figure out the right way to synchronize around mocktime, and
446 // ensure all call sites of GetTime() are accessing this safely.
447 LOCK(cs_main);
449 RPCTypeCheck(request.params, {UniValue::VNUM});
450 SetMockTime(request.params[0].get_int64());
452 return NullUniValue;
455 static UniValue RPCLockedMemoryInfo()
457 LockedPool::Stats stats = LockedPoolManager::Instance().stats();
458 UniValue obj(UniValue::VOBJ);
459 obj.push_back(Pair("used", uint64_t(stats.used)));
460 obj.push_back(Pair("free", uint64_t(stats.free)));
461 obj.push_back(Pair("total", uint64_t(stats.total)));
462 obj.push_back(Pair("locked", uint64_t(stats.locked)));
463 obj.push_back(Pair("chunks_used", uint64_t(stats.chunks_used)));
464 obj.push_back(Pair("chunks_free", uint64_t(stats.chunks_free)));
465 return obj;
468 #ifdef HAVE_MALLOC_INFO
469 static std::string RPCMallocInfo()
471 char *ptr = nullptr;
472 size_t size = 0;
473 FILE *f = open_memstream(&ptr, &size);
474 if (f) {
475 malloc_info(0, f);
476 fclose(f);
477 if (ptr) {
478 std::string rv(ptr, size);
479 free(ptr);
480 return rv;
483 return "";
485 #endif
487 UniValue getmemoryinfo(const JSONRPCRequest& request)
489 /* Please, avoid using the word "pool" here in the RPC interface or help,
490 * as users will undoubtedly confuse it with the other "memory pool"
492 if (request.fHelp || request.params.size() > 1)
493 throw std::runtime_error(
494 "getmemoryinfo (\"mode\")\n"
495 "Returns an object containing information about memory usage.\n"
496 "Arguments:\n"
497 "1. \"mode\" determines what kind of information is returned. This argument is optional, the default mode is \"stats\".\n"
498 " - \"stats\" returns general statistics about memory usage in the daemon.\n"
499 " - \"mallocinfo\" returns an XML string describing low-level heap state (only available if compiled with glibc 2.10+).\n"
500 "\nResult (mode \"stats\"):\n"
501 "{\n"
502 " \"locked\": { (json object) Information about locked memory manager\n"
503 " \"used\": xxxxx, (numeric) Number of bytes used\n"
504 " \"free\": xxxxx, (numeric) Number of bytes available in current arenas\n"
505 " \"total\": xxxxxxx, (numeric) Total number of bytes managed\n"
506 " \"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"
507 " \"chunks_used\": xxxxx, (numeric) Number allocated chunks\n"
508 " \"chunks_free\": xxxxx, (numeric) Number unused chunks\n"
509 " }\n"
510 "}\n"
511 "\nResult (mode \"mallocinfo\"):\n"
512 "\"<malloc version=\"1\">...\"\n"
513 "\nExamples:\n"
514 + HelpExampleCli("getmemoryinfo", "")
515 + HelpExampleRpc("getmemoryinfo", "")
518 std::string mode = request.params[0].isNull() ? "stats" : request.params[0].get_str();
519 if (mode == "stats") {
520 UniValue obj(UniValue::VOBJ);
521 obj.push_back(Pair("locked", RPCLockedMemoryInfo()));
522 return obj;
523 } else if (mode == "mallocinfo") {
524 #ifdef HAVE_MALLOC_INFO
525 return RPCMallocInfo();
526 #else
527 throw JSONRPCError(RPC_INVALID_PARAMETER, "mallocinfo is only available when compiled with glibc 2.10+");
528 #endif
529 } else {
530 throw JSONRPCError(RPC_INVALID_PARAMETER, "unknown mode " + mode);
534 uint32_t getCategoryMask(UniValue cats) {
535 cats = cats.get_array();
536 uint32_t mask = 0;
537 for (unsigned int i = 0; i < cats.size(); ++i) {
538 uint32_t flag = 0;
539 std::string cat = cats[i].get_str();
540 if (!GetLogCategory(&flag, &cat)) {
541 throw JSONRPCError(RPC_INVALID_PARAMETER, "unknown logging category " + cat);
543 if (flag == BCLog::NONE) {
544 return 0;
546 mask |= flag;
548 return mask;
551 UniValue logging(const JSONRPCRequest& request)
553 if (request.fHelp || request.params.size() > 2) {
554 throw std::runtime_error(
555 "logging ( <include> <exclude> )\n"
556 "Gets and sets the logging configuration.\n"
557 "When called without an argument, returns the list of categories with status that are currently being debug logged or not.\n"
558 "When called with arguments, adds or removes categories from debug logging and return the lists above.\n"
559 "The arguments are evaluated in order \"include\", \"exclude\".\n"
560 "If an item is both included and excluded, it will thus end up being excluded.\n"
561 "The valid logging categories are: " + ListLogCategories() + "\n"
562 "In addition, the following are available as category names with special meanings:\n"
563 " - \"all\", \"1\" : represent all logging categories.\n"
564 " - \"none\", \"0\" : even if other logging categories are specified, ignore all of them.\n"
565 "\nArguments:\n"
566 "1. \"include\" (array of strings, optional) A json array of categories to add debug logging\n"
567 " [\n"
568 " \"category\" (string) the valid logging category\n"
569 " ,...\n"
570 " ]\n"
571 "2. \"exclude\" (array of strings, optional) A json array of categories to remove debug logging\n"
572 " [\n"
573 " \"category\" (string) the valid logging category\n"
574 " ,...\n"
575 " ]\n"
576 "\nResult:\n"
577 "{ (json object where keys are the logging categories, and values indicates its status\n"
578 " \"category\": 0|1, (numeric) if being debug logged or not. 0:inactive, 1:active\n"
579 " ...\n"
580 "}\n"
581 "\nExamples:\n"
582 + HelpExampleCli("logging", "\"[\\\"all\\\"]\" \"[\\\"http\\\"]\"")
583 + HelpExampleRpc("logging", "[\"all\"], \"[libevent]\"")
587 uint32_t originalLogCategories = logCategories;
588 if (request.params[0].isArray()) {
589 logCategories |= getCategoryMask(request.params[0]);
592 if (request.params[1].isArray()) {
593 logCategories &= ~getCategoryMask(request.params[1]);
596 // Update libevent logging if BCLog::LIBEVENT has changed.
597 // If the library version doesn't allow it, UpdateHTTPServerLogging() returns false,
598 // in which case we should clear the BCLog::LIBEVENT flag.
599 // Throw an error if the user has explicitly asked to change only the libevent
600 // flag and it failed.
601 uint32_t changedLogCategories = originalLogCategories ^ logCategories;
602 if (changedLogCategories & BCLog::LIBEVENT) {
603 if (!UpdateHTTPServerLogging(logCategories & BCLog::LIBEVENT)) {
604 logCategories &= ~BCLog::LIBEVENT;
605 if (changedLogCategories == BCLog::LIBEVENT) {
606 throw JSONRPCError(RPC_INVALID_PARAMETER, "libevent logging cannot be updated when using libevent before v2.1.1.");
611 UniValue result(UniValue::VOBJ);
612 std::vector<CLogCategoryActive> vLogCatActive = ListActiveLogCategories();
613 for (const auto& logCatActive : vLogCatActive) {
614 result.pushKV(logCatActive.category, logCatActive.active);
617 return result;
620 UniValue echo(const JSONRPCRequest& request)
622 if (request.fHelp)
623 throw std::runtime_error(
624 "echo|echojson \"message\" ...\n"
625 "\nSimply echo back the input arguments. This command is for testing.\n"
626 "\nThe difference between echo and echojson is that echojson has argument conversion enabled in the client-side table in"
627 "bitcoin-cli and the GUI. There is no server-side difference."
630 return request.params;
633 static const CRPCCommand commands[] =
634 { // category name actor (function) argNames
635 // --------------------- ------------------------ ----------------------- ----------
636 { "control", "getmemoryinfo", &getmemoryinfo, {"mode"} },
637 { "control", "logging", &logging, {"include", "exclude"}},
638 { "util", "validateaddress", &validateaddress, {"address"} }, /* uses wallet if enabled */
639 { "util", "createmultisig", &createmultisig, {"nrequired","keys"} },
640 { "util", "verifymessage", &verifymessage, {"address","signature","message"} },
641 { "util", "signmessagewithprivkey", &signmessagewithprivkey, {"privkey","message"} },
643 /* Not shown in help */
644 { "hidden", "setmocktime", &setmocktime, {"timestamp"}},
645 { "hidden", "echo", &echo, {"arg0","arg1","arg2","arg3","arg4","arg5","arg6","arg7","arg8","arg9"}},
646 { "hidden", "echojson", &echo, {"arg0","arg1","arg2","arg3","arg4","arg5","arg6","arg7","arg8","arg9"}},
649 void RegisterMiscRPCCommands(CRPCTable &t)
651 for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
652 t.appendCommand(commands[vcidx].name, &commands[vcidx]);