Skip to content

Commit 2a0df15

Browse files
committed
merge bitcoin#25058: Move output script RPCs to separate file, rename misc.cpp
Review with `git log -p -n1 --color-moved=dimmed_zebra`.
1 parent 4653ea3 commit 2a0df15

File tree

4 files changed

+292
-253
lines changed

4 files changed

+292
-253
lines changed

src/Makefile.am

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -546,8 +546,9 @@ libbitcoin_node_a_SOURCES = \
546546
rpc/mempool.cpp \
547547
rpc/governance.cpp \
548548
rpc/mining.cpp \
549-
rpc/misc.cpp \
549+
rpc/node.cpp \
550550
rpc/net.cpp \
551+
rpc/output_script.cpp \
551552
rpc/quorums.cpp \
552553
rpc/rawtransaction.cpp \
553554
rpc/server.cpp \

src/rpc/misc.cpp renamed to src/rpc/node.cpp

Lines changed: 1 addition & 248 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,9 @@
2525
#include <rpc/server_util.h>
2626
#include <rpc/util.h>
2727
#include <scheduler.h>
28-
#include <script/descriptor.h>
2928
#include <txmempool.h>
3029
#include <univalue.h>
3130
#include <util/check.h>
32-
#include <util/strencodings.h>
3331
#include <util/system.h>
3432
#include <validation.h>
3533

@@ -238,247 +236,6 @@ static RPCHelpMan sporkupdate()
238236
};
239237
}
240238

241-
static RPCHelpMan validateaddress()
242-
{
243-
return RPCHelpMan{
244-
"validateaddress",
245-
"\nReturn information about the given Dash address.\n",
246-
{
247-
{"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The Dash address to validate"},
248-
},
249-
RPCResult{
250-
RPCResult::Type::OBJ, "", "",
251-
{
252-
{RPCResult::Type::BOOL, "isvalid", "If the address is valid or not"},
253-
{RPCResult::Type::STR, "address", /* optional */ true, "The Dash address validated"},
254-
{RPCResult::Type::STR_HEX, "scriptPubKey", /* optional */ true, "The hex-encoded scriptPubKey generated by the address"},
255-
{RPCResult::Type::BOOL, "isscript", /* optional */ true, "If the key is a script"},
256-
{RPCResult::Type::STR, "error", /* optional */ true, "Error message, if any"},
257-
}
258-
},
259-
RPCExamples{
260-
HelpExampleCli("validateaddress", "\"" + EXAMPLE_ADDRESS[0] + "\"") +
261-
HelpExampleRpc("validateaddress", "\"" + EXAMPLE_ADDRESS[0] + "\"")
262-
},
263-
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
264-
{
265-
std::string error_msg;
266-
CTxDestination dest = DecodeDestination(request.params[0].get_str(), error_msg);
267-
const bool isValid = IsValidDestination(dest);
268-
CHECK_NONFATAL(isValid == error_msg.empty());
269-
270-
UniValue ret(UniValue::VOBJ);
271-
ret.pushKV("isvalid", isValid);
272-
if (isValid) {
273-
std::string currentAddress = EncodeDestination(dest);
274-
ret.pushKV("address", currentAddress);
275-
276-
CScript scriptPubKey = GetScriptForDestination(dest);
277-
ret.pushKV("scriptPubKey", HexStr(scriptPubKey));;
278-
279-
UniValue detail = DescribeAddress(dest);
280-
ret.pushKVs(detail);
281-
} else {
282-
ret.pushKV("error", error_msg);
283-
}
284-
285-
return ret;
286-
},
287-
};
288-
}
289-
290-
static RPCHelpMan createmultisig()
291-
{
292-
return RPCHelpMan{"createmultisig",
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",
295-
{
296-
{"nrequired", RPCArg::Type::NUM, RPCArg::Optional::NO, "The number of required signatures out of the n keys."},
297-
{"keys", RPCArg::Type::ARR, RPCArg::Optional::NO, "The hex-encoded public keys.",
298-
{
299-
{"key", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "The hex-encoded public key"},
300-
}},
301-
},
302-
RPCResult{
303-
RPCResult::Type::OBJ, "", "",
304-
{
305-
{RPCResult::Type::STR, "address", "The value of the new multisig address."},
306-
{RPCResult::Type::STR_HEX, "redeemScript", "The string value of the hex-encoded redemption script."},
307-
{RPCResult::Type::STR, "descriptor", "The descriptor for this multisig."},
308-
}
309-
},
310-
RPCExamples{
311-
"\nCreate a multisig address from 2 public keys\n"
312-
+ HelpExampleCli("createmultisig", "2 \"[\\\"03789ed0bb717d88f7d321a368d905e7430207ebbd82bd342cf11ae157a7ace5fd\\\",\\\"03dbc6764b8884a92e871274b87583e6d5c2a58819473e17e107ef3f6aa5a61626\\\"]\"") +
313-
"\nAs a JSON-RPC call\n"
314-
+ HelpExampleRpc("createmultisig", "2, [\"03789ed0bb717d88f7d321a368d905e7430207ebbd82bd342cf11ae157a7ace5fd\",\"03dbc6764b8884a92e871274b87583e6d5c2a58819473e17e107ef3f6aa5a61626\"]")
315-
},
316-
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
317-
{
318-
int required = request.params[0].get_int();
319-
320-
// Get the public keys
321-
const UniValue& keys = request.params[1].get_array();
322-
std::vector<CPubKey> pubkeys;
323-
for (unsigned int i = 0; i < keys.size(); ++i) {
324-
if (IsHex(keys[i].get_str()) && (keys[i].get_str().length() == 66 || keys[i].get_str().length() == 130)) {
325-
pubkeys.push_back(HexToPubKey(keys[i].get_str()));
326-
} else {
327-
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Invalid public key: %s\n.", keys[i].get_str()));
328-
}
329-
}
330-
331-
// Construct using pay-to-script-hash:
332-
FillableSigningProvider keystore;
333-
CScript inner;
334-
const CTxDestination dest = AddAndGetMultisigDestination(required, pubkeys, keystore, inner);
335-
336-
// Make the descriptor
337-
std::unique_ptr<Descriptor> descriptor = InferDescriptor(GetScriptForDestination(dest), keystore);
338-
339-
UniValue result(UniValue::VOBJ);
340-
result.pushKV("address", EncodeDestination(dest));
341-
result.pushKV("redeemScript", HexStr(inner));
342-
result.pushKV("descriptor", descriptor->ToString());
343-
344-
return result;
345-
},
346-
};
347-
}
348-
349-
static RPCHelpMan getdescriptorinfo()
350-
{
351-
const std::string EXAMPLE_DESCRIPTOR = "wpkh([d34db33f/84h/0h/0h]0279be667ef9dcbbac55a06295Ce870b07029Bfcdb2dce28d959f2815b16f81798)";
352-
353-
return RPCHelpMan{"getdescriptorinfo",
354-
{"\nAnalyses a descriptor.\n"},
355-
{
356-
{"descriptor", RPCArg::Type::STR, RPCArg::Optional::NO, "The descriptor"},
357-
},
358-
RPCResult{
359-
RPCResult::Type::OBJ, "", "",
360-
{
361-
{RPCResult::Type::STR, "descriptor", "The descriptor in canonical form, without private keys"},
362-
{RPCResult::Type::STR, "checksum", "The checksum for the input descriptor"},
363-
{RPCResult::Type::BOOL, "isrange", "Whether the descriptor is ranged"},
364-
{RPCResult::Type::BOOL, "issolvable", "Whether the descriptor is solvable"},
365-
{RPCResult::Type::BOOL, "hasprivatekeys", "Whether the input descriptor contained at least one private key"},
366-
}
367-
},
368-
RPCExamples{
369-
"\nAnalyse a descriptor\n"
370-
+ HelpExampleCli("getdescriptorinfo", "\"" + EXAMPLE_DESCRIPTOR + "\"") +
371-
HelpExampleRpc("getdescriptorinfo", "\"" + EXAMPLE_DESCRIPTOR + "\"")
372-
373-
},
374-
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
375-
{
376-
377-
RPCTypeCheck(request.params, {UniValue::VSTR});
378-
379-
FlatSigningProvider provider;
380-
std::string error;
381-
auto desc = Parse(request.params[0].get_str(), provider, error);
382-
if (!desc) {
383-
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, error);
384-
}
385-
386-
UniValue result(UniValue::VOBJ);
387-
result.pushKV("descriptor", desc->ToString());
388-
result.pushKV("checksum", GetDescriptorChecksum(request.params[0].get_str()));
389-
result.pushKV("isrange", desc->IsRange());
390-
result.pushKV("issolvable", desc->IsSolvable());
391-
result.pushKV("hasprivatekeys", provider.keys.size() > 0);
392-
return result;
393-
},
394-
};
395-
}
396-
397-
static RPCHelpMan deriveaddresses()
398-
{
399-
const std::string EXAMPLE_DESCRIPTOR = "wpkh([d34db33f/84h/0h/0h]xpub6DJ2dNUysrn5Vt36jH2KLBT2i1auw1tTSSomg8PhqNiUtx8QX2SvC9nrHu81fT41fvDUnhMjEzQgXnQjKEu3oaqMSzhSrHMxyyoEAmUHQbY/0/*)#cjjspncu";
400-
401-
return RPCHelpMan{"deriveaddresses",
402-
"\nDerives one or more addresses corresponding to an output descriptor.\n"
403-
"Examples of output descriptors are:\n"
404-
" pkh(<pubkey>) P2PKH outputs for the given pubkey\n"
405-
" sh(multi(<n>,<pubkey>,<pubkey>,...)) P2SH-multisig outputs for the given threshold and pubkeys\n"
406-
" raw(<hex script>) Outputs whose scriptPubKey equals the specified hex scripts\n"
407-
"\nIn the above, <pubkey> either refers to a fixed public key in hexadecimal notation, or to an xpub/xprv optionally followed by one\n"
408-
"or more path elements separated by \"/\", where \"h\" represents a hardened child key.\n"
409-
"For more information on output descriptors, see the documentation in the doc/descriptors.md file.\n",
410-
{
411-
{"descriptor", RPCArg::Type::STR, RPCArg::Optional::NO, "The descriptor"},
412-
{"range", RPCArg::Type::RANGE, RPCArg::Optional::OMITTED_NAMED_ARG, "If a ranged descriptor is used, this specifies the end or the range (in [begin,end] notation) to derive."},
413-
},
414-
RPCResult{
415-
RPCResult::Type::ARR, "", "",
416-
{
417-
{RPCResult::Type::STR, "address", "the derived addresses"},
418-
}
419-
},
420-
RPCExamples{
421-
"\nFirst three receive addresses\n"
422-
+ HelpExampleCli("deriveaddresses", "\"" + EXAMPLE_DESCRIPTOR + "\" \"[0,2]\"") +
423-
HelpExampleRpc("deriveaddresses", "\"" + EXAMPLE_DESCRIPTOR + "\", \"[0,2]\"")
424-
},
425-
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
426-
{
427-
428-
RPCTypeCheck(request.params, {UniValue::VSTR, UniValueType()}); // Range argument is checked later
429-
const std::string desc_str = request.params[0].get_str();
430-
431-
int64_t range_begin = 0;
432-
int64_t range_end = 0;
433-
434-
if (request.params.size() >= 2 && !request.params[1].isNull()) {
435-
std::tie(range_begin, range_end) = ParseDescriptorRange(request.params[1]);
436-
}
437-
438-
FlatSigningProvider key_provider;
439-
std::string error;
440-
auto desc = Parse(desc_str, key_provider, error, /* require_checksum = */ true);
441-
if (!desc) {
442-
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, error);
443-
}
444-
445-
if (!desc->IsRange() && request.params.size() > 1) {
446-
throw JSONRPCError(RPC_INVALID_PARAMETER, "Range should not be specified for an un-ranged descriptor");
447-
}
448-
449-
if (desc->IsRange() && request.params.size() == 1) {
450-
throw JSONRPCError(RPC_INVALID_PARAMETER, "Range must be specified for a ranged descriptor");
451-
}
452-
453-
UniValue addresses(UniValue::VARR);
454-
455-
for (int64_t i = range_begin; i <= range_end; ++i) {
456-
FlatSigningProvider provider;
457-
std::vector<CScript> scripts;
458-
if (!desc->Expand(i, key_provider, scripts, provider)) {
459-
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Cannot derive script without private keys");
460-
}
461-
462-
for (const CScript &script : scripts) {
463-
CTxDestination dest;
464-
if (!ExtractDestination(script, dest)) {
465-
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Descriptor does not have a corresponding address");
466-
}
467-
468-
addresses.push_back(EncodeDestination(dest));
469-
}
470-
}
471-
472-
// This should not be possible, but an assert seems overkill:
473-
if (addresses.empty()) {
474-
throw JSONRPCError(RPC_MISC_ERROR, "Unexpected empty result");
475-
}
476-
477-
return addresses;
478-
},
479-
};
480-
}
481-
482239
static RPCHelpMan setmocktime()
483240
{
484241
return RPCHelpMan{"setmocktime",
@@ -1393,18 +1150,14 @@ static RPCHelpMan echoipc()
13931150
};
13941151
}
13951152

1396-
void RegisterMiscRPCCommands(CRPCTable &t)
1153+
void RegisterNodeRPCCommands(CRPCTable &t)
13971154
{
13981155
static const CRPCCommand commands[] =
13991156
{ // category actor (function)
14001157
// --------------------- ------------------------
14011158
{ "control", &debug, },
14021159
{ "control", &getmemoryinfo, },
14031160
{ "control", &logging, },
1404-
{ "util", &validateaddress, },
1405-
{ "util", &createmultisig, },
1406-
{ "util", &deriveaddresses, },
1407-
{ "util", &getdescriptorinfo, },
14081161
{ "util", &getindexinfo, },
14091162
{ "blockchain", &getspentinfo, },
14101163

0 commit comments

Comments
 (0)