Changeset View
Changeset View
Standalone View
Standalone View
src/rpc/util.cpp
// Copyright (c) 2017-2019 The Bitcoin Core developers | // Copyright (c) 2017-2019 The Bitcoin Core developers | ||||
// Distributed under the MIT software license, see the accompanying | // Distributed under the MIT software license, see the accompanying | ||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | // file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
#include <rpc/util.h> | #include <rpc/util.h> | ||||
#include <key_io.h> | #include <key_io.h> | ||||
#include <pubkey.h> | #include <pubkey.h> | ||||
#include <script/descriptor.h> | |||||
#include <script/signingprovider.h> | #include <script/signingprovider.h> | ||||
#include <tinyformat.h> | #include <tinyformat.h> | ||||
#include <util/strencodings.h> | #include <util/strencodings.h> | ||||
#include <util/string.h> | #include <util/string.h> | ||||
#include <tuple> | #include <tuple> | ||||
#include <boost/variant/static_visitor.hpp> | #include <boost/variant/static_visitor.hpp> | ||||
▲ Show 20 Lines • Show All 704 Lines • ▼ Show 20 Lines | std::pair<int64_t, int64_t> ParseDescriptorRange(const UniValue &value) { | ||||
if ((high >> 31) != 0) { | if ((high >> 31) != 0) { | ||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "End of range is too high"); | throw JSONRPCError(RPC_INVALID_PARAMETER, "End of range is too high"); | ||||
} | } | ||||
if (high >= low + 1000000) { | if (high >= low + 1000000) { | ||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Range is too large"); | throw JSONRPCError(RPC_INVALID_PARAMETER, "Range is too large"); | ||||
} | } | ||||
return {low, high}; | return {low, high}; | ||||
} | } | ||||
std::vector<CScript> | |||||
EvalDescriptorStringOrObject(const UniValue &scanobject, | |||||
FlatSigningProvider &provider) { | |||||
std::string desc_str; | |||||
std::pair<int64_t, int64_t> range = {0, 1000}; | |||||
if (scanobject.isStr()) { | |||||
desc_str = scanobject.get_str(); | |||||
} else if (scanobject.isObject()) { | |||||
UniValue desc_uni = find_value(scanobject, "desc"); | |||||
if (desc_uni.isNull()) { | |||||
throw JSONRPCError( | |||||
RPC_INVALID_PARAMETER, | |||||
"Descriptor needs to be provided in scan object"); | |||||
} | |||||
desc_str = desc_uni.get_str(); | |||||
UniValue range_uni = find_value(scanobject, "range"); | |||||
if (!range_uni.isNull()) { | |||||
range = ParseDescriptorRange(range_uni); | |||||
} | |||||
} else { | |||||
throw JSONRPCError( | |||||
RPC_INVALID_PARAMETER, | |||||
"Scan object needs to be either a string or an object"); | |||||
} | |||||
auto desc = Parse(desc_str, provider); | |||||
if (!desc) { | |||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, | |||||
strprintf("Invalid descriptor '%s'", desc_str)); | |||||
} | |||||
if (!desc->IsRange()) { | |||||
range.first = 0; | |||||
range.second = 0; | |||||
} | |||||
std::vector<CScript> ret; | |||||
for (int i = range.first; i <= range.second; ++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: '%s'", | |||||
desc_str)); | |||||
} | |||||
std::move(scripts.begin(), scripts.end(), std::back_inserter(ret)); | |||||
} | |||||
return ret; | |||||
} |