Merge #11191: RPC: Improve help text and behavior of RPC-logging.
[bitcoinplatinum.git] / src / rpc / misc.cpp
blobc511aa0eb245610f4cc8f6620669a728e7a7a965
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 <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 auto& meta = pwallet->mapKeyMetadata;
191 const CKeyID *keyID = boost::get<CKeyID>(&dest);
192 auto it = keyID ? meta.find(*keyID) : meta.end();
193 if (it == meta.end()) {
194 it = meta.find(CScriptID(scriptPubKey));
196 if (it != meta.end()) {
197 ret.push_back(Pair("timestamp", it->second.nCreateTime));
198 if (!it->second.hdKeypath.empty()) {
199 ret.push_back(Pair("hdkeypath", it->second.hdKeypath));
200 ret.push_back(Pair("hdmasterkeyid", it->second.hdMasterKeyID.GetHex()));
204 #endif
206 return ret;
209 // Needed even with !ENABLE_WALLET, to pass (ignored) pointers around
210 class CWallet;
213 * Used by addmultisigaddress / createmultisig:
215 CScript _createmultisig_redeemScript(CWallet * const pwallet, const UniValue& params)
217 int nRequired = params[0].get_int();
218 const UniValue& keys = params[1].get_array();
220 // Gather public keys
221 if (nRequired < 1)
222 throw std::runtime_error("a multisignature address must require at least one key to redeem");
223 if ((int)keys.size() < nRequired)
224 throw std::runtime_error(
225 strprintf("not enough keys supplied "
226 "(got %u keys, but need at least %d to redeem)", keys.size(), nRequired));
227 if (keys.size() > 16)
228 throw std::runtime_error("Number of addresses involved in the multisignature address creation > 16\nReduce the number");
229 std::vector<CPubKey> pubkeys;
230 pubkeys.resize(keys.size());
231 for (unsigned int i = 0; i < keys.size(); i++)
233 const std::string& ks = keys[i].get_str();
234 #ifdef ENABLE_WALLET
235 // Case 1: Bitcoin address and we have full public key:
236 CTxDestination dest = DecodeDestination(ks);
237 if (pwallet && IsValidDestination(dest)) {
238 const CKeyID *keyID = boost::get<CKeyID>(&dest);
239 if (!keyID) {
240 throw std::runtime_error(strprintf("%s does not refer to a key", ks));
242 CPubKey vchPubKey;
243 if (!pwallet->GetPubKey(*keyID, vchPubKey)) {
244 throw std::runtime_error(strprintf("no full public key for address %s", ks));
246 if (!vchPubKey.IsFullyValid())
247 throw std::runtime_error(" Invalid public key: "+ks);
248 pubkeys[i] = vchPubKey;
251 // Case 2: hex public key
252 else
253 #endif
254 if (IsHex(ks))
256 CPubKey vchPubKey(ParseHex(ks));
257 if (!vchPubKey.IsFullyValid())
258 throw std::runtime_error(" Invalid public key: "+ks);
259 pubkeys[i] = vchPubKey;
261 else
263 throw std::runtime_error(" Invalid public key: "+ks);
266 CScript result = GetScriptForMultisig(nRequired, pubkeys);
268 if (result.size() > MAX_SCRIPT_ELEMENT_SIZE)
269 throw std::runtime_error(
270 strprintf("redeemScript exceeds size limit: %d > %d", result.size(), MAX_SCRIPT_ELEMENT_SIZE));
272 return result;
275 UniValue createmultisig(const JSONRPCRequest& request)
277 #ifdef ENABLE_WALLET
278 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
279 #else
280 CWallet * const pwallet = nullptr;
281 #endif
283 if (request.fHelp || request.params.size() < 2 || request.params.size() > 2)
285 std::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 std::runtime_error(msg);
312 // Construct using pay-to-script-hash:
313 CScript inner = _createmultisig_redeemScript(pwallet, request.params);
314 CScriptID innerID(inner);
316 UniValue result(UniValue::VOBJ);
317 result.push_back(Pair("address", EncodeDestination(innerID)));
318 result.push_back(Pair("redeemScript", HexStr(inner.begin(), inner.end())));
320 return result;
323 UniValue verifymessage(const JSONRPCRequest& request)
325 if (request.fHelp || request.params.size() != 3)
326 throw std::runtime_error(
327 "verifymessage \"address\" \"signature\" \"message\"\n"
328 "\nVerify a signed message\n"
329 "\nArguments:\n"
330 "1. \"address\" (string, required) The bitcoin address to use for the signature.\n"
331 "2. \"signature\" (string, required) The signature provided by the signer in base 64 encoding (see signmessage).\n"
332 "3. \"message\" (string, required) The message that was signed.\n"
333 "\nResult:\n"
334 "true|false (boolean) If the signature is verified or not.\n"
335 "\nExamples:\n"
336 "\nUnlock the wallet for 30 seconds\n"
337 + HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") +
338 "\nCreate the signature\n"
339 + HelpExampleCli("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"my message\"") +
340 "\nVerify the signature\n"
341 + HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"signature\" \"my message\"") +
342 "\nAs json rpc\n"
343 + HelpExampleRpc("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\", \"signature\", \"my message\"")
346 LOCK(cs_main);
348 std::string strAddress = request.params[0].get_str();
349 std::string strSign = request.params[1].get_str();
350 std::string strMessage = request.params[2].get_str();
352 CTxDestination destination = DecodeDestination(strAddress);
353 if (!IsValidDestination(destination)) {
354 throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address");
357 const CKeyID *keyID = boost::get<CKeyID>(&destination);
358 if (!keyID) {
359 throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
362 bool fInvalid = false;
363 std::vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
365 if (fInvalid)
366 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Malformed base64 encoding");
368 CHashWriter ss(SER_GETHASH, 0);
369 ss << strMessageMagic;
370 ss << strMessage;
372 CPubKey pubkey;
373 if (!pubkey.RecoverCompact(ss.GetHash(), vchSig))
374 return false;
376 return (pubkey.GetID() == *keyID);
379 UniValue signmessagewithprivkey(const JSONRPCRequest& request)
381 if (request.fHelp || request.params.size() != 2)
382 throw std::runtime_error(
383 "signmessagewithprivkey \"privkey\" \"message\"\n"
384 "\nSign a message with the private key of an address\n"
385 "\nArguments:\n"
386 "1. \"privkey\" (string, required) The private key to sign the message with.\n"
387 "2. \"message\" (string, required) The message to create a signature of.\n"
388 "\nResult:\n"
389 "\"signature\" (string) The signature of the message encoded in base 64\n"
390 "\nExamples:\n"
391 "\nCreate the signature\n"
392 + HelpExampleCli("signmessagewithprivkey", "\"privkey\" \"my message\"") +
393 "\nVerify the signature\n"
394 + HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"signature\" \"my message\"") +
395 "\nAs json rpc\n"
396 + HelpExampleRpc("signmessagewithprivkey", "\"privkey\", \"my message\"")
399 std::string strPrivkey = request.params[0].get_str();
400 std::string strMessage = request.params[1].get_str();
402 CBitcoinSecret vchSecret;
403 bool fGood = vchSecret.SetString(strPrivkey);
404 if (!fGood)
405 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key");
406 CKey key = vchSecret.GetKey();
407 if (!key.IsValid())
408 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Private key outside allowed range");
410 CHashWriter ss(SER_GETHASH, 0);
411 ss << strMessageMagic;
412 ss << strMessage;
414 std::vector<unsigned char> vchSig;
415 if (!key.SignCompact(ss.GetHash(), vchSig))
416 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Sign failed");
418 return EncodeBase64(vchSig.data(), vchSig.size());
421 UniValue setmocktime(const JSONRPCRequest& request)
423 if (request.fHelp || request.params.size() != 1)
424 throw std::runtime_error(
425 "setmocktime timestamp\n"
426 "\nSet the local time to given timestamp (-regtest only)\n"
427 "\nArguments:\n"
428 "1. timestamp (integer, required) Unix seconds-since-epoch timestamp\n"
429 " Pass 0 to go back to using the system time."
432 if (!Params().MineBlocksOnDemand())
433 throw std::runtime_error("setmocktime for regression testing (-regtest mode) only");
435 // For now, don't change mocktime if we're in the middle of validation, as
436 // this could have an effect on mempool time-based eviction, as well as
437 // IsCurrentForFeeEstimation() and IsInitialBlockDownload().
438 // TODO: figure out the right way to synchronize around mocktime, and
439 // ensure all call sites of GetTime() are accessing this safely.
440 LOCK(cs_main);
442 RPCTypeCheck(request.params, {UniValue::VNUM});
443 SetMockTime(request.params[0].get_int64());
445 return NullUniValue;
448 static UniValue RPCLockedMemoryInfo()
450 LockedPool::Stats stats = LockedPoolManager::Instance().stats();
451 UniValue obj(UniValue::VOBJ);
452 obj.push_back(Pair("used", uint64_t(stats.used)));
453 obj.push_back(Pair("free", uint64_t(stats.free)));
454 obj.push_back(Pair("total", uint64_t(stats.total)));
455 obj.push_back(Pair("locked", uint64_t(stats.locked)));
456 obj.push_back(Pair("chunks_used", uint64_t(stats.chunks_used)));
457 obj.push_back(Pair("chunks_free", uint64_t(stats.chunks_free)));
458 return obj;
461 #ifdef HAVE_MALLOC_INFO
462 static std::string RPCMallocInfo()
464 char *ptr = nullptr;
465 size_t size = 0;
466 FILE *f = open_memstream(&ptr, &size);
467 if (f) {
468 malloc_info(0, f);
469 fclose(f);
470 if (ptr) {
471 std::string rv(ptr, size);
472 free(ptr);
473 return rv;
476 return "";
478 #endif
480 UniValue getmemoryinfo(const JSONRPCRequest& request)
482 /* Please, avoid using the word "pool" here in the RPC interface or help,
483 * as users will undoubtedly confuse it with the other "memory pool"
485 if (request.fHelp || request.params.size() > 1)
486 throw std::runtime_error(
487 "getmemoryinfo (\"mode\")\n"
488 "Returns an object containing information about memory usage.\n"
489 "Arguments:\n"
490 "1. \"mode\" determines what kind of information is returned. This argument is optional, the default mode is \"stats\".\n"
491 " - \"stats\" returns general statistics about memory usage in the daemon.\n"
492 " - \"mallocinfo\" returns an XML string describing low-level heap state (only available if compiled with glibc 2.10+).\n"
493 "\nResult (mode \"stats\"):\n"
494 "{\n"
495 " \"locked\": { (json object) Information about locked memory manager\n"
496 " \"used\": xxxxx, (numeric) Number of bytes used\n"
497 " \"free\": xxxxx, (numeric) Number of bytes available in current arenas\n"
498 " \"total\": xxxxxxx, (numeric) Total number of bytes managed\n"
499 " \"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"
500 " \"chunks_used\": xxxxx, (numeric) Number allocated chunks\n"
501 " \"chunks_free\": xxxxx, (numeric) Number unused chunks\n"
502 " }\n"
503 "}\n"
504 "\nResult (mode \"mallocinfo\"):\n"
505 "\"<malloc version=\"1\">...\"\n"
506 "\nExamples:\n"
507 + HelpExampleCli("getmemoryinfo", "")
508 + HelpExampleRpc("getmemoryinfo", "")
511 std::string mode = request.params[0].isNull() ? "stats" : request.params[0].get_str();
512 if (mode == "stats") {
513 UniValue obj(UniValue::VOBJ);
514 obj.push_back(Pair("locked", RPCLockedMemoryInfo()));
515 return obj;
516 } else if (mode == "mallocinfo") {
517 #ifdef HAVE_MALLOC_INFO
518 return RPCMallocInfo();
519 #else
520 throw JSONRPCError(RPC_INVALID_PARAMETER, "mallocinfo is only available when compiled with glibc 2.10+");
521 #endif
522 } else {
523 throw JSONRPCError(RPC_INVALID_PARAMETER, "unknown mode " + mode);
527 uint32_t getCategoryMask(UniValue cats) {
528 cats = cats.get_array();
529 uint32_t mask = 0;
530 for (unsigned int i = 0; i < cats.size(); ++i) {
531 uint32_t flag = 0;
532 std::string cat = cats[i].get_str();
533 if (!GetLogCategory(&flag, &cat)) {
534 throw JSONRPCError(RPC_INVALID_PARAMETER, "unknown logging category " + cat);
536 if (flag == BCLog::NONE) {
537 return 0;
539 mask |= flag;
541 return mask;
544 UniValue logging(const JSONRPCRequest& request)
546 if (request.fHelp || request.params.size() > 2) {
547 throw std::runtime_error(
548 "logging ( <include> <exclude> )\n"
549 "Gets and sets the logging configuration.\n"
550 "When called without an argument, returns the list of categories with status that are currently being debug logged or not.\n"
551 "When called with arguments, adds or removes categories from debug logging and return the lists above.\n"
552 "The arguments are evaluated in order \"include\", \"exclude\".\n"
553 "If an item is both included and excluded, it will thus end up being excluded.\n"
554 "The valid logging categories are: " + ListLogCategories() + "\n"
555 "In addition, the following are available as category names with special meanings:\n"
556 " - \"all\", \"1\" : represent all logging categories.\n"
557 " - \"none\", \"0\" : even if other logging categories are specified, ignore all of them.\n"
558 "\nArguments:\n"
559 "1. \"include\" (array of strings, optional) A json array of categories to add debug logging\n"
560 " [\n"
561 " \"category\" (string) the valid logging category\n"
562 " ,...\n"
563 " ]\n"
564 "2. \"exclude\" (array of strings, optional) A json array of categories to remove debug logging\n"
565 " [\n"
566 " \"category\" (string) the valid logging category\n"
567 " ,...\n"
568 " ]\n"
569 "\nResult:\n"
570 "{ (json object where keys are the logging categories, and values indicates its status\n"
571 " \"category\": 0|1, (numeric) if being debug logged or not. 0:inactive, 1:active\n"
572 " ...\n"
573 "}\n"
574 "\nExamples:\n"
575 + HelpExampleCli("logging", "\"[\\\"all\\\"]\" \"[\\\"http\\\"]\"")
576 + HelpExampleRpc("logging", "[\"all\"], \"[libevent]\"")
580 uint32_t originalLogCategories = logCategories;
581 if (request.params[0].isArray()) {
582 logCategories |= getCategoryMask(request.params[0]);
585 if (request.params[1].isArray()) {
586 logCategories &= ~getCategoryMask(request.params[1]);
589 // Update libevent logging if BCLog::LIBEVENT has changed.
590 // If the library version doesn't allow it, UpdateHTTPServerLogging() returns false,
591 // in which case we should clear the BCLog::LIBEVENT flag.
592 // Throw an error if the user has explicitly asked to change only the libevent
593 // flag and it failed.
594 uint32_t changedLogCategories = originalLogCategories ^ logCategories;
595 if (changedLogCategories & BCLog::LIBEVENT) {
596 if (!UpdateHTTPServerLogging(logCategories & BCLog::LIBEVENT)) {
597 logCategories &= ~BCLog::LIBEVENT;
598 if (changedLogCategories == BCLog::LIBEVENT) {
599 throw JSONRPCError(RPC_INVALID_PARAMETER, "libevent logging cannot be updated when using libevent before v2.1.1.");
604 UniValue result(UniValue::VOBJ);
605 std::vector<CLogCategoryActive> vLogCatActive = ListActiveLogCategories();
606 for (const auto& logCatActive : vLogCatActive) {
607 result.pushKV(logCatActive.category, logCatActive.active);
610 return result;
613 UniValue echo(const JSONRPCRequest& request)
615 if (request.fHelp)
616 throw std::runtime_error(
617 "echo|echojson \"message\" ...\n"
618 "\nSimply echo back the input arguments. This command is for testing.\n"
619 "\nThe difference between echo and echojson is that echojson has argument conversion enabled in the client-side table in"
620 "bitcoin-cli and the GUI. There is no server-side difference."
623 return request.params;
626 static const CRPCCommand commands[] =
627 { // category name actor (function) argNames
628 // --------------------- ------------------------ ----------------------- ----------
629 { "control", "getmemoryinfo", &getmemoryinfo, {"mode"} },
630 { "control", "logging", &logging, {"include", "exclude"}},
631 { "util", "validateaddress", &validateaddress, {"address"} }, /* uses wallet if enabled */
632 { "util", "createmultisig", &createmultisig, {"nrequired","keys"} },
633 { "util", "verifymessage", &verifymessage, {"address","signature","message"} },
634 { "util", "signmessagewithprivkey", &signmessagewithprivkey, {"privkey","message"} },
636 /* Not shown in help */
637 { "hidden", "setmocktime", &setmocktime, {"timestamp"}},
638 { "hidden", "echo", &echo, {"arg0","arg1","arg2","arg3","arg4","arg5","arg6","arg7","arg8","arg9"}},
639 { "hidden", "echojson", &echo, {"arg0","arg1","arg2","arg3","arg4","arg5","arg6","arg7","arg8","arg9"}},
642 void RegisterMiscRPCCommands(CRPCTable &t)
644 for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
645 t.appendCommand(commands[vcidx].name, &commands[vcidx]);