84uint64_t PolyMod(uint64_t c, 
int val)
 
   87    c = ((c & 0x7ffffffff) << 5) ^ val;
 
   88    if (c0 & 1) c ^= 0xf5dee51989;
 
   89    if (c0 & 2) c ^= 0xa9fdca3312;
 
   90    if (c0 & 4) c ^= 0x1bab10e32d;
 
   91    if (c0 & 8) c ^= 0x3706b1677a;
 
   92    if (c0 & 16) c ^= 0x644d626ffd;
 
  111    static std::string INPUT_CHARSET =
 
  112        "0123456789()[],'/*abcdefgh@:$%{}" 
  113        "IJKLMNOPQRSTUVWXYZ&+-.;<=>?!^_|~" 
  114        "ijklmnopqrstuvwxyzABCDEFGH`#\"\\ ";
 
  117    static std::string CHECKSUM_CHARSET = 
"qpzry9x8gf2tvdw0s3jn54khce6mua7l";
 
  122    for (
auto ch : span) {
 
  123        auto pos = INPUT_CHARSET.find(ch);
 
  124        if (pos == std::string::npos) 
return "";
 
  125        c = PolyMod(c, pos & 31); 
 
  126        cls = cls * 3 + (pos >> 5); 
 
  127        if (++clscount == 3) {
 
  134    if (clscount > 0) c = PolyMod(c, cls);
 
  135    for (
int j = 0; j < 8; ++j) c = PolyMod(c, 0); 
 
  138    std::string ret(8, 
' ');
 
  139    for (
int j = 0; j < 8; ++j) ret[j] = CHECKSUM_CHARSET[(c >> (5 * (7 - j))) & 31];
 
  143std::string AddChecksum(
const std::string& str) { 
return str + 
"#" + DescriptorChecksum(str); }
 
  149typedef std::vector<uint32_t> KeyPath;
 
  157    uint32_t m_expr_index;
 
  160    explicit PubkeyProvider(uint32_t exp_index) : m_expr_index(exp_index) {}
 
  162    virtual ~PubkeyProvider() = 
default;
 
  172    virtual bool IsRange() 
const = 0;
 
  175    virtual size_t GetSize() 
const = 0;
 
  178    virtual std::string 
ToString() 
const = 0;
 
  181    virtual bool ToPrivateString(
const SigningProvider& arg, std::string& out) 
const = 0;
 
  190class OriginPubkeyProvider final : 
public PubkeyProvider
 
  193    std::unique_ptr<PubkeyProvider> m_provider;
 
  195    std::string OriginString()
 const 
  201    OriginPubkeyProvider(uint32_t exp_index, 
KeyOriginInfo info, std::unique_ptr<PubkeyProvider> provider) : PubkeyProvider(exp_index), m_origin(std::move(info)), m_provider(std::move(provider)) {}
 
  204        if (!m_provider->GetPubKey(pos, arg, key, info, read_cache, write_cache)) 
return false;
 
  205        std::copy(std::begin(m_origin.fingerprint), std::end(m_origin.fingerprint), info.
fingerprint);
 
  206        info.
path.insert(info.
path.begin(), m_origin.path.begin(), m_origin.path.end());
 
  209    bool IsRange()
 const override { 
return m_provider->IsRange(); }
 
  210    size_t GetSize()
 const override { 
return m_provider->GetSize(); }
 
  211    std::string 
ToString()
 const override { 
return "[" + OriginString() + 
"]" + m_provider->ToString(); }
 
  212    bool ToPrivateString(
const SigningProvider& arg, std::string& ret)
 const override 
  215        if (!m_provider->ToPrivateString(arg, sub)) 
return false;
 
  216        ret = 
"[" + OriginString() + 
"]" + std::move(sub);
 
  222        if (!m_provider->ToNormalizedString(arg, sub, cache)) 
return false;
 
  228            ret = 
"[" + OriginString() + std::move(sub);
 
  230            ret = 
"[" + OriginString() + 
"]" + std::move(sub);
 
  236        return m_provider->GetPrivKey(pos, arg, key);
 
  241class ConstPubkeyProvider final : 
public PubkeyProvider
 
  247    ConstPubkeyProvider(uint32_t exp_index, 
const CPubKey& pubkey, 
bool xonly) : PubkeyProvider(exp_index), m_pubkey(pubkey), m_xonly(xonly) {}
 
  252        CKeyID keyid = m_pubkey.GetID();
 
  256    bool IsRange()
 const override { 
return false; }
 
  257    size_t GetSize()
 const override { 
return m_pubkey.size(); }
 
  258    std::string 
ToString()
 const override { 
return m_xonly ? 
HexStr(m_pubkey).substr(2) : 
HexStr(m_pubkey); }
 
  259    bool ToPrivateString(
const SigningProvider& arg, std::string& ret)
 const override 
  262        if (!arg.
GetKey(m_pubkey.GetID(), key)) 
return false;
 
  273        return arg.
GetKey(m_pubkey.GetID(), key);
 
  277enum class DeriveType {
 
  284class BIP32PubkeyProvider final : 
public PubkeyProvider
 
  294        if (!arg.
GetKey(m_root_extkey.pubkey.GetID(), key)) 
return false;
 
  295        ret.
nDepth = m_root_extkey.nDepth;
 
  297        ret.
nChild = m_root_extkey.nChild;
 
  306        if (!GetExtKey(arg, xprv)) 
return false;
 
  307        for (
auto entry : m_path) {
 
  310                last_hardened = xprv;
 
  316    bool IsHardened()
 const 
  318        if (m_derive == DeriveType::HARDENED) 
return true;
 
  319        for (
auto entry : m_path) {
 
  320            if (entry >> 31) 
return true;
 
  326    BIP32PubkeyProvider(uint32_t exp_index, 
const CExtPubKey& extkey, KeyPath path, DeriveType derive) : PubkeyProvider(exp_index), m_root_extkey(extkey), m_path(std::move(path)), m_derive(derive) {}
 
  327    bool IsRange()
 const override { 
return m_derive != DeriveType::NO; }
 
  328    size_t GetSize()
 const override { 
return 33; }
 
  333        CKeyID keyid = m_root_extkey.pubkey.GetID();
 
  335        parent_info.
path = m_path;
 
  339        if (m_derive == DeriveType::UNHARDENED) final_info_out_tmp.
path.push_back((uint32_t)pos);
 
  340        if (m_derive == DeriveType::HARDENED) final_info_out_tmp.
path.push_back(((uint32_t)pos) | 0x80000000L);
 
  348            if (!read_cache->GetCachedDerivedExtPubKey(m_expr_index, pos, final_extkey)) {
 
  349                if (m_derive == DeriveType::HARDENED) 
return false;
 
  351                if (!read_cache->GetCachedParentExtPubKey(m_expr_index, parent_extkey)) 
return false;
 
  352                final_extkey = parent_extkey;
 
  353                if (m_derive == DeriveType::UNHARDENED) der = parent_extkey.
Derive(final_extkey, pos);
 
  355        } 
else if (IsHardened()) {
 
  358            if (!GetDerivedExtKey(arg, xprv, lh_xprv)) 
return false;
 
  359            parent_extkey = xprv.
Neuter();
 
  360            if (m_derive == DeriveType::UNHARDENED) der = xprv.
Derive(xprv, pos);
 
  361            if (m_derive == DeriveType::HARDENED) der = xprv.
Derive(xprv, pos | 0x80000000UL);
 
  362            final_extkey = xprv.
Neuter();
 
  364                last_hardened_extkey = lh_xprv.
Neuter();
 
  367            for (
auto entry : m_path) {
 
  368                der = parent_extkey.
Derive(parent_extkey, entry);
 
  371            final_extkey = parent_extkey;
 
  372            if (m_derive == DeriveType::UNHARDENED) der = parent_extkey.
Derive(final_extkey, pos);
 
  373            assert(m_derive != DeriveType::HARDENED);
 
  377        final_info_out = final_info_out_tmp;
 
  378        key_out = final_extkey.
pubkey;
 
  382            if (m_derive != DeriveType::HARDENED) {
 
  383                write_cache->CacheParentExtPubKey(m_expr_index, parent_extkey);
 
  386                    write_cache->CacheLastHardenedExtPubKey(m_expr_index, last_hardened_extkey);
 
  388            } 
else if (final_info_out.
path.size() > 0) {
 
  389                write_cache->CacheDerivedExtPubKey(m_expr_index, pos, final_extkey);
 
  395    std::string 
ToString()
 const override 
  400            if (m_derive == DeriveType::HARDENED) ret += 
'\'';
 
  404    bool ToPrivateString(
const SigningProvider& arg, std::string& out)
 const override 
  407        if (!GetExtKey(arg, key)) 
return false;
 
  411            if (m_derive == DeriveType::HARDENED) out += 
'\'';
 
  418        if (m_derive == DeriveType::HARDENED) {
 
  423        int i = (int)m_path.size() - 1;
 
  424        for (; i >= 0; --i) {
 
  425            if (m_path.at(i) >> 31) {
 
  437        for (; k <= i; ++k) {
 
  439            origin.
path.push_back(m_path.at(k));
 
  443        for (; k < (int)m_path.size(); ++k) {
 
  444            end_path.push_back(m_path.at(k));
 
  447        CKeyID id = m_root_extkey.pubkey.GetID();
 
  448        std::copy(
id.begin(), 
id.begin() + 4, origin.
fingerprint);
 
  453        if (cache != 
nullptr) {
 
  459            if (!GetDerivedExtKey(arg, xprv, lh_xprv)) 
return false;
 
  469            assert(m_derive == DeriveType::UNHARDENED);
 
  477        if (!GetDerivedExtKey(arg, extkey, dummy)) 
return false;
 
  478        if (m_derive == DeriveType::UNHARDENED) extkey.
Derive(extkey, pos);
 
  479        if (m_derive == DeriveType::HARDENED) extkey.
Derive(extkey, pos | 0x80000000UL);
 
  489    const std::vector<std::unique_ptr<PubkeyProvider>> m_pubkey_args;
 
  491    const std::string m_name;
 
  498    const std::vector<std::unique_ptr<DescriptorImpl>> m_subdescriptor_args;
 
  501    virtual std::string ToStringExtra()
 const { 
return ""; }
 
  516    DescriptorImpl(std::vector<std::unique_ptr<PubkeyProvider>> pubkeys, 
const std::string& 
name) : m_pubkey_args(std::move(pubkeys)), m_name(
name), m_subdescriptor_args() {}
 
  517    DescriptorImpl(std::vector<std::unique_ptr<PubkeyProvider>> pubkeys, std::unique_ptr<DescriptorImpl> script, 
const std::string& 
name) : m_pubkey_args(std::move(pubkeys)), m_name(
name), m_subdescriptor_args(
Vector(std::move(script))) {}
 
  518    DescriptorImpl(std::vector<std::unique_ptr<PubkeyProvider>> pubkeys, std::vector<std::unique_ptr<DescriptorImpl>> scripts, 
const std::string& 
name) : m_pubkey_args(std::move(pubkeys)), m_name(
name), m_subdescriptor_args(std::move(scripts)) {}
 
  520    enum class StringType
 
  529        for (
const auto& arg : m_subdescriptor_args) {
 
  530            if (!arg->IsSolvable()) 
return false;
 
  537        for (
const auto& pubkey : m_pubkey_args) {
 
  538            if (pubkey->IsRange()) 
return true;
 
  540        for (
const auto& arg : m_subdescriptor_args) {
 
  541            if (arg->IsRange()) 
return true;
 
  546    virtual bool ToStringSubScriptHelper(
const SigningProvider* arg, std::string& ret, 
const StringType type, 
const DescriptorCache* cache = 
nullptr)
 const 
  549        for (
const auto& scriptarg : m_subdescriptor_args) {
 
  550            if (pos++) ret += 
",";
 
  552            if (!scriptarg->ToStringHelper(arg, tmp, type, cache)) 
return false;
 
  553            ret += std::move(tmp);
 
  560        std::string extra = ToStringExtra();
 
  561        size_t pos = extra.size() > 0 ? 1 : 0;
 
  562        std::string ret = m_name + 
"(" + extra;
 
  563        for (
const auto& pubkey : m_pubkey_args) {
 
  564            if (pos++) ret += 
",";
 
  567                case StringType::NORMALIZED:
 
  568                    if (!pubkey->ToNormalizedString(*arg, tmp, cache)) 
return false;
 
  570                case StringType::PRIVATE:
 
  571                    if (!pubkey->ToPrivateString(*arg, tmp)) 
return false;
 
  573                case StringType::PUBLIC:
 
  574                    tmp = pubkey->ToString();
 
  577            ret += std::move(tmp);
 
  579        std::string subscript;
 
  580        if (!ToStringSubScriptHelper(arg, subscript, type, cache)) 
return false;
 
  581        if (pos && subscript.size()) ret += 
',';
 
  582        out = std::move(ret) + std::move(subscript) + 
")";
 
  589        ToStringHelper(
nullptr, ret, StringType::PUBLIC);
 
  590        return AddChecksum(ret);
 
  595        bool ret = ToStringHelper(&arg, out, StringType::PRIVATE);
 
  596        out = AddChecksum(out);
 
  602        bool ret = ToStringHelper(&arg, out, StringType::NORMALIZED, cache);
 
  603        out = AddChecksum(out);
 
  609        std::vector<std::pair<CPubKey, KeyOriginInfo>> entries;
 
  610        entries.reserve(m_pubkey_args.size());
 
  613        for (
const auto& p : m_pubkey_args) {
 
  614            entries.emplace_back();
 
  615            if (!p->GetPubKey(pos, arg, entries.back().first, entries.back().second, read_cache, write_cache)) 
return false;
 
  617        std::vector<CScript> subscripts;
 
  619        for (
const auto& subarg : m_subdescriptor_args) {
 
  620            std::vector<CScript> outscripts;
 
  621            if (!subarg->ExpandHelper(pos, arg, read_cache, outscripts, subprovider, write_cache)) 
return false;
 
  622            assert(outscripts.size() == 1);
 
  623            subscripts.emplace_back(std::move(outscripts[0]));
 
  625        out = 
Merge(std::move(out), std::move(subprovider));
 
  627        std::vector<CPubKey> pubkeys;
 
  628        pubkeys.reserve(entries.size());
 
  629        for (
auto& entry : entries) {
 
  630            pubkeys.push_back(entry.first);
 
  631            out.
origins.emplace(entry.first.GetID(), std::make_pair<CPubKey, KeyOriginInfo>(
CPubKey(entry.first), std::move(entry.second)));
 
  634        output_scripts = MakeScripts(pubkeys, 
MakeSpan(subscripts), out);
 
  640        return ExpandHelper(pos, provider, 
nullptr, output_scripts, out, write_cache);
 
  650        for (
const auto& p : m_pubkey_args) {
 
  652            if (!p->GetPrivKey(pos, provider, key)) 
continue;
 
  655        for (
const auto& arg : m_subdescriptor_args) {
 
  656            arg->ExpandPrivate(pos, provider, out);
 
  660    std::optional<OutputType> 
GetOutputType()
 const override { 
return std::nullopt; }
 
  664class AddressDescriptor final : 
public DescriptorImpl
 
  668    std::string ToStringExtra()
 const override { 
return EncodeDestination(m_destination); }
 
  671    AddressDescriptor(
CTxDestination destination) : DescriptorImpl({}, 
"addr"), m_destination(std::move(destination)) {}
 
  672    bool IsSolvable() const final { 
return false; }
 
  674    std::optional<OutputType> GetOutputType()
 const override 
  678    bool IsSingleType() const final { 
return true; }
 
  682class RawDescriptor final : 
public DescriptorImpl
 
  686    std::string ToStringExtra()
 const override { 
return HexStr(m_script); }
 
  689    RawDescriptor(
CScript script) : DescriptorImpl({}, 
"raw"), m_script(std::move(script)) {}
 
  690    bool IsSolvable() const final { 
return false; }
 
  692    std::optional<OutputType> GetOutputType()
 const override 
  698    bool IsSingleType() const final { 
return true; }
 
  702class PKDescriptor final : 
public DescriptorImpl
 
  711            return Vector(std::move(script));
 
  717    PKDescriptor(std::unique_ptr<PubkeyProvider> prov, 
bool xonly = 
false) : DescriptorImpl(
Vector(std::move(prov)), 
"pk"), m_xonly(xonly) {}
 
  718    bool IsSingleType() const final { 
return true; }
 
  722class PKHDescriptor final : 
public DescriptorImpl
 
  727        CKeyID id = keys[0].GetID();
 
  728        out.
pubkeys.emplace(
id, keys[0]);
 
  732    PKHDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(
Vector(std::move(prov)), 
"pkh") {}
 
  733    std::optional<OutputType> GetOutputType()
 const override { 
return OutputType::LEGACY; }
 
  734    bool IsSingleType() const final { 
return true; }
 
  738class WPKHDescriptor final : 
public DescriptorImpl
 
  743        CKeyID id = keys[0].GetID();
 
  744        out.
pubkeys.emplace(
id, keys[0]);
 
  748    WPKHDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(
Vector(std::move(prov)), 
"wpkh") {}
 
  749    std::optional<OutputType> GetOutputType()
 const override { 
return OutputType::BECH32; }
 
  750    bool IsSingleType() const final { 
return true; }
 
  754class ComboDescriptor final : 
public DescriptorImpl
 
  759        std::vector<CScript> ret;
 
  760        CKeyID id = keys[0].GetID();
 
  761        out.
pubkeys.emplace(
id, keys[0]);
 
  764        if (keys[0].IsCompressed()) {
 
  767            ret.emplace_back(p2wpkh);
 
  773    ComboDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(
Vector(std::move(prov)), 
"combo") {}
 
  774    bool IsSingleType() const final { 
return false; }
 
  778class MultisigDescriptor final : 
public DescriptorImpl
 
  780    const int m_threshold;
 
  783    std::string ToStringExtra()
 const override { 
return strprintf(
"%i", m_threshold); }
 
  786            std::vector<CPubKey> sorted_keys(keys);
 
  787            std::sort(sorted_keys.begin(), sorted_keys.end());
 
  793    MultisigDescriptor(
int threshold, std::vector<std::unique_ptr<PubkeyProvider>> providers, 
bool sorted = 
false) : DescriptorImpl(std::move(providers), sorted ? 
"sortedmulti" : 
"multi"), m_threshold(threshold), m_sorted(sorted) {}
 
  794    bool IsSingleType() const final { 
return true; }
 
  798class SHDescriptor final : 
public DescriptorImpl
 
  808    SHDescriptor(std::unique_ptr<DescriptorImpl> desc) : DescriptorImpl({}, std::move(desc), 
"sh") {}
 
  810    std::optional<OutputType> GetOutputType()
 const override 
  812        assert(m_subdescriptor_args.size() == 1);
 
  816    bool IsSingleType() const final { 
return true; }
 
  820class WSHDescriptor final : 
public DescriptorImpl
 
  830    WSHDescriptor(std::unique_ptr<DescriptorImpl> desc) : DescriptorImpl({}, std::move(desc), 
"wsh") {}
 
  831    std::optional<OutputType> GetOutputType()
 const override { 
return OutputType::BECH32; }
 
  832    bool IsSingleType() const final { 
return true; }
 
  836class TRDescriptor final : 
public DescriptorImpl
 
  838    std::vector<int> m_depths;
 
  844        for (
size_t pos = 0; pos < m_depths.size(); ++pos) {
 
  850        if (!xpk.IsFullyValid()) 
return {};
 
  856    bool ToStringSubScriptHelper(
const SigningProvider* arg, std::string& ret, 
const StringType type, 
const DescriptorCache* cache = 
nullptr)
 const override 
  858        if (m_depths.empty()) 
return true;
 
  859        std::vector<bool> path;
 
  860        for (
size_t pos = 0; pos < m_depths.size(); ++pos) {
 
  862            while ((
int)path.size() <= m_depths[pos]) {
 
  863                if (path.size()) ret += 
'{';
 
  864                path.push_back(
false);
 
  867            if (!m_subdescriptor_args[pos]->ToStringHelper(arg, tmp, type, cache)) 
return false;
 
  868            ret += std::move(tmp);
 
  869            while (!path.empty() && path.back()) {
 
  870                if (path.size() > 1) ret += 
'}';
 
  873            if (!path.empty()) path.back() = 
true;
 
  878    TRDescriptor(std::unique_ptr<PubkeyProvider> internal_key, std::vector<std::unique_ptr<DescriptorImpl>> descs, std::vector<int> depths) :
 
  879        DescriptorImpl(
Vector(std::move(internal_key)), std::move(descs), 
"tr"), m_depths(std::move(depths))
 
  881        assert(m_subdescriptor_args.size() == m_depths.size());
 
  884    bool IsSingleType() const final { 
return true; }
 
  891enum class ParseScriptContext {
 
  900[[nodiscard]] 
bool ParseKeyPath(
const std::vector<
Span<const char>>& split, KeyPath& out, std::string& 
error)
 
  902    for (
size_t i = 1; i < split.size(); ++i) {
 
  904        bool hardened = 
false;
 
  905        if (elem.
size() > 0 && (elem[elem.
size() - 1] == 
'\'' || elem[elem.
size() - 1] == 
'h')) {
 
  913        } 
else if (p > 0x7FFFFFFFUL) {
 
  917        out.push_back(p | (((uint32_t)hardened) << 31));
 
  927    bool permit_uncompressed = 
ctx == ParseScriptContext::TOP || 
ctx == ParseScriptContext::P2SH;
 
  928    auto split = 
Split(sp, 
'/');
 
  929    std::string str(split[0].begin(), split[0].end());
 
  930    if (str.size() == 0) {
 
  931        error = 
"No key provided";
 
  934    if (split.size() == 1) {
 
  936            std::vector<unsigned char> data = 
ParseHex(str);
 
  938            if (pubkey.IsFullyValid()) {
 
  939                if (permit_uncompressed || pubkey.IsCompressed()) {
 
  940                    return std::make_unique<ConstPubkeyProvider>(key_exp_index, pubkey, 
false);
 
  942                    error = 
"Uncompressed keys are not allowed";
 
  945            } 
else if (data.size() == 32 && 
ctx == ParseScriptContext::P2TR) {
 
  946                unsigned char fullkey[33] = {0x02};
 
  947                std::copy(data.begin(), data.end(), fullkey + 1);
 
  948                pubkey.Set(std::begin(fullkey), std::end(fullkey));
 
  949                if (pubkey.IsFullyValid()) {
 
  950                    return std::make_unique<ConstPubkeyProvider>(key_exp_index, pubkey, 
true);
 
  961                return std::make_unique<ConstPubkeyProvider>(key_exp_index, pubkey, 
ctx == ParseScriptContext::P2TR);
 
  963                error = 
"Uncompressed keys are not allowed";
 
  975    DeriveType type = DeriveType::NO;
 
  976    if (split.back() == 
MakeSpan(
"*").first(1)) {
 
  978        type = DeriveType::UNHARDENED;
 
  979    } 
else if (split.back() == 
MakeSpan(
"*'").first(2) || split.back() == 
MakeSpan(
"*h").first(2)) {
 
  981        type = DeriveType::HARDENED;
 
  983    if (!ParseKeyPath(split, path, 
error)) 
return nullptr;
 
  985        extpubkey = extkey.
Neuter();
 
  988    return std::make_unique<BIP32PubkeyProvider>(key_exp_index, extpubkey, std::move(path), type);
 
  996    auto origin_split = 
Split(sp, 
']');
 
  997    if (origin_split.size() > 2) {
 
  998        error = 
"Multiple ']' characters found for a single pubkey";
 
 1001    if (origin_split.size() == 1) 
return ParsePubkeyInner(key_exp_index, origin_split[0], 
ctx, out, 
error);
 
 1002    if (origin_split[0].empty() || origin_split[0][0] != 
'[') {
 
 1003        error = 
strprintf(
"Key origin start '[ character expected but not found, got '%c' instead",
 
 1004                          origin_split[0].empty() ?  
']' : origin_split[0][0]);
 
 1007    auto slash_split = 
Split(origin_split[0].subspan(1), 
'/');
 
 1008    if (slash_split[0].size() != 8) {
 
 1009        error = 
strprintf(
"Fingerprint is not 4 bytes (%u characters instead of 8 characters)", slash_split[0].size());
 
 1012    std::string fpr_hex = std::string(slash_split[0].begin(), slash_split[0].end());
 
 1013    if (!
IsHex(fpr_hex)) {
 
 1017    auto fpr_bytes = 
ParseHex(fpr_hex);
 
 1019    static_assert(
sizeof(info.
fingerprint) == 4, 
"Fingerprint must be 4 bytes");
 
 1020    assert(fpr_bytes.size() == 4);
 
 1021    std::copy(fpr_bytes.begin(), fpr_bytes.end(), info.
fingerprint);
 
 1022    if (!ParseKeyPath(slash_split, info.
path, 
error)) 
return nullptr;
 
 1023    auto provider = ParsePubkeyInner(key_exp_index, origin_split[1], 
ctx, out, 
error);
 
 1024    if (!provider) 
return nullptr;
 
 1025    return std::make_unique<OriginPubkeyProvider>(key_exp_index, std::move(info), std::move(provider));
 
 1033    auto expr = 
Expr(sp);
 
 1034    bool sorted_multi = 
false;
 
 1035    if (
Func(
"pk", expr)) {
 
 1036        auto pubkey = ParsePubkey(key_exp_index, expr, 
ctx, out, 
error);
 
 1037        if (!pubkey) 
return nullptr;
 
 1039        return std::make_unique<PKDescriptor>(std::move(pubkey), 
ctx == ParseScriptContext::P2TR);
 
 1041    if ((
ctx == ParseScriptContext::TOP || 
ctx == ParseScriptContext::P2SH || 
ctx == ParseScriptContext::P2WSH) && 
Func(
"pkh", expr)) {
 
 1042        auto pubkey = ParsePubkey(key_exp_index, expr, 
ctx, out, 
error);
 
 1043        if (!pubkey) 
return nullptr;
 
 1045        return std::make_unique<PKHDescriptor>(std::move(pubkey));
 
 1046    } 
else if (
Func(
"pkh", expr)) {
 
 1047        error = 
"Can only have pkh at top level, in sh(), or in wsh()";
 
 1050    if (
ctx == ParseScriptContext::TOP && 
Func(
"combo", expr)) {
 
 1051        auto pubkey = ParsePubkey(key_exp_index, expr, 
ctx, out, 
error);
 
 1052        if (!pubkey) 
return nullptr;
 
 1054        return std::make_unique<ComboDescriptor>(std::move(pubkey));
 
 1055    } 
else if (
Func(
"combo", expr)) {
 
 1056        error = 
"Can only have combo() at top level";
 
 1059    if ((
ctx == ParseScriptContext::TOP || 
ctx == ParseScriptContext::P2SH || 
ctx == ParseScriptContext::P2WSH) && ((sorted_multi = 
Func(
"sortedmulti", expr)) || 
Func(
"multi", expr))) {
 
 1060        auto threshold = 
Expr(expr);
 
 1062        std::vector<std::unique_ptr<PubkeyProvider>> providers;
 
 1063        if (!
ParseUInt32(std::string(threshold.begin(), threshold.end()), &thres)) {
 
 1064            error = 
strprintf(
"Multi threshold '%s' is not valid", std::string(threshold.begin(), threshold.end()));
 
 1067        size_t script_size = 0;
 
 1068        while (expr.size()) {
 
 1069            if (!
Const(
",", expr)) {
 
 1073            auto arg = 
Expr(expr);
 
 1074            auto pk = ParsePubkey(key_exp_index, arg, 
ctx, out, 
error);
 
 1075            if (!pk) 
return nullptr;
 
 1076            script_size += pk->GetSize() + 1;
 
 1077            providers.emplace_back(std::move(pk));
 
 1083        } 
else if (thres < 1) {
 
 1084            error = 
strprintf(
"Multisig threshold cannot be %d, must be at least 1", thres);
 
 1086        } 
else if (thres > providers.size()) {
 
 1087            error = 
strprintf(
"Multisig threshold cannot be larger than the number of keys; threshold is %d but only %u keys specified", thres, providers.size());
 
 1090        if (
ctx == ParseScriptContext::TOP) {
 
 1091            if (providers.size() > 3) {
 
 1092                error = 
strprintf(
"Cannot have %u pubkeys in bare multisig; only at most 3 pubkeys", providers.size());
 
 1096        if (
ctx == ParseScriptContext::P2SH) {
 
 1103        return std::make_unique<MultisigDescriptor>(thres, std::move(providers), sorted_multi);
 
 1104    } 
else if (
Func(
"sortedmulti", expr) || 
Func(
"multi", expr)) {
 
 1105        error = 
"Can only have multi/sortedmulti at top level, in sh(), or in wsh()";
 
 1108    if ((
ctx == ParseScriptContext::TOP || 
ctx == ParseScriptContext::P2SH) && 
Func(
"wpkh", expr)) {
 
 1109        auto pubkey = ParsePubkey(key_exp_index, expr, ParseScriptContext::P2WPKH, out, 
error);
 
 1110        if (!pubkey) 
return nullptr;
 
 1112        return std::make_unique<WPKHDescriptor>(std::move(pubkey));
 
 1113    } 
else if (
Func(
"wpkh", expr)) {
 
 1114        error = 
"Can only have wpkh() at top level or inside sh()";
 
 1117    if (
ctx == ParseScriptContext::TOP && 
Func(
"sh", expr)) {
 
 1118        auto desc = 
ParseScript(key_exp_index, expr, ParseScriptContext::P2SH, out, 
error);
 
 1119        if (!desc || expr.size()) 
return nullptr;
 
 1120        return std::make_unique<SHDescriptor>(std::move(desc));
 
 1121    } 
else if (
Func(
"sh", expr)) {
 
 1122        error = 
"Can only have sh() at top level";
 
 1125    if ((
ctx == ParseScriptContext::TOP || 
ctx == ParseScriptContext::P2SH) && 
Func(
"wsh", expr)) {
 
 1126        auto desc = 
ParseScript(key_exp_index, expr, ParseScriptContext::P2WSH, out, 
error);
 
 1127        if (!desc || expr.size()) 
return nullptr;
 
 1128        return std::make_unique<WSHDescriptor>(std::move(desc));
 
 1129    } 
else if (
Func(
"wsh", expr)) {
 
 1130        error = 
"Can only have wsh() at top level or inside sh()";
 
 1133    if (
ctx == ParseScriptContext::TOP && 
Func(
"addr", expr)) {
 
 1136            error = 
"Address is not valid";
 
 1139        return std::make_unique<AddressDescriptor>(std::move(dest));
 
 1140    } 
else if (
Func(
"addr", expr)) {
 
 1141        error = 
"Can only have addr() at top level";
 
 1144    if (
ctx == ParseScriptContext::TOP && 
Func(
"tr", expr)) {
 
 1145        auto arg = 
Expr(expr);
 
 1146        auto internal_key = ParsePubkey(key_exp_index, arg, ParseScriptContext::P2TR, out, 
error);
 
 1147        if (!internal_key) 
return nullptr;
 
 1149        std::vector<std::unique_ptr<DescriptorImpl>> subscripts; 
 
 1150        std::vector<int> depths; 
 
 1152            if (!
Const(
",", expr)) {
 
 1159            std::vector<bool> branches;
 
 1164                while (
Const(
"{", expr)) {
 
 1165                    branches.push_back(
false); 
 
 1172                auto sarg = 
Expr(expr);
 
 1173                subscripts.emplace_back(
ParseScript(key_exp_index, sarg, ParseScriptContext::P2TR, out, 
error));
 
 1174                if (!subscripts.back()) 
return nullptr;
 
 1175                depths.push_back(branches.size());
 
 1177                while (branches.size() && branches.back()) {
 
 1178                    if (!
Const(
"}", expr)) {
 
 1182                    branches.pop_back(); 
 
 1185                if (branches.size() && !branches.back()) {
 
 1186                    if (!
Const(
",", expr)) {
 
 1190                    branches.back() = 
true; 
 
 1192            } 
while (branches.size());
 
 1200        return std::make_unique<TRDescriptor>(std::move(internal_key), std::move(subscripts), std::move(depths));
 
 1201    } 
else if (
Func(
"tr", expr)) {
 
 1202        error = 
"Can only have tr at top level";
 
 1205    if (
ctx == ParseScriptContext::TOP && 
Func(
"raw", expr)) {
 
 1206        std::string str(expr.begin(), expr.end());
 
 1208            error = 
"Raw script is not hex";
 
 1212        return std::make_unique<RawDescriptor>(
CScript(bytes.begin(), bytes.end()));
 
 1213    } 
else if (
Func(
"raw", expr)) {
 
 1214        error = 
"Can only have raw() at top level";
 
 1217    if (
ctx == ParseScriptContext::P2SH) {
 
 1218        error = 
"A function is needed within P2SH";
 
 1220    } 
else if (
ctx == ParseScriptContext::P2WSH) {
 
 1221        error = 
"A function is needed within P2WSH";
 
 1224    error = 
strprintf(
"%s is not a valid descriptor function", std::string(expr.begin(), expr.end()));
 
 1228std::unique_ptr<PubkeyProvider> InferPubkey(
const CPubKey& pubkey, ParseScriptContext, 
const SigningProvider& provider)
 
 1230    std::unique_ptr<PubkeyProvider> key_provider = std::make_unique<ConstPubkeyProvider>(0, pubkey, 
false);
 
 1233        return std::make_unique<OriginPubkeyProvider>(0, std::move(info), std::move(key_provider));
 
 1235    return key_provider;
 
 1241    std::copy(xkey.
begin(), xkey.
end(), full_key + 1);
 
 1243    std::unique_ptr<PubkeyProvider> key_provider = std::make_unique<ConstPubkeyProvider>(0, pubkey, 
true);
 
 1246        return std::make_unique<OriginPubkeyProvider>(0, std::move(info), std::move(key_provider));
 
 1248    return key_provider;
 
 1251std::unique_ptr<DescriptorImpl> InferScript(
const CScript& script, ParseScriptContext 
ctx, 
const SigningProvider& provider)
 
 1253    if (
ctx == ParseScriptContext::P2TR && script.
size() == 34 && script[0] == 32 && script[33] == 
OP_CHECKSIG) {
 
 1255        return std::make_unique<PKDescriptor>(InferXOnlyPubkey(key, 
ctx, provider));
 
 1258    std::vector<std::vector<unsigned char>> data;
 
 1261    if (txntype == 
TxoutType::PUBKEY && (
ctx == ParseScriptContext::TOP || 
ctx == ParseScriptContext::P2SH || 
ctx == ParseScriptContext::P2WSH)) {
 
 1264            return std::make_unique<PKDescriptor>(InferPubkey(pubkey, 
ctx, provider));
 
 1267    if (txntype == 
TxoutType::PUBKEYHASH && (
ctx == ParseScriptContext::TOP || 
ctx == ParseScriptContext::P2SH || 
ctx == ParseScriptContext::P2WSH)) {
 
 1271        if (provider.
GetPubKey(keyid, pubkey)) {
 
 1272            return std::make_unique<PKHDescriptor>(InferPubkey(pubkey, 
ctx, provider));
 
 1279        if (provider.
GetPubKey(keyid, pubkey)) {
 
 1280            return std::make_unique<WPKHDescriptor>(InferPubkey(pubkey, 
ctx, provider));
 
 1283    if (txntype == 
TxoutType::MULTISIG && (
ctx == ParseScriptContext::TOP || 
ctx == ParseScriptContext::P2SH || 
ctx == ParseScriptContext::P2WSH)) {
 
 1284        std::vector<std::unique_ptr<PubkeyProvider>> providers;
 
 1285        for (
size_t i = 1; i + 1 < data.size(); ++i) {
 
 1287            providers.push_back(InferPubkey(pubkey, 
ctx, provider));
 
 1289        return std::make_unique<MultisigDescriptor>((
int)data[0][0], std::move(providers));
 
 1295        if (provider.
GetCScript(scriptid, subscript)) {
 
 1296            auto sub = InferScript(subscript, ParseScriptContext::P2SH, provider);
 
 1297            if (sub) 
return std::make_unique<SHDescriptor>(std::move(sub));
 
 1304        if (provider.
GetCScript(scriptid, subscript)) {
 
 1305            auto sub = InferScript(subscript, ParseScriptContext::P2WSH, provider);
 
 1306            if (sub) 
return std::make_unique<WSHDescriptor>(std::move(sub));
 
 1312        std::copy(data[0].begin(), data[0].end(), pubkey.
begin());
 
 1321                std::vector<std::unique_ptr<DescriptorImpl>> subscripts; 
 
 1322                std::vector<int> depths; 
 
 1323                for (
const auto& [depth, script, leaf_ver] : *tree) {
 
 1324                    std::unique_ptr<DescriptorImpl> subdesc;
 
 1326                        subdesc = InferScript(script, ParseScriptContext::P2TR, provider);
 
 1332                        subscripts.push_back(std::move(subdesc));
 
 1333                        depths.push_back(depth);
 
 1337                    auto key = InferXOnlyPubkey(tap.
internal_key, ParseScriptContext::P2TR, provider);
 
 1338                    return std::make_unique<TRDescriptor>(std::move(key), std::move(subscripts), std::move(depths));
 
 1347            return std::make_unique<AddressDescriptor>(std::move(dest));
 
 1351    return std::make_unique<RawDescriptor>(script);
 
 1362    auto check_split = 
Split(sp, 
'#');
 
 1363    if (check_split.size() > 2) {
 
 1364        error = 
"Multiple '#' symbols";
 
 1367    if (check_split.size() == 1 && require_checksum){
 
 1368        error = 
"Missing checksum";
 
 1371    if (check_split.size() == 2) {
 
 1372        if (check_split[1].size() != 8) {
 
 1373            error = 
strprintf(
"Expected 8 character checksum, not %u characters", check_split[1].size());
 
 1377    auto checksum = DescriptorChecksum(check_split[0]);
 
 1378    if (checksum.empty()) {
 
 1379        error = 
"Invalid characters in payload";
 
 1382    if (check_split.size() == 2) {
 
 1383        if (!std::equal(checksum.begin(), checksum.end(), check_split[1].begin())) {
 
 1384            error = 
strprintf(
"Provided checksum '%s' does not match computed checksum '%s'", std::string(check_split[1].begin(), check_split[1].end()), checksum);
 
 1388    if (out_checksum) *out_checksum = std::move(checksum);
 
 1389    sp = check_split[0];
 
 1397    uint32_t key_exp_index = 0;
 
 1398    auto ret = 
ParseScript(key_exp_index, sp, ParseScriptContext::TOP, out, 
error);
 
 1399    if (sp.
size() == 0 && ret) 
return std::unique_ptr<Descriptor>(std::move(ret));
 
 1414    return InferScript(script, ParseScriptContext::TOP, provider);
 
 1425    xpubs[der_index] = xpub;
 
 1445    const auto& der_it = key_exp_it->second.find(der_index);
 
 1446    if (der_it == key_exp_it->second.end()) 
return false;
 
 1447    xpub = der_it->second;
 
 1465            if (xpub != parent_xpub_pair.second) {
 
 1466                throw std::runtime_error(std::string(__func__) + 
": New cached parent xpub does not match already cached parent xpub");
 
 1474        for (
const auto& derived_xpub_pair : derived_xpub_map_pair.second) {
 
 1477                if (xpub != derived_xpub_pair.second) {
 
 1478                    throw std::runtime_error(std::string(__func__) + 
": New cached derived xpub does not match already cached derived xpub");
 
 1482            CacheDerivedExtPubKey(derived_xpub_map_pair.first, derived_xpub_pair.first, derived_xpub_pair.second);
 
 1483            diff.
CacheDerivedExtPubKey(derived_xpub_map_pair.first, derived_xpub_pair.first, derived_xpub_pair.second);
 
 1489            if (xpub != lh_xpub_pair.second) {
 
 1490                throw std::runtime_error(std::string(__func__) + 
": New cached last hardened xpub does not match already cached last hardened xpub");
 
std::string FormatHDKeypath(const std::vector< uint32_t > &path)
An encapsulated private key.
bool IsValid() const
Check whether this private key is valid.
bool IsCompressed() const
Check whether the public key corresponding to this private key is (to be) compressed.
CPubKey GetPubKey() const
Compute the public key from a private key.
A reference to a CKey: the Hash160 of its serialized public key.
An encapsulated public key.
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
static constexpr unsigned int COMPRESSED_SIZE
A hasher class for RIPEMD-160.
CRIPEMD160 & Write(const unsigned char *data, size_t len)
void Finalize(unsigned char hash[OUTPUT_SIZE])
Serialized script, used inside transaction inputs and outputs.
A reference to a CScript: the Hash160 of its serialization (see script.h)
Cache for single descriptor's derived extended pubkeys.
bool GetCachedParentExtPubKey(uint32_t key_exp_pos, CExtPubKey &xpub) const
Retrieve a cached parent xpub.
ExtPubKeyMap m_last_hardened_xpubs
Map key expression index -> last hardened xpub.
void CacheDerivedExtPubKey(uint32_t key_exp_pos, uint32_t der_index, const CExtPubKey &xpub)
Cache an xpub derived at an index.
const ExtPubKeyMap GetCachedLastHardenedExtPubKeys() const
Retrieve all cached last hardened xpubs.
DescriptorCache MergeAndDiff(const DescriptorCache &other)
Combine another DescriptorCache into this one.
void CacheParentExtPubKey(uint32_t key_exp_pos, const CExtPubKey &xpub)
Cache a parent xpub.
void CacheLastHardenedExtPubKey(uint32_t key_exp_pos, const CExtPubKey &xpub)
Cache a last hardened xpub.
bool GetCachedDerivedExtPubKey(uint32_t key_exp_pos, uint32_t der_index, CExtPubKey &xpub) const
Retrieve a cached xpub derived at an index.
std::unordered_map< uint32_t, ExtPubKeyMap > m_derived_xpubs
Map key expression index -> map of (key derivation index -> xpub)
bool GetCachedLastHardenedExtPubKey(uint32_t key_exp_pos, CExtPubKey &xpub) const
Retrieve a cached last hardened xpub.
const ExtPubKeyMap GetCachedParentExtPubKeys() const
Retrieve all cached parent xpubs.
const std::unordered_map< uint32_t, ExtPubKeyMap > GetCachedDerivedExtPubKeys() const
Retrieve all cached derived xpubs.
ExtPubKeyMap m_parent_xpubs
Map key expression index -> parent xpub.
An interface to be implemented by keystores that support signing.
virtual bool GetCScript(const CScriptID &scriptid, CScript &script) const
virtual bool GetTaprootSpendData(const XOnlyPubKey &output_key, TaprootSpendData &spenddata) const
virtual bool GetPubKey(const CKeyID &address, CPubKey &pubkey) const
bool GetKeyOriginByXOnly(const XOnlyPubKey &pubkey, KeyOriginInfo &info) const
virtual bool GetKey(const CKeyID &address, CKey &key) const
virtual bool GetKeyOrigin(const CKeyID &keyid, KeyOriginInfo &info) const
A Span is an object that can refer to a contiguous sequence of objects.
constexpr std::size_t size() const noexcept
CONSTEXPR_IF_NOT_DEBUG Span< C > first(std::size_t count) const noexcept
constexpr C * begin() const noexcept
constexpr C * end() const noexcept
Utility class to construct Taproot outputs from internal key and script tree.
WitnessV1Taproot GetOutput()
Compute scriptPubKey (after Finalize()).
TaprootSpendData GetSpendData() const
Compute spending data (after Finalize()).
TaprootBuilder & Add(int depth, const CScript &script, int leaf_version, bool track=true)
Add a new script at a certain depth in the tree.
bool IsComplete() const
Return whether there were either no leaves, or the leaves form a Huffman tree.
static bool ValidDepths(const std::vector< int > &depths)
Check if a list of depths is legal (will lead to IsComplete()).
TaprootBuilder & Finalize(const XOnlyPubKey &internal_key)
Finalize the construction.
const unsigned char * end() const
const unsigned char * begin() const
CScript ParseScript(const std::string &s)
std::unique_ptr< Descriptor > InferDescriptor(const CScript &script, const SigningProvider &provider)
Find a descriptor for the specified script, using information from provider where possible.
std::unique_ptr< Descriptor > Parse(const std::string &descriptor, FlatSigningProvider &out, std::string &error, bool require_checksum)
Parse a descriptor string.
bool CheckChecksum(Span< const char > &sp, bool require_checksum, std::string &error, std::string *out_checksum=nullptr)
Check a descriptor checksum, and update desc to be the checksum-less part.
std::string GetDescriptorChecksum(const std::string &descriptor)
Get the checksum for a descriptor.
std::unordered_map< uint32_t, CExtPubKey > ExtPubKeyMap
static constexpr uint8_t TAPROOT_LEAF_TAPSCRIPT
static constexpr size_t TAPROOT_CONTROL_MAX_NODE_COUNT
std::string EncodeExtKey(const CExtKey &key)
CExtPubKey DecodeExtPubKey(const std::string &str)
std::string EncodeSecret(const CKey &key)
std::string EncodeDestination(const CTxDestination &dest)
CKey DecodeSecret(const std::string &str)
std::string EncodeExtPubKey(const CExtPubKey &key)
CTxDestination DecodeDestination(const std::string &str, std::string &error_msg)
CExtKey DecodeExtKey(const std::string &str)
std::vector< Span< const char > > Split(const Span< const char > &sp, char sep)
Split a string on every instance of sep, returning a vector.
Span< const char > Expr(Span< const char > &sp)
Extract the expression that sp begins with.
bool Const(const std::string &str, Span< const char > &sp)
Parse a constant.
bool Func(const std::string &str, Span< const char > &sp)
Parse a function call.
std::optional< OutputType > OutputTypeFromDestination(const CTxDestination &dest)
Get the OutputType for a CTxDestination.
@ TOP
Top-level scriptPubKey.
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE
static const int MAX_PUBKEYS_PER_MULTISIG
std::vector< unsigned char > ToByteVector(const T &in)
bool IsSolvable(const SigningProvider &provider, const CScript &script)
static bool GetPubKey(const SigningProvider &provider, const SignatureData &sigdata, const CKeyID &address, CPubKey &pubkey)
const SigningProvider & DUMMY_SIGNING_PROVIDER
FlatSigningProvider Merge(const FlatSigningProvider &a, const FlatSigningProvider &b)
constexpr Span< A > MakeSpan(A(&a)[N])
MakeSpan for arrays:
TxoutType Solver(const CScript &scriptPubKey, std::vector< std::vector< unsigned char > > &vSolutionsRet)
Parse a scriptPubKey and identify script type for standard scripts.
std::optional< std::vector< std::tuple< int, CScript, int > > > InferTaprootTree(const TaprootSpendData &spenddata, const XOnlyPubKey &output)
Given a TaprootSpendData and the output key, reconstruct its script tree.
CScript GetScriptForMultisig(int nRequired, const std::vector< CPubKey > &keys)
Generate a multisig script.
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a standard scriptPubKey for the destination address.
CScript GetScriptForRawPubKey(const CPubKey &pubKey)
Generate a P2PK script for the given pubkey.
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
std::variant< CNoDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, WitnessUnknown > CTxDestination
A txout script template with a specific destination.
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
std::vector< unsigned char > ParseHex(const char *psz)
bool ParseUInt32(const std::string &str, uint32_t *out)
Convert decimal string to unsigned 32-bit integer with strict parse error feedback.
bool IsHex(const std::string &str)
std::string ToString(const T &t)
Locale-independent version of std::to_string.
unsigned char vchFingerprint[4]
CExtPubKey Neuter() const
bool Derive(CExtKey &out, unsigned int nChild) const
bool Derive(CExtPubKey &out, unsigned int nChild) const
Interface for parsed descriptor objects.
virtual std::string ToString() const =0
Convert the descriptor back to a string, undoing parsing.
virtual bool ToNormalizedString(const SigningProvider &provider, std::string &out, const DescriptorCache *cache=nullptr) const =0
Convert the descriptor to a normalized string.
virtual std::optional< OutputType > GetOutputType() const =0
virtual bool Expand(int pos, const SigningProvider &provider, std::vector< CScript > &output_scripts, FlatSigningProvider &out, DescriptorCache *write_cache=nullptr) const =0
Expand a descriptor at a specified position.
virtual bool IsRange() const =0
Whether the expansion of this descriptor depends on the position.
virtual bool IsSolvable() const =0
Whether this descriptor has all information about signing ignoring lack of private keys.
virtual void ExpandPrivate(int pos, const SigningProvider &provider, FlatSigningProvider &out) const =0
Expand the private key for a descriptor at a specified position, if possible.
virtual bool ToPrivateString(const SigningProvider &provider, std::string &out) const =0
Convert the descriptor to a private string.
virtual bool ExpandFromCache(int pos, const DescriptorCache &read_cache, std::vector< CScript > &output_scripts, FlatSigningProvider &out) const =0
Expand a descriptor at a specified position using cached expansion data.
std::map< CKeyID, std::pair< CPubKey, KeyOriginInfo > > origins
std::map< XOnlyPubKey, TaprootSpendData > tr_spenddata
std::map< CKeyID, CPubKey > pubkeys
std::map< CKeyID, CKey > keys
std::map< CScriptID, CScript > scripts
unsigned char fingerprint[4]
First 32 bits of the Hash160 of the public key at the root of the path.
std::vector< uint32_t > path
XOnlyPubKey internal_key
The BIP341 internal key.
bool error(const char *fmt, const Args &... args)
static secp256k1_context * ctx
std::vector< typename std::common_type< Args... >::type > Vector(Args &&... args)
Construct a vector with the specified elements.