Skip to content

Commit fb90ec3

Browse files
committed
Abstract out EvalDescriptorStringOrObject from scantxoutset
1 parent eaf4f88 commit fb90ec3

File tree

3 files changed

+48
-34
lines changed

3 files changed

+48
-34
lines changed

src/rpc/blockchain.cpp

Lines changed: 5 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2241,41 +2241,12 @@ UniValue scantxoutset(const JSONRPCRequest& request)
22412241

22422242
// loop through the scan objects
22432243
for (const UniValue& scanobject : request.params[1].get_array().getValues()) {
2244-
std::string desc_str;
2245-
std::pair<int64_t, int64_t> range = {0, 1000};
2246-
if (scanobject.isStr()) {
2247-
desc_str = scanobject.get_str();
2248-
} else if (scanobject.isObject()) {
2249-
UniValue desc_uni = find_value(scanobject, "desc");
2250-
if (desc_uni.isNull()) throw JSONRPCError(RPC_INVALID_PARAMETER, "Descriptor needs to be provided in scan object");
2251-
desc_str = desc_uni.get_str();
2252-
UniValue range_uni = find_value(scanobject, "range");
2253-
if (!range_uni.isNull()) {
2254-
range = ParseDescriptorRange(range_uni);
2255-
}
2256-
} else {
2257-
throw JSONRPCError(RPC_INVALID_PARAMETER, "Scan object needs to be either a string or an object");
2258-
}
2259-
22602244
FlatSigningProvider provider;
2261-
auto desc = Parse(desc_str, provider);
2262-
if (!desc) {
2263-
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Invalid descriptor '%s'", desc_str));
2264-
}
2265-
if (!desc->IsRange()) {
2266-
range.first = 0;
2267-
range.second = 0;
2268-
}
2269-
for (int i = range.first; i <= range.second; ++i) {
2270-
std::vector<CScript> scripts;
2271-
if (!desc->Expand(i, provider, scripts, provider)) {
2272-
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Cannot derive script without private keys: '%s'", desc_str));
2273-
}
2274-
for (const auto& script : scripts) {
2275-
std::string inferred = InferDescriptor(script, provider)->ToString();
2276-
needles.emplace(script);
2277-
descriptors.emplace(std::move(script), std::move(inferred));
2278-
}
2245+
auto scripts = EvalDescriptorStringOrObject(scanobject, provider);
2246+
for (const auto& script : scripts) {
2247+
std::string inferred = InferDescriptor(script, provider)->ToString();
2248+
needles.emplace(script);
2249+
descriptors.emplace(std::move(script), std::move(inferred));
22792250
}
22802251
}
22812252

src/rpc/util.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <key_io.h>
66
#include <keystore.h>
77
#include <rpc/util.h>
8+
#include <script/descriptor.h>
89
#include <tinyformat.h>
910
#include <util/strencodings.h>
1011

@@ -685,3 +686,40 @@ std::pair<int64_t, int64_t> ParseDescriptorRange(const UniValue& value)
685686
}
686687
return {low, high};
687688
}
689+
690+
std::vector<CScript> EvalDescriptorStringOrObject(const UniValue& scanobject, FlatSigningProvider& provider)
691+
{
692+
std::string desc_str;
693+
std::pair<int64_t, int64_t> range = {0, 1000};
694+
if (scanobject.isStr()) {
695+
desc_str = scanobject.get_str();
696+
} else if (scanobject.isObject()) {
697+
UniValue desc_uni = find_value(scanobject, "desc");
698+
if (desc_uni.isNull()) throw JSONRPCError(RPC_INVALID_PARAMETER, "Descriptor needs to be provided in scan object");
699+
desc_str = desc_uni.get_str();
700+
UniValue range_uni = find_value(scanobject, "range");
701+
if (!range_uni.isNull()) {
702+
range = ParseDescriptorRange(range_uni);
703+
}
704+
} else {
705+
throw JSONRPCError(RPC_INVALID_PARAMETER, "Scan object needs to be either a string or an object");
706+
}
707+
708+
auto desc = Parse(desc_str, provider);
709+
if (!desc) {
710+
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Invalid descriptor '%s'", desc_str));
711+
}
712+
if (!desc->IsRange()) {
713+
range.first = 0;
714+
range.second = 0;
715+
}
716+
std::vector<CScript> ret;
717+
for (int i = range.first; i <= range.second; ++i) {
718+
std::vector<CScript> scripts;
719+
if (!desc->Expand(i, provider, scripts, provider)) {
720+
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Cannot derive script without private keys: '%s'", desc_str));
721+
}
722+
std::move(scripts.begin(), scripts.end(), std::back_inserter(ret));
723+
}
724+
return ret;
725+
}

src/rpc/util.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
#include <node/transaction.h>
99
#include <pubkey.h>
1010
#include <rpc/protocol.h>
11+
#include <script/script.h>
12+
#include <script/sign.h>
1113
#include <script/standard.h>
1214
#include <univalue.h>
1315

@@ -83,6 +85,9 @@ UniValue JSONRPCTransactionError(TransactionError terr, const std::string& err_s
8385
//! Parse a JSON range specified as int64, or [int64, int64]
8486
std::pair<int64_t, int64_t> ParseDescriptorRange(const UniValue& value);
8587

88+
/** Evaluate a descriptor given as a string, or as a {"desc":...,"range":...} object, with default range of 1000. */
89+
std::vector<CScript> EvalDescriptorStringOrObject(const UniValue& scanobject, FlatSigningProvider& provider);
90+
8691
struct RPCArg {
8792
enum class Type {
8893
OBJ,

0 commit comments

Comments
 (0)