Page MenuHomePhabricator

No OneTemporary

diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp
index 3784d09754..383dc6f8e2 100644
--- a/src/rpc/misc.cpp
+++ b/src/rpc/misc.cpp
@@ -1,588 +1,593 @@
// Copyright (c) 2010 Satoshi Nakamoto
// Copyright (c) 2009-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <chain.h>
#include <clientversion.h>
#include <config.h>
#include <core_io.h>
#include <httpserver.h>
#include <key_io.h>
#include <logging.h>
#include <net.h>
#include <netbase.h>
#include <outputtype.h>
#include <rpc/blockchain.h>
#include <rpc/server.h>
#include <rpc/util.h>
#include <timedata.h>
#include <util/check.h>
#include <util/strencodings.h>
#include <util/system.h>
#include <validation.h>
#include <warnings.h>
#include <univalue.h>
#include <cstdint>
#ifdef HAVE_MALLOC_INFO
#include <malloc.h>
#endif
static UniValue validateaddress(const Config &config,
const JSONRPCRequest &request) {
if (request.fHelp || request.params.size() != 1) {
- throw std::runtime_error(
- RPCHelpMan{
- "validateaddress",
- "\nReturn information about the given bitcoin address.\n",
- {
- {"address", RPCArg::Type::STR, /* opt */ false,
- /* default_val */ "", "The bitcoin address to validate"},
- }}
- .ToString() +
- "\nResult:\n"
- "{\n"
- " \"isvalid\" : true|false, (boolean) If the address is "
- "valid or not. If not, this is the only property returned.\n"
- " \"address\" : \"address\", (string) The bitcoin address "
- "validated\n"
- " \"scriptPubKey\" : \"hex\", (string) The hex-encoded "
- "scriptPubKey generated by the address\n"
- " \"isscript\" : true|false, (boolean) If the key is a "
- "script\n"
- "}\n"
- "\nExamples:\n" +
- HelpExampleCli("validateaddress",
- "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"") +
- HelpExampleRpc("validateaddress",
- "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\""));
+ throw std::runtime_error(RPCHelpMan{
+ "validateaddress",
+ "\nReturn information about the given bitcoin address.\n",
+ {
+ {"address", RPCArg::Type::STR, /* opt */ false,
+ /* default_val */ "", "The bitcoin address to validate"},
+ },
+ RPCResult{
+ "{\n"
+ " \"isvalid\" : true|false, (boolean) If the address is "
+ "valid or not. If not, this is the only property returned.\n"
+ " \"address\" : \"address\", (string) The bitcoin "
+ "address validated\n"
+ " \"scriptPubKey\" : \"hex\", (string) The hex-encoded "
+ "scriptPubKey generated by the address\n"
+ " \"isscript\" : true|false, (boolean) If the key is a "
+ "script\n"
+ "}\n"},
+ RPCExamples{
+ HelpExampleCli("validateaddress",
+ "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"") +
+ HelpExampleRpc("validateaddress",
+ "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")},
+ }
+ .ToStringWithResultsAndExamples());
}
CTxDestination dest =
DecodeDestination(request.params[0].get_str(), config.GetChainParams());
bool isValid = IsValidDestination(dest);
UniValue ret(UniValue::VOBJ);
ret.pushKV("isvalid", isValid);
if (isValid) {
if (ret["address"].isNull()) {
std::string currentAddress = EncodeDestination(dest, config);
ret.pushKV("address", currentAddress);
CScript scriptPubKey = GetScriptForDestination(dest);
ret.pushKV("scriptPubKey",
HexStr(scriptPubKey.begin(), scriptPubKey.end()));
UniValue detail = DescribeAddress(dest);
ret.pushKVs(detail);
}
}
return ret;
}
static UniValue createmultisig(const Config &config,
const JSONRPCRequest &request) {
if (request.fHelp || request.params.size() < 2 ||
request.params.size() > 2) {
std::string msg =
RPCHelpMan{
"createmultisig",
"\nCreates a multi-signature address with n signature of m "
"keys required.\n"
"It returns a json object with the address and redeemScript.\n",
{
{"nrequired", RPCArg::Type::NUM, /* opt */ false,
/* default_val */ "",
"The number of required signatures out of the n keys."},
{"keys",
RPCArg::Type::ARR,
/* opt */ false,
/* default_val */ "",
"A json array of hex-encoded public keys.",
{
{"key", RPCArg::Type::STR_HEX, /* opt */ false,
/* default_val */ "", "The hex-encoded public key"},
}},
- }}
- .ToString() +
- "\nResult:\n"
- "{\n"
- " \"address\":\"multisigaddress\", (string) The value of the new "
- "multisig address.\n"
- " \"redeemScript\":\"script\" (string) The string value of "
- "the hex-encoded redemption script.\n"
- "}\n"
-
- "\nExamples:\n"
- "\nCreate a multisig address from 2 public keys\n" +
- HelpExampleCli("createmultisig",
- "2 "
- "\"["
- "\\\"03789ed0bb717d88f7d321a368d905e7430207ebbd82bd3"
- "42cf11ae157a7ace5fd\\\","
- "\\\"03dbc6764b8884a92e871274b87583e6d5c2a58819473e1"
- "7e107ef3f6aa5a61626\\\"]\"") +
- "\nAs a JSON-RPC call\n" +
- HelpExampleRpc("createmultisig",
- "2, "
- "\"["
- "\\\"03789ed0bb717d88f7d321a368d905e7430207ebbd82bd3"
- "42cf11ae157a7ace5fd\\\","
- "\\\"03dbc6764b8884a92e871274b87583e6d5c2a58819473e1"
- "7e107ef3f6aa5a61626\\\"]\"");
+ },
+ RPCResult{"{\n"
+ " \"address\":\"multisigaddress\", (string) The "
+ "value of the new multisig address.\n"
+ " \"redeemScript\":\"script\" (string) The "
+ "string value of the hex-encoded redemption script.\n"
+ "}\n"},
+ RPCExamples{
+ "\nCreate a multisig address from 2 public keys\n" +
+ HelpExampleCli(
+ "createmultisig",
+ "2 "
+ "\"["
+ "\\\"03789ed0bb717d88f7d321a368d905e7430207ebbd82bd3"
+ "42cf11ae157a7ace5fd\\\","
+ "\\\"03dbc6764b8884a92e871274b87583e6d5c2a58819473e1"
+ "7e107ef3f6aa5a61626\\\"]\"") +
+ "\nAs a JSON-RPC call\n" +
+ HelpExampleRpc(
+ "createmultisig",
+ "2, "
+ "\"["
+ "\\\"03789ed0bb717d88f7d321a368d905e7430207ebbd82bd3"
+ "42cf11ae157a7ace5fd\\\","
+ "\\\"03dbc6764b8884a92e871274b87583e6d5c2a58819473e1"
+ "7e107ef3f6aa5a61626\\\"]\"")},
+ }
+ .ToStringWithResultsAndExamples();
throw std::runtime_error(msg);
}
int required = request.params[0].get_int();
// Get the public keys
const UniValue &keys = request.params[1].get_array();
std::vector<CPubKey> pubkeys;
for (size_t i = 0; i < keys.size(); ++i) {
if ((keys[i].get_str().length() ==
2 * CPubKey::COMPRESSED_PUBLIC_KEY_SIZE ||
keys[i].get_str().length() == 2 * CPubKey::PUBLIC_KEY_SIZE) &&
IsHex(keys[i].get_str())) {
pubkeys.push_back(HexToPubKey(keys[i].get_str()));
} else {
throw JSONRPCError(
RPC_INVALID_ADDRESS_OR_KEY,
strprintf("Invalid public key: %s\n", keys[i].get_str()));
}
}
// Get the output type
OutputType output_type = OutputType::LEGACY;
// Construct using pay-to-script-hash:
const CScript inner = CreateMultisigRedeemscript(required, pubkeys);
CBasicKeyStore keystore;
const CTxDestination dest =
AddAndGetDestinationForScript(keystore, inner, output_type);
UniValue result(UniValue::VOBJ);
result.pushKV("address", EncodeDestination(dest, config));
result.pushKV("redeemScript", HexStr(inner.begin(), inner.end()));
return result;
}
static UniValue verifymessage(const Config &config,
const JSONRPCRequest &request) {
if (request.fHelp || request.params.size() != 3) {
- throw std::runtime_error(
- RPCHelpMan{
- "verifymessage",
- "\nVerify a signed message\n",
- {
- {"address", RPCArg::Type::STR, /* opt */ false,
- /* default_val */ "",
- "The bitcoin address to use for the signature."},
- {"signature", RPCArg::Type::STR, /* opt */ false,
- /* default_val */ "",
- "The signature provided by the signer in base 64 encoding "
- "(see signmessage)."},
- {"message", RPCArg::Type::STR, /* opt */ false,
- /* default_val */ "", "The message that was signed."},
- }}
- .ToString() +
- "\nResult:\n"
- "true|false (boolean) If the signature is verified or not.\n"
- "\nExamples:\n"
- "\nUnlock the wallet for 30 seconds\n" +
- HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") +
- "\nCreate the signature\n" +
- HelpExampleCli(
- "signmessage",
- "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"my message\"") +
- "\nVerify the signature\n" +
- HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4"
- "XX\" \"signature\" \"my "
- "message\"") +
- "\nAs a JSON-RPC call\n" +
- HelpExampleRpc("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4"
- "XX\", \"signature\", \"my "
- "message\""));
+ throw std::runtime_error(RPCHelpMan{
+ "verifymessage",
+ "\nVerify a signed message\n",
+ {
+ {"address", RPCArg::Type::STR, /* opt */ false,
+ /* default_val */ "",
+ "The bitcoin address to use for the signature."},
+ {"signature", RPCArg::Type::STR, /* opt */ false,
+ /* default_val */ "",
+ "The signature provided by the signer in base 64 encoding "
+ "(see signmessage)."},
+ {"message", RPCArg::Type::STR, /* opt */ false,
+ /* default_val */ "", "The message that was signed."},
+ },
+ RPCResult{"true|false (boolean) If the signature is verified or "
+ "not.\n"},
+ RPCExamples{
+ "\nUnlock the wallet for 30 seconds\n" +
+ HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") +
+ "\nCreate the signature\n" +
+ HelpExampleCli(
+ "signmessage",
+ "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"my message\"") +
+ "\nVerify the signature\n" +
+ HelpExampleCli("verifymessage",
+ "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4"
+ "XX\" \"signature\" \"my "
+ "message\"") +
+ "\nAs a JSON-RPC call\n" +
+ HelpExampleRpc("verifymessage",
+ "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4"
+ "XX\", \"signature\", \"my "
+ "message\"")},
+ }
+ .ToStringWithResultsAndExamples());
}
LOCK(cs_main);
std::string strAddress = request.params[0].get_str();
std::string strSign = request.params[1].get_str();
std::string strMessage = request.params[2].get_str();
CTxDestination destination =
DecodeDestination(strAddress, config.GetChainParams());
if (!IsValidDestination(destination)) {
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address");
}
const CKeyID *keyID = boost::get<CKeyID>(&destination);
if (!keyID) {
throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
}
bool fInvalid = false;
std::vector<uint8_t> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
if (fInvalid) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY,
"Malformed base64 encoding");
}
CHashWriter ss(SER_GETHASH, 0);
ss << strMessageMagic;
ss << strMessage;
CPubKey pubkey;
if (!pubkey.RecoverCompact(ss.GetHash(), vchSig)) {
return false;
}
return (pubkey.GetID() == *keyID);
}
static UniValue signmessagewithprivkey(const Config &config,
const JSONRPCRequest &request) {
if (request.fHelp || request.params.size() != 2) {
- throw std::runtime_error(
- RPCHelpMan{"signmessagewithprivkey",
- "\nSign a message with the private key of an address\n",
- {
- {"privkey", RPCArg::Type::STR, /* opt */ false,
- /* default_val */ "",
- "The private key to sign the message with."},
- {"message", RPCArg::Type::STR, /* opt */ false,
- /* default_val */ "",
- "The message to create a signature of."},
- }}
- .ToString() +
- "\nResult:\n"
- "\"signature\" (string) The signature of the message "
- "encoded in base 64\n"
- "\nExamples:\n"
- "\nCreate the signature\n" +
- HelpExampleCli("signmessagewithprivkey",
- "\"privkey\" \"my message\"") +
- "\nVerify the signature\n" +
- HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4"
- "XX\" \"signature\" \"my "
- "message\"") +
- "\nAs a JSON-RPC call\n" +
- HelpExampleRpc("signmessagewithprivkey",
- "\"privkey\", \"my message\""));
+ throw std::runtime_error(RPCHelpMan{
+ "signmessagewithprivkey",
+ "\nSign a message with the private key of an address\n",
+ {
+ {"privkey", RPCArg::Type::STR, /* opt */ false,
+ /* default_val */ "",
+ "The private key to sign the message with."},
+ {"message", RPCArg::Type::STR, /* opt */ false,
+ /* default_val */ "", "The message to create a signature of."},
+ },
+ RPCResult{"\"signature\" (string) The signature of the "
+ "message encoded in base 64\n"},
+ RPCExamples{"\nCreate the signature\n" +
+ HelpExampleCli("signmessagewithprivkey",
+ "\"privkey\" \"my message\"") +
+ "\nVerify the signature\n" +
+ HelpExampleCli("verifymessage",
+ "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4"
+ "XX\" \"signature\" \"my "
+ "message\"") +
+ "\nAs a JSON-RPC call\n" +
+ HelpExampleRpc("signmessagewithprivkey",
+ "\"privkey\", \"my message\"")},
+ }
+ .ToStringWithResultsAndExamples());
}
std::string strPrivkey = request.params[0].get_str();
std::string strMessage = request.params[1].get_str();
CKey key = DecodeSecret(strPrivkey);
if (!key.IsValid()) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key");
}
CHashWriter ss(SER_GETHASH, 0);
ss << strMessageMagic;
ss << strMessage;
std::vector<uint8_t> vchSig;
if (!key.SignCompact(ss.GetHash(), vchSig)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Sign failed");
}
return EncodeBase64(vchSig.data(), vchSig.size());
}
static UniValue setmocktime(const Config &config,
const JSONRPCRequest &request) {
if (request.fHelp || request.params.size() != 1) {
throw std::runtime_error(RPCHelpMan{
"setmocktime",
"\nSet the local time to given timestamp (-regtest only)\n",
{
{"timestamp", RPCArg::Type::NUM, /* opt */ false,
/* default_val */ "",
"Unix seconds-since-epoch timestamp\n"
" Pass 0 to go back to using the system time."},
- }}.ToString());
+ },
+ RPCResults{},
+ RPCExamples{""},
+ }
+ .ToStringWithResultsAndExamples());
}
if (!config.GetChainParams().MineBlocksOnDemand()) {
throw std::runtime_error(
"setmocktime for regression testing (-regtest mode) only");
}
// For now, don't change mocktime if we're in the middle of validation, as
// this could have an effect on mempool time-based eviction, as well as
// IsInitialBlockDownload().
// TODO: figure out the right way to synchronize around mocktime, and
// ensure all call sites of GetTime() are accessing this safely.
LOCK(cs_main);
RPCTypeCheck(request.params, {UniValue::VNUM});
SetMockTime(request.params[0].get_int64());
return NullUniValue;
}
static UniValue RPCLockedMemoryInfo() {
LockedPool::Stats stats = LockedPoolManager::Instance().stats();
UniValue obj(UniValue::VOBJ);
obj.pushKV("used", uint64_t(stats.used));
obj.pushKV("free", uint64_t(stats.free));
obj.pushKV("total", uint64_t(stats.total));
obj.pushKV("locked", uint64_t(stats.locked));
obj.pushKV("chunks_used", uint64_t(stats.chunks_used));
obj.pushKV("chunks_free", uint64_t(stats.chunks_free));
return obj;
}
#ifdef HAVE_MALLOC_INFO
static std::string RPCMallocInfo() {
char *ptr = nullptr;
size_t size = 0;
FILE *f = open_memstream(&ptr, &size);
if (f) {
malloc_info(0, f);
fclose(f);
if (ptr) {
std::string rv(ptr, size);
free(ptr);
return rv;
}
}
return "";
}
#endif
static UniValue getmemoryinfo(const Config &config,
const JSONRPCRequest &request) {
/* Please, avoid using the word "pool" here in the RPC interface or help,
* as users will undoubtedly confuse it with the other "memory pool"
*/
if (request.fHelp || request.params.size() > 1) {
- throw std::runtime_error(
- RPCHelpMan{
- "getmemoryinfo",
- "Returns an object containing information about memory "
- "usage.\n",
- {
- {"mode", RPCArg::Type::STR, /* opt */ true,
- /* default_val */ "",
- "determines what kind of information is returned. This "
- "argument is optional, the default mode is \"stats\".\n"
- " - \"stats\" returns general statistics about memory "
- "usage in the daemon.\n"
- " - \"mallocinfo\" returns an XML string describing "
- "low-level heap state (only available if compiled with "
- "glibc 2.10+)."},
- }}
- .ToString() +
- "\nResult (mode \"stats\"):\n"
- "{\n"
- " \"locked\": { (json object) Information about "
- "locked memory manager\n"
- " \"used\": xxxxx, (numeric) Number of bytes used\n"
- " \"free\": xxxxx, (numeric) Number of bytes available "
- "in current arenas\n"
- " \"total\": xxxxxxx, (numeric) Total number of bytes "
- "managed\n"
- " \"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"
- " \"chunks_used\": xxxxx, (numeric) Number allocated chunks\n"
- " \"chunks_free\": xxxxx, (numeric) Number unused chunks\n"
- " }\n"
- "}\n"
- "\nResult (mode \"mallocinfo\"):\n"
- "\"<malloc version=\"1\">...\"\n"
- "\nExamples:\n" +
- HelpExampleCli("getmemoryinfo", "") +
- HelpExampleRpc("getmemoryinfo", ""));
+ throw std::runtime_error(RPCHelpMan{
+ "getmemoryinfo",
+ "Returns an object containing information about memory usage.\n",
+ {
+ {"mode", RPCArg::Type::STR, /* opt */ true,
+ /* default_val */ "",
+ "determines what kind of information is returned. This "
+ "argument is optional, the default mode is \"stats\".\n"
+ " - \"stats\" returns general statistics about memory usage "
+ "in the daemon.\n"
+ " - \"mallocinfo\" returns an XML string describing "
+ "low-level heap state (only available if compiled with glibc "
+ "2.10+)."},
+ },
+ {
+ RPCResult{"mode \"stats\"",
+ "{\n"
+ " \"locked\": { (json object) "
+ "Information about locked memory manager\n"
+ " \"used\": xxxxx, (numeric) Number of "
+ "bytes used\n"
+ " \"free\": xxxxx, (numeric) Number of "
+ "bytes available in current arenas\n"
+ " \"total\": xxxxxxx, (numeric) Total "
+ "number of bytes managed\n"
+ " \"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"
+ " \"chunks_used\": xxxxx, (numeric) Number "
+ "allocated chunks\n"
+ " \"chunks_free\": xxxxx, (numeric) Number "
+ "unused chunks\n"
+ " }\n"
+ "}\n"},
+ RPCResult{"mode \"mallocinfo\"",
+ "\"<malloc version=\"1\">...\"\n"},
+ },
+ RPCExamples{HelpExampleCli("getmemoryinfo", "") +
+ HelpExampleRpc("getmemoryinfo", "")},
+ }
+ .ToStringWithResultsAndExamples());
}
std::string mode =
request.params[0].isNull() ? "stats" : request.params[0].get_str();
if (mode == "stats") {
UniValue obj(UniValue::VOBJ);
obj.pushKV("locked", RPCLockedMemoryInfo());
return obj;
} else if (mode == "mallocinfo") {
#ifdef HAVE_MALLOC_INFO
return RPCMallocInfo();
#else
throw JSONRPCError(
RPC_INVALID_PARAMETER,
"mallocinfo is only available when compiled with glibc 2.10+");
#endif
} else {
throw JSONRPCError(RPC_INVALID_PARAMETER, "unknown mode " + mode);
}
}
static void EnableOrDisableLogCategories(UniValue cats, bool enable) {
cats = cats.get_array();
for (size_t i = 0; i < cats.size(); ++i) {
std::string cat = cats[i].get_str();
bool success;
if (enable) {
success = LogInstance().EnableCategory(cat);
} else {
success = LogInstance().DisableCategory(cat);
}
if (!success) {
throw JSONRPCError(RPC_INVALID_PARAMETER,
"unknown logging category " + cat);
}
}
}
static UniValue logging(const Config &config, const JSONRPCRequest &request) {
if (request.fHelp || request.params.size() > 2) {
- throw std::runtime_error(
- RPCHelpMan{
- "logging",
- "Gets and sets the logging configuration.\n"
- "When called without an argument, returns the list of "
- "categories with status that are currently being debug logged "
- "or not.\n"
- "When called with arguments, adds or removes categories from "
- "debug logging and return the lists above.\n"
- "The arguments are evaluated in order \"include\", "
- "\"exclude\".\n"
- "If an item is both included and excluded, it will thus end up "
- "being excluded.\n"
- "The valid logging categories are: " +
- ListLogCategories() +
- "\n"
- "In addition, the following are available as category "
- "names with special meanings:\n"
- " - \"all\", \"1\" : represent all logging categories.\n"
- " - \"none\", \"0\" : even if other logging categories "
- "are specified, ignore all of them.\n",
- {
- {"include",
- RPCArg::Type::ARR,
- /* opt */ true,
- /* default_val */ "",
- "A json array of categories to add debug logging",
- {
- {"include_category", RPCArg::Type::STR,
- /* opt */ false, /* default_val */ "",
- "the valid logging category"},
- }},
- {"exclude",
- RPCArg::Type::ARR,
- /* opt */ true,
- /* default_val */ "",
- "A json array of categories to remove debug logging",
- {
- {"exclude_category", RPCArg::Type::STR,
- /* opt */ false, /* default_val */ "",
- "the valid logging category"},
- }},
- }}
- .ToString() +
- "\nResult:\n"
- "{ (json object where keys are the logging "
- "categories, and values indicates its status\n"
- " \"category\": 0|1, (numeric) if being debug logged or not. "
- "0:inactive, 1:active\n"
- " ...\n"
- "}\n"
- "\nExamples:\n" +
- HelpExampleCli("logging", "\"[\\\"all\\\"]\" \"[\\\"http\\\"]\"") +
- HelpExampleRpc("logging", "[\"all\"], \"[libevent]\""));
+ throw std::runtime_error(RPCHelpMan{
+ "logging",
+ "Gets and sets the logging configuration.\n"
+ "When called without an argument, returns the list of categories "
+ "with status that are currently being debug logged or not.\n"
+ "When called with arguments, adds or removes categories from debug "
+ "logging and return the lists above.\n"
+ "The arguments are evaluated in order \"include\", \"exclude\".\n"
+ "If an item is both included and excluded, it will thus end up "
+ "being excluded.\n"
+ "The valid logging categories are: " +
+ ListLogCategories() +
+ "\n"
+ "In addition, the following are available as category names "
+ "with special meanings:\n"
+ " - \"all\", \"1\" : represent all logging categories.\n"
+ " - \"none\", \"0\" : even if other logging categories are "
+ "specified, ignore all of them.\n",
+ {
+ {"include",
+ RPCArg::Type::ARR,
+ /* opt */ true,
+ /* default_val */ "",
+ "A json array of categories to add debug logging",
+ {
+ {"include_category", RPCArg::Type::STR,
+ /* opt */ false, /* default_val */ "",
+ "the valid logging category"},
+ }},
+ {"exclude",
+ RPCArg::Type::ARR,
+ /* opt */ true,
+ /* default_val */ "",
+ "A json array of categories to remove debug logging",
+ {
+ {"exclude_category", RPCArg::Type::STR,
+ /* opt */ false, /* default_val */ "",
+ "the valid logging category"},
+ }},
+ },
+ RPCResult{"{ (json object where keys are the "
+ "logging categories, and values indicates its status\n"
+ " \"category\": 0|1, (numeric) if being debug logged "
+ "or not. 0:inactive, 1:active\n"
+ " ...\n"
+ "}\n"},
+ RPCExamples{HelpExampleCli("logging",
+ "\"[\\\"all\\\"]\" \"[\\\"http\\\"]\"") +
+ HelpExampleRpc("logging", "[\"all\"], \"[libevent]\"")},
+ }
+ .ToStringWithResultsAndExamples());
}
uint32_t original_log_categories = LogInstance().GetCategoryMask();
if (request.params[0].isArray()) {
EnableOrDisableLogCategories(request.params[0], true);
}
if (request.params[1].isArray()) {
EnableOrDisableLogCategories(request.params[1], false);
}
uint32_t updated_log_categories = LogInstance().GetCategoryMask();
uint32_t changed_log_categories =
original_log_categories ^ updated_log_categories;
/**
* Update libevent logging if BCLog::LIBEVENT has changed.
* If the library version doesn't allow it, UpdateHTTPServerLogging()
* returns false, in which case we should clear the BCLog::LIBEVENT flag.
* Throw an error if the user has explicitly asked to change only the
* libevent flag and it failed.
*/
if (changed_log_categories & BCLog::LIBEVENT) {
if (!UpdateHTTPServerLogging(
LogInstance().WillLogCategory(BCLog::LIBEVENT))) {
LogInstance().DisableCategory(BCLog::LIBEVENT);
if (changed_log_categories == BCLog::LIBEVENT) {
throw JSONRPCError(RPC_INVALID_PARAMETER,
"libevent logging cannot be updated when "
"using libevent before v2.1.1.");
}
}
}
UniValue result(UniValue::VOBJ);
std::vector<CLogCategoryActive> vLogCatActive = ListActiveLogCategories();
for (const auto &logCatActive : vLogCatActive) {
result.pushKV(logCatActive.category, logCatActive.active);
}
return result;
}
static UniValue echo(const Config &config, const JSONRPCRequest &request) {
if (request.fHelp) {
- throw std::runtime_error(
- RPCHelpMan{
- "echo|echojson ...",
- "\nSimply echo back the input arguments. This command is for "
- "testing.\n"
- "\nIt will return an internal bug report when exactly 100 "
- "arguments are passed.\n"
- "\nThe difference between echo and echojson is that echojson "
- "has argument conversion enabled in the client-side table in "
- "bitcoin-cli and the GUI. There is no server-side difference.",
- {}}
- .ToString() +
- "");
+ throw std::runtime_error(RPCHelpMan{
+ "echo|echojson ...",
+ "\nSimply echo back the input arguments. This command is for "
+ "testing.\n"
+ "\nThe difference between echo and echojson is that echojson has "
+ "argument conversion enabled in the client-side table in "
+ "bitcoin-cli and the GUI. There is no server-side difference.",
+ {},
+ RPCResults{},
+ RPCExamples{""},
+ }
+ .ToStringWithResultsAndExamples());
}
CHECK_NONFATAL(request.params.size() != 100);
return request.params;
}
// clang-format off
static const CRPCCommand commands[] = {
// category name actor (function) argNames
// ------------------- ------------------------ ---------------------- ----------
{ "control", "getmemoryinfo", getmemoryinfo, {"mode"} },
{ "control", "logging", logging, {"include", "exclude"} },
{ "util", "validateaddress", validateaddress, {"address"} },
{ "util", "createmultisig", createmultisig, {"nrequired","keys"} },
{ "util", "verifymessage", verifymessage, {"address","signature","message"} },
{ "util", "signmessagewithprivkey", signmessagewithprivkey, {"privkey","message"} },
/* Not shown in help */
{ "hidden", "setmocktime", setmocktime, {"timestamp"}},
{ "hidden", "echo", echo, {"arg0","arg1","arg2","arg3","arg4","arg5","arg6","arg7","arg8","arg9"}},
{ "hidden", "echojson", echo, {"arg0","arg1","arg2","arg3","arg4","arg5","arg6","arg7","arg8","arg9"}},
};
// clang-format on
void RegisterMiscRPCCommands(CRPCTable &t) {
for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++) {
t.appendCommand(commands[vcidx].name, &commands[vcidx]);
}
}

File Metadata

Mime Type
text/x-diff
Expires
Wed, May 21, 22:57 (23 h, 37 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5866113
Default Alt Text
(35 KB)

Event Timeline