Changeset View
Changeset View
Standalone View
Standalone View
src/rpc/misc.cpp
Show All 10 Lines | |||||
#include <key_io.h> | #include <key_io.h> | ||||
#include <logging.h> | #include <logging.h> | ||||
#include <net.h> | #include <net.h> | ||||
#include <netbase.h> | #include <netbase.h> | ||||
#include <outputtype.h> | #include <outputtype.h> | ||||
#include <rpc/blockchain.h> | #include <rpc/blockchain.h> | ||||
#include <rpc/server.h> | #include <rpc/server.h> | ||||
#include <rpc/util.h> | #include <rpc/util.h> | ||||
#include <script/descriptor.h> | |||||
#include <timedata.h> | #include <timedata.h> | ||||
#include <util/check.h> | #include <util/check.h> | ||||
#include <util/strencodings.h> | #include <util/strencodings.h> | ||||
#include <util/system.h> | #include <util/system.h> | ||||
#include <util/validation.h> | #include <util/validation.h> | ||||
#include <validation.h> | #include <validation.h> | ||||
#include <warnings.h> | #include <warnings.h> | ||||
▲ Show 20 Lines • Show All 140 Lines • ▼ Show 20 Lines | static UniValue createmultisig(const Config &config, | ||||
UniValue result(UniValue::VOBJ); | UniValue result(UniValue::VOBJ); | ||||
result.pushKV("address", EncodeDestination(dest, config)); | result.pushKV("address", EncodeDestination(dest, config)); | ||||
result.pushKV("redeemScript", HexStr(inner.begin(), inner.end())); | result.pushKV("redeemScript", HexStr(inner.begin(), inner.end())); | ||||
return result; | return result; | ||||
} | } | ||||
UniValue deriveaddresses(const Config &config, const JSONRPCRequest &request) { | |||||
if (request.fHelp || request.params.empty() || request.params.size() > 3) { | |||||
throw std::runtime_error(RPCHelpMan{ | |||||
"deriveaddresses", | |||||
{"\nDerives one or more addresses corresponding to an output " | |||||
"descriptor.\n" | |||||
"Examples of output descriptors are:\n" | |||||
" pkh(<pubkey>) P2PKH outputs for the " | |||||
"given pubkey\n" | |||||
" sh(multi(<n>,<pubkey>,<pubkey>,...)) P2SH-multisig outputs " | |||||
"for the given threshold and pubkeys\n" | |||||
" raw(<hex script>) Outputs whose " | |||||
"scriptPubKey equals the specified hex scripts\n" | |||||
"\nIn the above, <pubkey> either refers to a fixed public key in " | |||||
"hexadecimal notation, or to an xpub/xprv optionally followed by " | |||||
"one\n" | |||||
"or more path elements separated by \"/\", where \"h\" represents " | |||||
"a hardened child key.\n" | |||||
"For more information on output descriptors, see the " | |||||
"documentation in the doc/descriptors.md file.\n"}, | |||||
{{"descriptor", RPCArg::Type::STR, /* opt */ false, | |||||
/* default_val */ "", "The descriptor."}, | |||||
{"begin", RPCArg::Type::NUM, /* opt */ true, /* default_val */ "", | |||||
"If a ranged descriptor is used, this specifies the beginning of " | |||||
"the range to import."}, | |||||
{"end", RPCArg::Type::NUM, /* opt */ true, /* default_val */ "", | |||||
"If a ranged descriptor is used, this specifies the end of the " | |||||
"range to import."}}, | |||||
RPCResult{"[ address ] (array) the derived addresses\n"}, | |||||
RPCExamples{ | |||||
"First three native segwit receive addresses\n" + | |||||
HelpExampleCli( | |||||
"deriveaddresses", | |||||
"\"pkh([d34db33f/84h/0h/" | |||||
"0h]" | |||||
"xpub6DJ2dNUysrn5Vt36jH2KLBT2i1auw1tTSSomg8PhqNiUtx8QX2SvC9" | |||||
"nrHu81fT41fvDUnhMjEzQgXnQjKEu3oaqMSzhSrHMxyyoEAmUHQbY/0/" | |||||
"*)\" 0 2")}}.ToString()); | |||||
} | |||||
RPCTypeCheck(request.params, | |||||
{UniValue::VSTR, UniValue::VNUM, UniValue::VNUM}); | |||||
const std::string desc_str = request.params[0].get_str(); | |||||
int range_begin = 0; | |||||
int range_end = 0; | |||||
if (request.params.size() >= 2) { | |||||
if (request.params.size() == 2) { | |||||
throw JSONRPCError(RPC_INVALID_PARAMETER, | |||||
"Missing range end parameter"); | |||||
} | |||||
range_begin = request.params[1].get_int(); | |||||
range_end = request.params[2].get_int(); | |||||
if (range_begin < 0) { | |||||
throw JSONRPCError(RPC_INVALID_PARAMETER, | |||||
"Range should be greater or equal than 0"); | |||||
} | |||||
if (range_begin > range_end) { | |||||
throw JSONRPCError( | |||||
RPC_INVALID_PARAMETER, | |||||
"Range end should be equal to or greater than begin"); | |||||
} | |||||
} | |||||
FlatSigningProvider provider; | |||||
auto desc = Parse(desc_str, provider); | |||||
if (!desc) { | |||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, | |||||
strprintf("Invalid descriptor")); | |||||
} | |||||
if (!desc->IsRange() && request.params.size() > 1) { | |||||
throw JSONRPCError( | |||||
RPC_INVALID_PARAMETER, | |||||
"Range should not be specified for an un-ranged descriptor"); | |||||
} | |||||
if (desc->IsRange() && request.params.size() == 1) { | |||||
throw JSONRPCError(RPC_INVALID_PARAMETER, | |||||
"Range must be specified for a ranged descriptor"); | |||||
} | |||||
UniValue addresses(UniValue::VARR); | |||||
for (int i = range_begin; i <= range_end; ++i) { | |||||
std::vector<CScript> scripts; | |||||
if (!desc->Expand(i, provider, scripts, provider)) { | |||||
throw JSONRPCError( | |||||
RPC_INVALID_ADDRESS_OR_KEY, | |||||
strprintf("Cannot derive script without private keys")); | |||||
} | |||||
for (const CScript &script : scripts) { | |||||
CTxDestination dest; | |||||
if (!ExtractDestination(script, dest)) { | |||||
throw JSONRPCError( | |||||
RPC_INVALID_ADDRESS_OR_KEY, | |||||
strprintf( | |||||
"Descriptor does not have a corresponding address")); | |||||
} | |||||
addresses.push_back(EncodeDestination(dest, config)); | |||||
} | |||||
} | |||||
// This should not be possible, but an assert seems overkill: | |||||
if (addresses.empty()) { | |||||
throw JSONRPCError(RPC_MISC_ERROR, "Unexpected empty result"); | |||||
} | |||||
return addresses; | |||||
} | |||||
static UniValue verifymessage(const Config &config, | static UniValue verifymessage(const Config &config, | ||||
const JSONRPCRequest &request) { | const JSONRPCRequest &request) { | ||||
if (request.fHelp || request.params.size() != 3) { | if (request.fHelp || request.params.size() != 3) { | ||||
throw std::runtime_error(RPCHelpMan{ | throw std::runtime_error(RPCHelpMan{ | ||||
"verifymessage", | "verifymessage", | ||||
"\nVerify a signed message\n", | "\nVerify a signed message\n", | ||||
{ | { | ||||
{"address", RPCArg::Type::STR, /* opt */ false, | {"address", RPCArg::Type::STR, /* opt */ false, | ||||
▲ Show 20 Lines • Show All 395 Lines • ▼ Show 20 Lines | |||||
// clang-format off | // clang-format off | ||||
static const CRPCCommand commands[] = { | static const CRPCCommand commands[] = { | ||||
// category name actor (function) argNames | // category name actor (function) argNames | ||||
// ------------------- ------------------------ ---------------------- ---------- | // ------------------- ------------------------ ---------------------- ---------- | ||||
{ "control", "getmemoryinfo", getmemoryinfo, {"mode"} }, | { "control", "getmemoryinfo", getmemoryinfo, {"mode"} }, | ||||
{ "control", "logging", logging, {"include", "exclude"} }, | { "control", "logging", logging, {"include", "exclude"} }, | ||||
{ "util", "validateaddress", validateaddress, {"address"} }, | { "util", "validateaddress", validateaddress, {"address"} }, | ||||
{ "util", "createmultisig", createmultisig, {"nrequired","keys"} }, | { "util", "createmultisig", createmultisig, {"nrequired","keys"} }, | ||||
{ "util", "deriveaddresses", deriveaddresses, {"descriptor", "begin", "end"} }, | |||||
{ "util", "verifymessage", verifymessage, {"address","signature","message"} }, | { "util", "verifymessage", verifymessage, {"address","signature","message"} }, | ||||
{ "util", "signmessagewithprivkey", signmessagewithprivkey, {"privkey","message"} }, | { "util", "signmessagewithprivkey", signmessagewithprivkey, {"privkey","message"} }, | ||||
/* Not shown in help */ | /* Not shown in help */ | ||||
{ "hidden", "setmocktime", setmocktime, {"timestamp"}}, | { "hidden", "setmocktime", setmocktime, {"timestamp"}}, | ||||
{ "hidden", "echo", echo, {"arg0","arg1","arg2","arg3","arg4","arg5","arg6","arg7","arg8","arg9"}}, | { "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"}}, | { "hidden", "echojson", echo, {"arg0","arg1","arg2","arg3","arg4","arg5","arg6","arg7","arg8","arg9"}}, | ||||
}; | }; | ||||
// clang-format on | // clang-format on | ||||
void RegisterMiscRPCCommands(CRPCTable &t) { | void RegisterMiscRPCCommands(CRPCTable &t) { | ||||
for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++) { | for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++) { | ||||
t.appendCommand(commands[vcidx].name, &commands[vcidx]); | t.appendCommand(commands[vcidx].name, &commands[vcidx]); | ||||
} | } | ||||
} | } |