LCOV - code coverage report
Current view: top level - src/script - descriptor.cpp (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 791 831 95.2 %
Date: 2021-06-29 14:35:33 Functions: 95 102 93.1 %
Legend: Modified by patch:
Lines: hit not hit | Branches: + taken - not taken # not executed

Not modified by patch:
Lines: hit not hit | Branches: + taken - not taken # not executed
Branches: 412 468 88.0 %

           Branch data     Line data    Source code
#       1                 :            : // Copyright (c) 2018-2020 The Bitcoin Core developers
#       2                 :            : // Distributed under the MIT software license, see the accompanying
#       3                 :            : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
#       4                 :            : 
#       5                 :            : #include <script/descriptor.h>
#       6                 :            : 
#       7                 :            : #include <key_io.h>
#       8                 :            : #include <pubkey.h>
#       9                 :            : #include <script/script.h>
#      10                 :            : #include <script/standard.h>
#      11                 :            : 
#      12                 :            : #include <span.h>
#      13                 :            : #include <util/bip32.h>
#      14                 :            : #include <util/spanparsing.h>
#      15                 :            : #include <util/system.h>
#      16                 :            : #include <util/strencodings.h>
#      17                 :            : #include <util/vector.h>
#      18                 :            : 
#      19                 :            : #include <memory>
#      20                 :            : #include <optional>
#      21                 :            : #include <string>
#      22                 :            : #include <vector>
#      23                 :            : 
#      24                 :            : namespace {
#      25                 :            : 
#      26                 :            : ////////////////////////////////////////////////////////////////////////////
#      27                 :            : // Checksum                                                               //
#      28                 :            : ////////////////////////////////////////////////////////////////////////////
#      29                 :            : 
#      30                 :            : // This section implements a checksum algorithm for descriptors with the
#      31                 :            : // following properties:
#      32                 :            : // * Mistakes in a descriptor string are measured in "symbol errors". The higher
#      33                 :            : //   the number of symbol errors, the harder it is to detect:
#      34                 :            : //   * An error substituting a character from 0123456789()[],'/*abcdefgh@:$%{} for
#      35                 :            : //     another in that set always counts as 1 symbol error.
#      36                 :            : //     * Note that hex encoded keys are covered by these characters. Xprvs and
#      37                 :            : //       xpubs use other characters too, but already have their own checksum
#      38                 :            : //       mechanism.
#      39                 :            : //     * Function names like "multi()" use other characters, but mistakes in
#      40                 :            : //       these would generally result in an unparsable descriptor.
#      41                 :            : //   * A case error always counts as 1 symbol error.
#      42                 :            : //   * Any other 1 character substitution error counts as 1 or 2 symbol errors.
#      43                 :            : // * Any 1 symbol error is always detected.
#      44                 :            : // * Any 2 or 3 symbol error in a descriptor of up to 49154 characters is always detected.
#      45                 :            : // * Any 4 symbol error in a descriptor of up to 507 characters is always detected.
#      46                 :            : // * Any 5 symbol error in a descriptor of up to 77 characters is always detected.
#      47                 :            : // * Is optimized to minimize the chance a 5 symbol error in a descriptor up to 387 characters is undetected
#      48                 :            : // * Random errors have a chance of 1 in 2**40 of being undetected.
#      49                 :            : //
#      50                 :            : // These properties are achieved by expanding every group of 3 (non checksum) characters into
#      51                 :            : // 4 GF(32) symbols, over which a cyclic code is defined.
#      52                 :            : 
#      53                 :            : /*
#      54                 :            :  * Interprets c as 8 groups of 5 bits which are the coefficients of a degree 8 polynomial over GF(32),
#      55                 :            :  * multiplies that polynomial by x, computes its remainder modulo a generator, and adds the constant term val.
#      56                 :            :  *
#      57                 :            :  * This generator is G(x) = x^8 + {30}x^7 + {23}x^6 + {15}x^5 + {14}x^4 + {10}x^3 + {6}x^2 + {12}x + {9}.
#      58                 :            :  * It is chosen to define an cyclic error detecting code which is selected by:
#      59                 :            :  * - Starting from all BCH codes over GF(32) of degree 8 and below, which by construction guarantee detecting
#      60                 :            :  *   3 errors in windows up to 19000 symbols.
#      61                 :            :  * - Taking all those generators, and for degree 7 ones, extend them to degree 8 by adding all degree-1 factors.
#      62                 :            :  * - Selecting just the set of generators that guarantee detecting 4 errors in a window of length 512.
#      63                 :            :  * - Selecting one of those with best worst-case behavior for 5 errors in windows of length up to 512.
#      64                 :            :  *
#      65                 :            :  * The generator and the constants to implement it can be verified using this Sage code:
#      66                 :            :  *   B = GF(2) # Binary field
#      67                 :            :  *   BP.<b> = B[] # Polynomials over the binary field
#      68                 :            :  *   F_mod = b**5 + b**3 + 1
#      69                 :            :  *   F.<f> = GF(32, modulus=F_mod, repr='int') # GF(32) definition
#      70                 :            :  *   FP.<x> = F[] # Polynomials over GF(32)
#      71                 :            :  *   E_mod = x**3 + x + F.fetch_int(8)
#      72                 :            :  *   E.<e> = F.extension(E_mod) # Extension field definition
#      73                 :            :  *   alpha = e**2743 # Choice of an element in extension field
#      74                 :            :  *   for p in divisors(E.order() - 1): # Verify alpha has order 32767.
#      75                 :            :  *       assert((alpha**p == 1) == (p % 32767 == 0))
#      76                 :            :  *   G = lcm([(alpha**i).minpoly() for i in [1056,1057,1058]] + [x + 1])
#      77                 :            :  *   print(G) # Print out the generator
#      78                 :            :  *   for i in [1,2,4,8,16]: # Print out {1,2,4,8,16}*(G mod x^8), packed in hex integers.
#      79                 :            :  *       v = 0
#      80                 :            :  *       for coef in reversed((F.fetch_int(i)*(G % x**8)).coefficients(sparse=True)):
#      81                 :            :  *           v = v*32 + coef.integer_representation()
#      82                 :            :  *       print("0x%x" % v)
#      83                 :            :  */
#      84                 :            : uint64_t PolyMod(uint64_t c, int val)
#      85                 :   38500643 : {
#      86                 :   38500643 :     uint8_t c0 = c >> 35;
#      87                 :   38500643 :     c = ((c & 0x7ffffffff) << 5) ^ val;
#      88         [ +  + ]:   38500643 :     if (c0 & 1) c ^= 0xf5dee51989;
#      89         [ +  + ]:   38500643 :     if (c0 & 2) c ^= 0xa9fdca3312;
#      90         [ +  + ]:   38500643 :     if (c0 & 4) c ^= 0x1bab10e32d;
#      91         [ +  + ]:   38500643 :     if (c0 & 8) c ^= 0x3706b1677a;
#      92         [ +  + ]:   38500643 :     if (c0 & 16) c ^= 0x644d626ffd;
#      93                 :   38500643 :     return c;
#      94                 :   38500643 : }
#      95                 :            : 
#      96                 :            : std::string DescriptorChecksum(const Span<const char>& span)
#      97                 :     250836 : {
#      98                 :            :     /** A character set designed such that:
#      99                 :            :      *  - The most common 'unprotected' descriptor characters (hex, keypaths) are in the first group of 32.
#     100                 :            :      *  - Case errors cause an offset that's a multiple of 32.
#     101                 :            :      *  - As many alphabetic characters are in the same group (while following the above restrictions).
#     102                 :            :      *
#     103                 :            :      * If p(x) gives the position of a character c in this character set, every group of 3 characters
#     104                 :            :      * (a,b,c) is encoded as the 4 symbols (p(a) & 31, p(b) & 31, p(c) & 31, (p(a) / 32) + 3 * (p(b) / 32) + 9 * (p(c) / 32).
#     105                 :            :      * This means that changes that only affect the lower 5 bits of the position, or only the higher 2 bits, will just
#     106                 :            :      * affect a single symbol.
#     107                 :            :      *
#     108                 :            :      * As a result, within-group-of-32 errors count as 1 symbol, as do cross-group errors that don't affect
#     109                 :            :      * the position within the groups.
#     110                 :            :      */
#     111                 :     250836 :     static std::string INPUT_CHARSET =
#     112                 :     250836 :         "0123456789()[],'/*abcdefgh@:$%{}"
#     113                 :     250836 :         "IJKLMNOPQRSTUVWXYZ&+-.;<=>?!^_|~"
#     114                 :     250836 :         "ijklmnopqrstuvwxyzABCDEFGH`#\"\\ ";
#     115                 :            : 
#     116                 :            :     /** The character set for the checksum itself (same as bech32). */
#     117                 :     250836 :     static std::string CHECKSUM_CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l";
#     118                 :            : 
#     119                 :     250836 :     uint64_t c = 1;
#     120                 :     250836 :     int cls = 0;
#     121                 :     250836 :     int clscount = 0;
#     122         [ +  + ]:   27307272 :     for (auto ch : span) {
#     123                 :   27307272 :         auto pos = INPUT_CHARSET.find(ch);
#     124         [ +  + ]:   27307272 :         if (pos == std::string::npos) return "";
#     125                 :   27307270 :         c = PolyMod(c, pos & 31); // Emit a symbol for the position inside the group, for every character.
#     126                 :   27307270 :         cls = cls * 3 + (pos >> 5); // Accumulate the group numbers
#     127         [ +  + ]:   27307270 :         if (++clscount == 3) {
#     128                 :            :             // Emit an extra symbol representing the group numbers, for every 3 characters.
#     129                 :    8996722 :             c = PolyMod(c, cls);
#     130                 :    8996722 :             cls = 0;
#     131                 :    8996722 :             clscount = 0;
#     132                 :    8996722 :         }
#     133                 :   27307270 :     }
#     134         [ +  + ]:     250836 :     if (clscount > 0) c = PolyMod(c, cls);
#     135         [ +  + ]:    2257506 :     for (int j = 0; j < 8; ++j) c = PolyMod(c, 0); // Shift further to determine the checksum.
#     136                 :     250834 :     c ^= 1; // Prevent appending zeroes from not affecting the checksum.
#     137                 :            : 
#     138                 :     250834 :     std::string ret(8, ' ');
#     139         [ +  + ]:    2257506 :     for (int j = 0; j < 8; ++j) ret[j] = CHECKSUM_CHARSET[(c >> (5 * (7 - j))) & 31];
#     140                 :     250834 :     return ret;
#     141                 :     250836 : }
#     142                 :            : 
#     143                 :     247686 : std::string AddChecksum(const std::string& str) { return str + "#" + DescriptorChecksum(str); }
#     144                 :            : 
#     145                 :            : ////////////////////////////////////////////////////////////////////////////
#     146                 :            : // Internal representation                                                //
#     147                 :            : ////////////////////////////////////////////////////////////////////////////
#     148                 :            : 
#     149                 :            : typedef std::vector<uint32_t> KeyPath;
#     150                 :            : 
#     151                 :            : /** Interface for public key objects in descriptors. */
#     152                 :            : struct PubkeyProvider
#     153                 :            : {
#     154                 :            : protected:
#     155                 :            :     //! Index of this key expression in the descriptor
#     156                 :            :     //! E.g. If this PubkeyProvider is key1 in multi(2, key1, key2, key3), then m_expr_index = 0
#     157                 :            :     uint32_t m_expr_index;
#     158                 :            : 
#     159                 :            : public:
#     160                 :     408707 :     explicit PubkeyProvider(uint32_t exp_index) : m_expr_index(exp_index) {}
#     161                 :            : 
#     162                 :     408707 :     virtual ~PubkeyProvider() = default;
#     163                 :            : 
#     164                 :            :     /** Derive a public key.
#     165                 :            :      *  read_cache is the cache to read keys from (if not nullptr)
#     166                 :            :      *  write_cache is the cache to write keys to (if not nullptr)
#     167                 :            :      *  Caches are not exclusive but this is not tested. Currently we use them exclusively
#     168                 :            :      */
#     169                 :            :     virtual bool GetPubKey(int pos, const SigningProvider& arg, CPubKey& key, KeyOriginInfo& info, const DescriptorCache* read_cache = nullptr, DescriptorCache* write_cache = nullptr) = 0;
#     170                 :            : 
#     171                 :            :     /** Whether this represent multiple public keys at different positions. */
#     172                 :            :     virtual bool IsRange() const = 0;
#     173                 :            : 
#     174                 :            :     /** Get the size of the generated public key(s) in bytes (33 or 65). */
#     175                 :            :     virtual size_t GetSize() const = 0;
#     176                 :            : 
#     177                 :            :     /** Get the descriptor string form. */
#     178                 :            :     virtual std::string ToString() const = 0;
#     179                 :            : 
#     180                 :            :     /** Get the descriptor string form including private data (if available in arg). */
#     181                 :            :     virtual bool ToPrivateString(const SigningProvider& arg, std::string& out) const = 0;
#     182                 :            : 
#     183                 :            :     /** Get the descriptor string form with the xpub at the last hardened derivation */
#     184                 :            :     virtual bool ToNormalizedString(const SigningProvider& arg, std::string& out, bool priv) const = 0;
#     185                 :            : 
#     186                 :            :     /** Derive a private key, if private data is available in arg. */
#     187                 :            :     virtual bool GetPrivKey(int pos, const SigningProvider& arg, CKey& key) const = 0;
#     188                 :            : };
#     189                 :            : 
#     190                 :            : class OriginPubkeyProvider final : public PubkeyProvider
#     191                 :            : {
#     192                 :            :     KeyOriginInfo m_origin;
#     193                 :            :     std::unique_ptr<PubkeyProvider> m_provider;
#     194                 :            : 
#     195                 :            :     std::string OriginString() const
#     196                 :     119414 :     {
#     197                 :     119414 :         return HexStr(m_origin.fingerprint) + FormatHDKeypath(m_origin.path);
#     198                 :     119414 :     }
#     199                 :            : 
#     200                 :            : public:
#     201                 :     202790 :     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)) {}
#     202                 :            :     bool GetPubKey(int pos, const SigningProvider& arg, CPubKey& key, KeyOriginInfo& info, const DescriptorCache* read_cache = nullptr, DescriptorCache* write_cache = nullptr) override
#     203                 :     107206 :     {
#     204         [ +  + ]:     107206 :         if (!m_provider->GetPubKey(pos, arg, key, info, read_cache, write_cache)) return false;
#     205                 :     107189 :         std::copy(std::begin(m_origin.fingerprint), std::end(m_origin.fingerprint), info.fingerprint);
#     206                 :     107189 :         info.path.insert(info.path.begin(), m_origin.path.begin(), m_origin.path.end());
#     207                 :     107189 :         return true;
#     208                 :     107189 :     }
#     209                 :       1094 :     bool IsRange() const override { return m_provider->IsRange(); }
#     210                 :        324 :     size_t GetSize() const override { return m_provider->GetSize(); }
#     211                 :     119099 :     std::string ToString() const override { return "[" + OriginString() + "]" + m_provider->ToString(); }
#     212                 :            :     bool ToPrivateString(const SigningProvider& arg, std::string& ret) const override
#     213                 :        200 :     {
#     214                 :        200 :         std::string sub;
#     215         [ +  + ]:        200 :         if (!m_provider->ToPrivateString(arg, sub)) return false;
#     216                 :        100 :         ret = "[" + OriginString() + "]" + std::move(sub);
#     217                 :        100 :         return true;
#     218                 :        100 :     }
#     219                 :            :     bool ToNormalizedString(const SigningProvider& arg, std::string& ret, bool priv) const override
#     220                 :        215 :     {
#     221                 :        215 :         std::string sub;
#     222         [ -  + ]:        215 :         if (!m_provider->ToNormalizedString(arg, sub, priv)) return false;
#     223                 :            :         // If m_provider is a BIP32PubkeyProvider, we may get a string formatted like a OriginPubkeyProvider
#     224                 :            :         // In that case, we need to strip out the leading square bracket and fingerprint from the substring,
#     225                 :            :         // and append that to our own origin string.
#     226         [ +  + ]:        215 :         if (sub[0] == '[') {
#     227                 :         32 :             sub = sub.substr(9);
#     228                 :         32 :             ret = "[" + OriginString() + std::move(sub);
#     229                 :        183 :         } else {
#     230                 :        183 :             ret = "[" + OriginString() + "]" + std::move(sub);
#     231                 :        183 :         }
#     232                 :        215 :         return true;
#     233                 :        215 :     }
#     234                 :            :     bool GetPrivKey(int pos, const SigningProvider& arg, CKey& key) const override
#     235                 :         78 :     {
#     236                 :         78 :         return m_provider->GetPrivKey(pos, arg, key);
#     237                 :         78 :     }
#     238                 :            : };
#     239                 :            : 
#     240                 :            : /** An object representing a parsed constant public key in a descriptor. */
#     241                 :            : class ConstPubkeyProvider final : public PubkeyProvider
#     242                 :            : {
#     243                 :            :     CPubKey m_pubkey;
#     244                 :            : 
#     245                 :            : public:
#     246                 :     204079 :     ConstPubkeyProvider(uint32_t exp_index, const CPubKey& pubkey) : PubkeyProvider(exp_index), m_pubkey(pubkey) {}
#     247                 :            :     bool GetPubKey(int pos, const SigningProvider& arg, CPubKey& key, KeyOriginInfo& info, const DescriptorCache* read_cache = nullptr, DescriptorCache* write_cache = nullptr) override
#     248                 :     159122 :     {
#     249                 :     159122 :         key = m_pubkey;
#     250                 :     159122 :         info.path.clear();
#     251                 :     159122 :         CKeyID keyid = m_pubkey.GetID();
#     252                 :     159122 :         std::copy(keyid.begin(), keyid.begin() + sizeof(info.fingerprint), info.fingerprint);
#     253                 :     159122 :         return true;
#     254                 :     159122 :     }
#     255                 :       9181 :     bool IsRange() const override { return false; }
#     256                 :       1087 :     size_t GetSize() const override { return m_pubkey.size(); }
#     257                 :     144940 :     std::string ToString() const override { return HexStr(m_pubkey); }
#     258                 :            :     bool ToPrivateString(const SigningProvider& arg, std::string& ret) const override
#     259                 :        724 :     {
#     260                 :        724 :         CKey key;
#     261         [ +  + ]:        724 :         if (!arg.GetKey(m_pubkey.GetID(), key)) return false;
#     262                 :        632 :         ret = EncodeSecret(key);
#     263                 :        632 :         return true;
#     264                 :        632 :     }
#     265                 :            :     bool ToNormalizedString(const SigningProvider& arg, std::string& ret, bool priv) const override
#     266                 :        639 :     {
#     267         [ +  + ]:        639 :         if (priv) return ToPrivateString(arg, ret);
#     268                 :        323 :         ret = ToString();
#     269                 :        323 :         return true;
#     270                 :        323 :     }
#     271                 :            :     bool GetPrivKey(int pos, const SigningProvider& arg, CKey& key) const override
#     272                 :       4787 :     {
#     273                 :       4787 :         return arg.GetKey(m_pubkey.GetID(), key);
#     274                 :       4787 :     }
#     275                 :            : };
#     276                 :            : 
#     277                 :            : enum class DeriveType {
#     278                 :            :     NO,
#     279                 :            :     UNHARDENED,
#     280                 :            :     HARDENED,
#     281                 :            : };
#     282                 :            : 
#     283                 :            : /** An object representing a parsed extended public key in a descriptor. */
#     284                 :            : class BIP32PubkeyProvider final : public PubkeyProvider
#     285                 :            : {
#     286                 :            :     // Root xpub, path, and final derivation step type being used, if any
#     287                 :            :     CExtPubKey m_root_extkey;
#     288                 :            :     KeyPath m_path;
#     289                 :            :     DeriveType m_derive;
#     290                 :            :     // Cache of the parent of the final derived pubkeys.
#     291                 :            :     // Primarily useful for situations when no read_cache is provided
#     292                 :            :     CExtPubKey m_cached_xpub;
#     293                 :            : 
#     294                 :            :     bool GetExtKey(const SigningProvider& arg, CExtKey& ret) const
#     295                 :      11608 :     {
#     296                 :      11608 :         CKey key;
#     297         [ +  + ]:      11608 :         if (!arg.GetKey(m_root_extkey.pubkey.GetID(), key)) return false;
#     298                 :      11082 :         ret.nDepth = m_root_extkey.nDepth;
#     299                 :      11082 :         std::copy(m_root_extkey.vchFingerprint, m_root_extkey.vchFingerprint + sizeof(ret.vchFingerprint), ret.vchFingerprint);
#     300                 :      11082 :         ret.nChild = m_root_extkey.nChild;
#     301                 :      11082 :         ret.chaincode = m_root_extkey.chaincode;
#     302                 :      11082 :         ret.key = key;
#     303                 :      11082 :         return true;
#     304                 :      11082 :     }
#     305                 :            : 
#     306                 :            :     // Derives the last xprv
#     307                 :            :     bool GetDerivedExtKey(const SigningProvider& arg, CExtKey& xprv) const
#     308                 :      10667 :     {
#     309         [ +  + ]:      10667 :         if (!GetExtKey(arg, xprv)) return false;
#     310         [ +  + ]:      25852 :         for (auto entry : m_path) {
#     311                 :      25852 :             xprv.Derive(xprv, entry);
#     312                 :      25852 :         }
#     313                 :      10285 :         return true;
#     314                 :      10285 :     }
#     315                 :            : 
#     316                 :            :     bool IsHardened() const
#     317                 :       8209 :     {
#     318         [ +  + ]:       8209 :         if (m_derive == DeriveType::HARDENED) return true;
#     319         [ +  + ]:       1116 :         for (auto entry : m_path) {
#     320         [ +  + ]:       1093 :             if (entry >> 31) return true;
#     321                 :       1093 :         }
#     322                 :       1116 :         return false;
#     323                 :       1116 :     }
#     324                 :            : 
#     325                 :            : public:
#     326                 :       1838 :     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                 :     148277 :     bool IsRange() const override { return m_derive != DeriveType::NO; }
#     328                 :        260 :     size_t GetSize() const override { return 33; }
#     329                 :            :     bool GetPubKey(int pos, const SigningProvider& arg, CPubKey& key_out, KeyOriginInfo& final_info_out, const DescriptorCache* read_cache = nullptr, DescriptorCache* write_cache = nullptr) override
#     330                 :     353568 :     {
#     331                 :            :         // Info of parent of the to be derived pubkey
#     332                 :     353568 :         KeyOriginInfo parent_info;
#     333                 :     353568 :         CKeyID keyid = m_root_extkey.pubkey.GetID();
#     334                 :     353568 :         std::copy(keyid.begin(), keyid.begin() + sizeof(parent_info.fingerprint), parent_info.fingerprint);
#     335                 :     353568 :         parent_info.path = m_path;
#     336                 :            : 
#     337                 :            :         // Info of the derived key itself which is copied out upon successful completion
#     338                 :     353568 :         KeyOriginInfo final_info_out_tmp = parent_info;
#     339         [ +  + ]:     353568 :         if (m_derive == DeriveType::UNHARDENED) final_info_out_tmp.path.push_back((uint32_t)pos);
#     340         [ +  + ]:     353568 :         if (m_derive == DeriveType::HARDENED) final_info_out_tmp.path.push_back(((uint32_t)pos) | 0x80000000L);
#     341                 :            : 
#     342                 :            :         // Derive keys or fetch them from cache
#     343                 :     353568 :         CExtPubKey final_extkey = m_root_extkey;
#     344                 :     353568 :         CExtPubKey parent_extkey = m_root_extkey;
#     345                 :     353568 :         bool der = true;
#     346         [ +  + ]:     353568 :         if (read_cache) {
#     347         [ +  + ]:     332237 :             if (!read_cache->GetCachedDerivedExtPubKey(m_expr_index, pos, final_extkey)) {
#     348         [ +  + ]:     331509 :                 if (m_derive == DeriveType::HARDENED) return false;
#     349                 :            :                 // Try to get the derivation parent
#     350         [ +  + ]:     330517 :                 if (!read_cache->GetCachedParentExtPubKey(m_expr_index, parent_extkey)) return false;
#     351                 :     329730 :                 final_extkey = parent_extkey;
#     352         [ +  + ]:     329730 :                 if (m_derive == DeriveType::UNHARDENED) der = parent_extkey.Derive(final_extkey, pos);
#     353                 :     329730 :             }
#     354 [ +  + ][ +  + ]:     332237 :         } else if (m_cached_xpub.pubkey.IsValid() && m_derive != DeriveType::HARDENED) {
#     355                 :      13122 :             parent_extkey = final_extkey = m_cached_xpub;
#     356         [ +  + ]:      13122 :             if (m_derive == DeriveType::UNHARDENED) der = parent_extkey.Derive(final_extkey, pos);
#     357         [ +  + ]:      13122 :         } else if (IsHardened()) {
#     358                 :       7922 :             CExtKey xprv;
#     359         [ +  + ]:       7922 :             if (!GetDerivedExtKey(arg, xprv)) return false;
#     360                 :       7704 :             parent_extkey = xprv.Neuter();
#     361         [ +  + ]:       7704 :             if (m_derive == DeriveType::UNHARDENED) der = xprv.Derive(xprv, pos);
#     362         [ +  + ]:       7704 :             if (m_derive == DeriveType::HARDENED) der = xprv.Derive(xprv, pos | 0x80000000UL);
#     363                 :       7704 :             final_extkey = xprv.Neuter();
#     364                 :       7704 :         } else {
#     365         [ +  + ]:        287 :             for (auto entry : m_path) {
#     366                 :        258 :                 der = parent_extkey.Derive(parent_extkey, entry);
#     367                 :        258 :                 assert(der);
#     368                 :        258 :             }
#     369                 :        287 :             final_extkey = parent_extkey;
#     370         [ +  + ]:        287 :             if (m_derive == DeriveType::UNHARDENED) der = parent_extkey.Derive(final_extkey, pos);
#     371                 :        287 :             assert(m_derive != DeriveType::HARDENED);
#     372                 :        287 :         }
#     373                 :     353568 :         assert(der);
#     374                 :            : 
#     375                 :     351571 :         final_info_out = final_info_out_tmp;
#     376                 :     351571 :         key_out = final_extkey.pubkey;
#     377                 :            : 
#     378                 :            :         // We rely on the consumer to check that m_derive isn't HARDENED as above
#     379                 :            :         // But we can't have already cached something in case we read something from the cache
#     380                 :            :         // and parent_extkey isn't actually the parent.
#     381         [ +  + ]:     351571 :         if (!m_cached_xpub.pubkey.IsValid()) m_cached_xpub = parent_extkey;
#     382                 :            : 
#     383         [ +  + ]:     351571 :         if (write_cache) {
#     384                 :            :             // Only cache parent if there is any unhardened derivation
#     385         [ +  + ]:       2319 :             if (m_derive != DeriveType::HARDENED) {
#     386                 :       1453 :                 write_cache->CacheParentExtPubKey(m_expr_index, parent_extkey);
#     387         [ +  - ]:       1453 :             } else if (final_info_out.path.size() > 0) {
#     388                 :        866 :                 write_cache->CacheDerivedExtPubKey(m_expr_index, pos, final_extkey);
#     389                 :        866 :             }
#     390                 :       2319 :         }
#     391                 :            : 
#     392                 :     351571 :         return true;
#     393                 :     353568 :     }
#     394                 :            :     std::string ToString() const override
#     395                 :     107848 :     {
#     396                 :     107848 :         std::string ret = EncodeExtPubKey(m_root_extkey) + FormatHDKeypath(m_path);
#     397         [ +  + ]:     107848 :         if (IsRange()) {
#     398                 :     107588 :             ret += "/*";
#     399         [ +  + ]:     107588 :             if (m_derive == DeriveType::HARDENED) ret += '\'';
#     400                 :     107588 :         }
#     401                 :     107848 :         return ret;
#     402                 :     107848 :     }
#     403                 :            :     bool ToPrivateString(const SigningProvider& arg, std::string& out) const override
#     404                 :        552 :     {
#     405                 :        552 :         CExtKey key;
#     406         [ +  + ]:        552 :         if (!GetExtKey(arg, key)) return false;
#     407                 :        408 :         out = EncodeExtKey(key) + FormatHDKeypath(m_path);
#     408         [ +  + ]:        408 :         if (IsRange()) {
#     409                 :        152 :             out += "/*";
#     410         [ +  + ]:        152 :             if (m_derive == DeriveType::HARDENED) out += '\'';
#     411                 :        152 :         }
#     412                 :        408 :         return true;
#     413                 :        408 :     }
#     414                 :            :     bool ToNormalizedString(const SigningProvider& arg, std::string& out, bool priv) const override
#     415                 :        765 :     {
#     416                 :            :         // For hardened derivation type, just return the typical string, nothing to normalize
#     417         [ +  + ]:        765 :         if (m_derive == DeriveType::HARDENED) {
#     418         [ +  + ]:         65 :             if (priv) return ToPrivateString(arg, out);
#     419                 :         33 :             out = ToString();
#     420                 :         33 :             return true;
#     421                 :         33 :         }
#     422                 :            :         // Step backwards to find the last hardened step in the path
#     423                 :        700 :         int i = (int)m_path.size() - 1;
#     424         [ +  + ]:       1337 :         for (; i >= 0; --i) {
#     425         [ +  + ]:       1026 :             if (m_path.at(i) >> 31) {
#     426                 :        389 :                 break;
#     427                 :        389 :             }
#     428                 :       1026 :         }
#     429                 :            :         // Either no derivation or all unhardened derivation
#     430         [ +  + ]:        700 :         if (i == -1) {
#     431         [ +  + ]:        311 :             if (priv) return ToPrivateString(arg, out);
#     432                 :        163 :             out = ToString();
#     433                 :        163 :             return true;
#     434                 :        163 :         }
#     435                 :            :         // Derive the xpub at the last hardened step
#     436                 :        389 :         CExtKey xprv;
#     437         [ -  + ]:        389 :         if (!GetExtKey(arg, xprv)) return false;
#     438                 :        389 :         KeyOriginInfo origin;
#     439                 :        389 :         int k = 0;
#     440         [ +  + ]:       1364 :         for (; k <= i; ++k) {
#     441                 :            :             // Derive
#     442                 :        975 :             xprv.Derive(xprv, m_path.at(k));
#     443                 :            :             // Add to the path
#     444                 :        975 :             origin.path.push_back(m_path.at(k));
#     445                 :            :             // First derivation element, get the fingerprint for origin
#     446         [ +  + ]:        975 :             if (k == 0) {
#     447                 :        389 :                 std::copy(xprv.vchFingerprint, xprv.vchFingerprint + 4, origin.fingerprint);
#     448                 :        389 :             }
#     449                 :        975 :         }
#     450                 :            :         // Build the remaining path
#     451                 :        389 :         KeyPath end_path;
#     452         [ +  + ]:        778 :         for (; k < (int)m_path.size(); ++k) {
#     453                 :        389 :             end_path.push_back(m_path.at(k));
#     454                 :        389 :         }
#     455                 :            :         // Build the string
#     456                 :        389 :         std::string origin_str = HexStr(origin.fingerprint) + FormatHDKeypath(origin.path);
#     457         [ +  + ]:        389 :         out = "[" + origin_str + "]" + (priv ? EncodeExtKey(xprv) : EncodeExtPubKey(xprv.Neuter())) + FormatHDKeypath(end_path);
#     458         [ +  + ]:        389 :         if (IsRange()) {
#     459                 :        293 :             out += "/*";
#     460                 :        293 :             assert(m_derive == DeriveType::UNHARDENED);
#     461                 :        293 :         }
#     462                 :        389 :         return true;
#     463                 :        389 :     }
#     464                 :            :     bool GetPrivKey(int pos, const SigningProvider& arg, CKey& key) const override
#     465                 :       2745 :     {
#     466                 :       2745 :         CExtKey extkey;
#     467         [ +  + ]:       2745 :         if (!GetDerivedExtKey(arg, extkey)) return false;
#     468         [ +  + ]:       2581 :         if (m_derive == DeriveType::UNHARDENED) extkey.Derive(extkey, pos);
#     469         [ +  + ]:       2581 :         if (m_derive == DeriveType::HARDENED) extkey.Derive(extkey, pos | 0x80000000UL);
#     470                 :       2581 :         key = extkey.key;
#     471                 :       2581 :         return true;
#     472                 :       2581 :     }
#     473                 :            : };
#     474                 :            : 
#     475                 :            : /** Base class for all Descriptor implementations. */
#     476                 :            : class DescriptorImpl : public Descriptor
#     477                 :            : {
#     478                 :            :     //! Public key arguments for this descriptor (size 1 for PK, PKH, WPKH; any size for Multisig).
#     479                 :            :     const std::vector<std::unique_ptr<PubkeyProvider>> m_pubkey_args;
#     480                 :            :     //! The string name of the descriptor function.
#     481                 :            :     const std::string m_name;
#     482                 :            : 
#     483                 :            : protected:
#     484                 :            :     //! The sub-descriptor arguments (empty for everything but SH and WSH).
#     485                 :            :     //! In doc/descriptors.m this is referred to as SCRIPT expressions sh(SCRIPT)
#     486                 :            :     //! and wsh(SCRIPT), and distinct from KEY expressions and ADDR expressions.
#     487                 :            :     //! Subdescriptors can only ever generate a single script.
#     488                 :            :     const std::vector<std::unique_ptr<DescriptorImpl>> m_subdescriptor_args;
#     489                 :            : 
#     490                 :            :     //! Return a serialization of anything except pubkey and script arguments, to be prepended to those.
#     491                 :     274147 :     virtual std::string ToStringExtra() const { return ""; }
#     492                 :            : 
#     493                 :            :     /** A helper function to construct the scripts for this descriptor.
#     494                 :            :      *
#     495                 :            :      *  This function is invoked once by ExpandHelper.
#     496                 :            :      *
#     497                 :            :      *  @param pubkeys The evaluations of the m_pubkey_args field.
#     498                 :            :      *  @param scripts The evaluations of m_subdescriptor_args (one for each m_subdescriptor_args element).
#     499                 :            :      *  @param out A FlatSigningProvider to put scripts or public keys in that are necessary to the solver.
#     500                 :            :      *             The origin info of the provided pubkeys is automatically added.
#     501                 :            :      *  @return A vector with scriptPubKeys for this descriptor.
#     502                 :            :      */
#     503                 :            :     virtual std::vector<CScript> MakeScripts(const std::vector<CPubKey>& pubkeys, Span<const CScript> scripts, FlatSigningProvider& out) const = 0;
#     504                 :            : 
#     505                 :            : public:
#     506                 :     308699 :     DescriptorImpl(std::vector<std::unique_ptr<PubkeyProvider>> pubkeys, const std::string& name) : m_pubkey_args(std::move(pubkeys)), m_name(name), m_subdescriptor_args() {}
#     507                 :      27510 :     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))) {}
#     508                 :            : 
#     509                 :            :     bool IsSolvable() const override
#     510                 :       2040 :     {
#     511         [ +  + ]:       2040 :         for (const auto& arg : m_subdescriptor_args) {
#     512         [ -  + ]:        778 :             if (!arg->IsSolvable()) return false;
#     513                 :        778 :         }
#     514                 :       2040 :         return true;
#     515                 :       2040 :     }
#     516                 :            : 
#     517                 :            :     bool IsRange() const final
#     518                 :      50214 :     {
#     519         [ +  + ]:      50214 :         for (const auto& pubkey : m_pubkey_args) {
#     520         [ +  + ]:      48813 :             if (pubkey->IsRange()) return true;
#     521                 :      48813 :         }
#     522         [ +  + ]:      50214 :         for (const auto& arg : m_subdescriptor_args) {
#     523         [ +  + ]:       2413 :             if (arg->IsRange()) return true;
#     524                 :       2413 :         }
#     525                 :      10781 :         return false;
#     526                 :      10781 :     }
#     527                 :            : 
#     528                 :            :     virtual bool ToStringSubScriptHelper(const SigningProvider* arg, std::string& ret, bool priv, bool normalized) const
#     529                 :     277073 :     {
#     530                 :     277073 :         size_t pos = 0;
#     531         [ +  + ]:     277073 :         for (const auto& scriptarg : m_subdescriptor_args) {
#     532         [ -  + ]:      29623 :             if (pos++) ret += ",";
#     533                 :      29623 :             std::string tmp;
#     534         [ +  + ]:      29623 :             if (!scriptarg->ToStringHelper(arg, tmp, priv, normalized)) return false;
#     535                 :      29487 :             ret += std::move(tmp);
#     536                 :      29487 :         }
#     537                 :     277073 :         return true;
#     538                 :     277073 :     }
#     539                 :            : 
#     540                 :            :     bool ToStringHelper(const SigningProvider* arg, std::string& out, bool priv, bool normalized) const
#     541                 :     277309 :     {
#     542                 :     277309 :         std::string extra = ToStringExtra();
#     543         [ +  + ]:     277309 :         size_t pos = extra.size() > 0 ? 1 : 0;
#     544                 :     277309 :         std::string ret = m_name + "(" + extra;
#     545         [ +  + ]:     277309 :         for (const auto& pubkey : m_pubkey_args) {
#     546         [ +  + ]:     254453 :             if (pos++) ret += ",";
#     547                 :     254453 :             std::string tmp;
#     548         [ +  + ]:     254453 :             if (normalized) {
#     549         [ -  + ]:       1404 :                 if (!pubkey->ToNormalizedString(*arg, tmp, priv)) return false;
#     550         [ +  + ]:     253049 :             } else if (priv) {
#     551         [ +  + ]:        780 :                 if (!pubkey->ToPrivateString(*arg, tmp)) return false;
#     552                 :     252269 :             } else {
#     553                 :     252269 :                 tmp = pubkey->ToString();
#     554                 :     252269 :             }
#     555                 :     254453 :             ret += std::move(tmp);
#     556                 :     254217 :         }
#     557                 :     277309 :         std::string subscript;
#     558         [ +  + ]:     277073 :         if (!ToStringSubScriptHelper(arg, subscript, priv, normalized)) return false;
#     559 [ +  + ][ -  + ]:     276937 :         if (pos && subscript.size()) ret += ',';
#     560                 :     276937 :         out = std::move(ret) + std::move(subscript) + ")";
#     561                 :     276937 :         return true;
#     562                 :     276937 :     }
#     563                 :            : 
#     564                 :            :     std::string ToString() const final
#     565                 :     246425 :     {
#     566                 :     246425 :         std::string ret;
#     567                 :     246425 :         ToStringHelper(nullptr, ret, false, false);
#     568                 :     246425 :         return AddChecksum(ret);
#     569                 :     246425 :     }
#     570                 :            : 
#     571                 :            :     bool ToPrivateString(const SigningProvider& arg, std::string& out) const final
#     572                 :        472 :     {
#     573                 :        472 :         bool ret = ToStringHelper(&arg, out, true, false);
#     574                 :        472 :         out = AddChecksum(out);
#     575                 :        472 :         return ret;
#     576                 :        472 :     }
#     577                 :            : 
#     578                 :            :     bool ToNormalizedString(const SigningProvider& arg, std::string& out, bool priv) const override final
#     579                 :        789 :     {
#     580                 :        789 :         bool ret = ToStringHelper(&arg, out, priv, true);
#     581                 :        789 :         out = AddChecksum(out);
#     582                 :        789 :         return ret;
#     583                 :        789 :     }
#     584                 :            : 
#     585                 :            :     bool ExpandHelper(int pos, const SigningProvider& arg, const DescriptorCache* read_cache, std::vector<CScript>& output_scripts, FlatSigningProvider& out, DescriptorCache* write_cache) const
#     586                 :     558008 :     {
#     587                 :     558008 :         std::vector<std::pair<CPubKey, KeyOriginInfo>> entries;
#     588                 :     558008 :         entries.reserve(m_pubkey_args.size());
#     589                 :            : 
#     590                 :            :         // Construct temporary data in `entries`, `subscripts`, and `subprovider` to avoid producing output in case of failure.
#     591         [ +  + ]:     558008 :         for (const auto& p : m_pubkey_args) {
#     592                 :     512690 :             entries.emplace_back();
#     593         [ +  + ]:     512690 :             if (!p->GetPubKey(pos, arg, entries.back().first, entries.back().second, read_cache, write_cache)) return false;
#     594                 :     512690 :         }
#     595                 :     558008 :         std::vector<CScript> subscripts;
#     596                 :     556011 :         FlatSigningProvider subprovider;
#     597         [ +  + ]:     556011 :         for (const auto& subarg : m_subdescriptor_args) {
#     598                 :      30861 :             std::vector<CScript> outscripts;
#     599         [ +  + ]:      30861 :             if (!subarg->ExpandHelper(pos, arg, read_cache, outscripts, subprovider, write_cache)) return false;
#     600                 :      30395 :             assert(outscripts.size() == 1);
#     601                 :      30395 :             subscripts.emplace_back(std::move(outscripts[0]));
#     602                 :      30395 :         }
#     603                 :     556011 :         out = Merge(std::move(out), std::move(subprovider));
#     604                 :            : 
#     605                 :     555545 :         std::vector<CPubKey> pubkeys;
#     606                 :     555545 :         pubkeys.reserve(entries.size());
#     607         [ +  + ]:     555545 :         for (auto& entry : entries) {
#     608                 :     510693 :             pubkeys.push_back(entry.first);
#     609                 :     510693 :             out.origins.emplace(entry.first.GetID(), std::make_pair<CPubKey, KeyOriginInfo>(CPubKey(entry.first), std::move(entry.second)));
#     610                 :     510693 :         }
#     611                 :            : 
#     612                 :     555545 :         output_scripts = MakeScripts(pubkeys, MakeSpan(subscripts), out);
#     613                 :     555545 :         return true;
#     614                 :     556011 :     }
#     615                 :            : 
#     616                 :            :     bool Expand(int pos, const SigningProvider& provider, std::vector<CScript>& output_scripts, FlatSigningProvider& out, DescriptorCache* write_cache = nullptr) const final
#     617                 :     211365 :     {
#     618                 :     211365 :         return ExpandHelper(pos, provider, nullptr, output_scripts, out, write_cache);
#     619                 :     211365 :     }
#     620                 :            : 
#     621                 :            :     bool ExpandFromCache(int pos, const DescriptorCache& read_cache, std::vector<CScript>& output_scripts, FlatSigningProvider& out) const final
#     622                 :     315782 :     {
#     623                 :     315782 :         return ExpandHelper(pos, DUMMY_SIGNING_PROVIDER, &read_cache, output_scripts, out, nullptr);
#     624                 :     315782 :     }
#     625                 :            : 
#     626                 :            :     void ExpandPrivate(int pos, const SigningProvider& provider, FlatSigningProvider& out) const final
#     627                 :       7402 :     {
#     628         [ +  + ]:       7532 :         for (const auto& p : m_pubkey_args) {
#     629                 :       7532 :             CKey key;
#     630         [ +  + ]:       7532 :             if (!p->GetPrivKey(pos, provider, key)) continue;
#     631                 :       7223 :             out.keys.emplace(key.GetPubKey().GetID(), key);
#     632                 :       7223 :         }
#     633         [ +  + ]:       7402 :         for (const auto& arg : m_subdescriptor_args) {
#     634                 :        104 :             arg->ExpandPrivate(pos, provider, out);
#     635                 :        104 :         }
#     636                 :       7402 :     }
#     637                 :            : 
#     638                 :        104 :     std::optional<OutputType> GetOutputType() const override { return std::nullopt; }
#     639                 :            : };
#     640                 :            : 
#     641                 :            : /** A parsed addr(A) descriptor. */
#     642                 :            : class AddressDescriptor final : public DescriptorImpl
#     643                 :            : {
#     644                 :            :     const CTxDestination m_destination;
#     645                 :            : protected:
#     646                 :         63 :     std::string ToStringExtra() const override { return EncodeDestination(m_destination); }
#     647                 :      32307 :     std::vector<CScript> MakeScripts(const std::vector<CPubKey>&, Span<const CScript>, FlatSigningProvider&) const override { return Vector(GetScriptForDestination(m_destination)); }
#     648                 :            : public:
#     649                 :      32305 :     AddressDescriptor(CTxDestination destination) : DescriptorImpl({}, "addr"), m_destination(std::move(destination)) {}
#     650                 :          0 :     bool IsSolvable() const final { return false; }
#     651                 :            : 
#     652                 :            :     std::optional<OutputType> GetOutputType() const override
#     653                 :          0 :     {
#     654                 :          0 :         switch (m_destination.index()) {
#     655         [ #  # ]:          0 :             case 1 /* PKHash */:
#     656         [ #  # ]:          0 :             case 2 /* ScriptHash */: return OutputType::LEGACY;
#     657         [ #  # ]:          0 :             case 3 /* WitnessV0ScriptHash */:
#     658         [ #  # ]:          0 :             case 4 /* WitnessV0KeyHash */:
#     659         [ #  # ]:          0 :             case 5 /* WitnessUnknown */: return OutputType::BECH32;
#     660         [ #  # ]:          0 :             case 0 /* CNoDestination */:
#     661         [ #  # ]:          0 :             default: return std::nullopt;
#     662                 :          0 :         }
#     663                 :          0 :     }
#     664                 :          0 :     bool IsSingleType() const final { return true; }
#     665                 :            : };
#     666                 :            : 
#     667                 :            : /** A parsed raw(H) descriptor. */
#     668                 :            : class RawDescriptor final : public DescriptorImpl
#     669                 :            : {
#     670                 :            :     const CScript m_script;
#     671                 :            : protected:
#     672                 :          4 :     std::string ToStringExtra() const override { return HexStr(m_script); }
#     673                 :      74791 :     std::vector<CScript> MakeScripts(const std::vector<CPubKey>&, Span<const CScript>, FlatSigningProvider&) const override { return Vector(m_script); }
#     674                 :            : public:
#     675                 :      74795 :     RawDescriptor(CScript script) : DescriptorImpl({}, "raw"), m_script(std::move(script)) {}
#     676                 :          0 :     bool IsSolvable() const final { return false; }
#     677                 :            : 
#     678                 :            :     std::optional<OutputType> GetOutputType() const override
#     679                 :          0 :     {
#     680                 :          0 :         CTxDestination dest;
#     681                 :          0 :         ExtractDestination(m_script, dest);
#     682                 :          0 :         switch (dest.index()) {
#     683         [ #  # ]:          0 :             case 1 /* PKHash */:
#     684         [ #  # ]:          0 :             case 2 /* ScriptHash */: return OutputType::LEGACY;
#     685         [ #  # ]:          0 :             case 3 /* WitnessV0ScriptHash */:
#     686         [ #  # ]:          0 :             case 4 /* WitnessV0KeyHash */:
#     687         [ #  # ]:          0 :             case 5 /* WitnessUnknown */: return OutputType::BECH32;
#     688         [ #  # ]:          0 :             case 0 /* CNoDestination */:
#     689         [ #  # ]:          0 :             default: return std::nullopt;
#     690                 :          0 :         }
#     691                 :          0 :     }
#     692                 :          0 :     bool IsSingleType() const final { return true; }
#     693                 :            : };
#     694                 :            : 
#     695                 :            : /** A parsed pk(P) descriptor. */
#     696                 :            : class PKDescriptor final : public DescriptorImpl
#     697                 :            : {
#     698                 :            : protected:
#     699                 :       2683 :     std::vector<CScript> MakeScripts(const std::vector<CPubKey>& keys, Span<const CScript>, FlatSigningProvider&) const override { return Vector(GetScriptForRawPubKey(keys[0])); }
#     700                 :            : public:
#     701                 :      22177 :     PKDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Vector(std::move(prov)), "pk") {}
#     702                 :          1 :     bool IsSingleType() const final { return true; }
#     703                 :            : };
#     704                 :            : 
#     705                 :            : /** A parsed pkh(P) descriptor. */
#     706                 :            : class PKHDescriptor final : public DescriptorImpl
#     707                 :            : {
#     708                 :            : protected:
#     709                 :            :     std::vector<CScript> MakeScripts(const std::vector<CPubKey>& keys, Span<const CScript>, FlatSigningProvider& out) const override
#     710                 :      42482 :     {
#     711                 :      42482 :         CKeyID id = keys[0].GetID();
#     712                 :      42482 :         out.pubkeys.emplace(id, keys[0]);
#     713                 :      42482 :         return Vector(GetScriptForDestination(PKHash(id)));
#     714                 :      42482 :     }
#     715                 :            : public:
#     716                 :      77785 :     PKHDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Vector(std::move(prov)), "pkh") {}
#     717                 :        584 :     std::optional<OutputType> GetOutputType() const override { return OutputType::LEGACY; }
#     718                 :       4189 :     bool IsSingleType() const final { return true; }
#     719                 :            : };
#     720                 :            : 
#     721                 :            : /** A parsed wpkh(P) descriptor. */
#     722                 :            : class WPKHDescriptor final : public DescriptorImpl
#     723                 :            : {
#     724                 :            : protected:
#     725                 :            :     std::vector<CScript> MakeScripts(const std::vector<CPubKey>& keys, Span<const CScript>, FlatSigningProvider& out) const override
#     726                 :     267918 :     {
#     727                 :     267918 :         CKeyID id = keys[0].GetID();
#     728                 :     267918 :         out.pubkeys.emplace(id, keys[0]);
#     729                 :     267918 :         return Vector(GetScriptForDestination(WitnessV0KeyHash(id)));
#     730                 :     267918 :     }
#     731                 :            : public:
#     732                 :      98093 :     WPKHDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Vector(std::move(prov)), "wpkh") {}
#     733                 :      10385 :     std::optional<OutputType> GetOutputType() const override { return OutputType::BECH32; }
#     734                 :       9906 :     bool IsSingleType() const final { return true; }
#     735                 :            : };
#     736                 :            : 
#     737                 :            : /** A parsed combo(P) descriptor. */
#     738                 :            : class ComboDescriptor final : public DescriptorImpl
#     739                 :            : {
#     740                 :            : protected:
#     741                 :            :     std::vector<CScript> MakeScripts(const std::vector<CPubKey>& keys, Span<const CScript>, FlatSigningProvider& out) const override
#     742                 :      87903 :     {
#     743                 :      87903 :         std::vector<CScript> ret;
#     744                 :      87903 :         CKeyID id = keys[0].GetID();
#     745                 :      87903 :         out.pubkeys.emplace(id, keys[0]);
#     746                 :      87903 :         ret.emplace_back(GetScriptForRawPubKey(keys[0])); // P2PK
#     747                 :      87903 :         ret.emplace_back(GetScriptForDestination(PKHash(id))); // P2PKH
#     748         [ +  + ]:      87903 :         if (keys[0].IsCompressed()) {
#     749                 :      87854 :             CScript p2wpkh = GetScriptForDestination(WitnessV0KeyHash(id));
#     750                 :      87854 :             out.scripts.emplace(CScriptID(p2wpkh), p2wpkh);
#     751                 :      87854 :             ret.emplace_back(p2wpkh);
#     752                 :      87854 :             ret.emplace_back(GetScriptForDestination(ScriptHash(p2wpkh))); // P2SH-P2WPKH
#     753                 :      87854 :         }
#     754                 :      87903 :         return ret;
#     755                 :      87903 :     }
#     756                 :            : public:
#     757                 :        209 :     ComboDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Vector(std::move(prov)), "combo") {}
#     758                 :          1 :     bool IsSingleType() const final { return false; }
#     759                 :            : };
#     760                 :            : 
#     761                 :            : /** A parsed multi(...) or sortedmulti(...) descriptor */
#     762                 :            : class MultisigDescriptor final : public DescriptorImpl
#     763                 :            : {
#     764                 :            :     const int m_threshold;
#     765                 :            :     const bool m_sorted;
#     766                 :            : protected:
#     767                 :       3095 :     std::string ToStringExtra() const override { return strprintf("%i", m_threshold); }
#     768                 :      17066 :     std::vector<CScript> MakeScripts(const std::vector<CPubKey>& keys, Span<const CScript>, FlatSigningProvider&) const override {
#     769         [ +  + ]:      17066 :         if (m_sorted) {
#     770                 :       2169 :             std::vector<CPubKey> sorted_keys(keys);
#     771                 :       2169 :             std::sort(sorted_keys.begin(), sorted_keys.end());
#     772                 :       2169 :             return Vector(GetScriptForMultisig(m_threshold, sorted_keys));
#     773                 :       2169 :         }
#     774                 :      14897 :         return Vector(GetScriptForMultisig(m_threshold, keys));
#     775                 :      14897 :     }
#     776                 :            : public:
#     777                 :       3335 :     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) {}
#     778                 :          0 :     bool IsSingleType() const final { return true; }
#     779                 :            : };
#     780                 :            : 
#     781                 :            : /** A parsed sh(...) descriptor. */
#     782                 :            : class SHDescriptor final : public DescriptorImpl
#     783                 :            : {
#     784                 :            : protected:
#     785                 :            :     std::vector<CScript> MakeScripts(const std::vector<CPubKey>&, Span<const CScript> scripts, FlatSigningProvider& out) const override
#     786                 :      15992 :     {
#     787                 :      15992 :         auto ret = Vector(GetScriptForDestination(ScriptHash(scripts[0])));
#     788         [ +  - ]:      15992 :         if (ret.size()) out.scripts.emplace(CScriptID(scripts[0]), scripts[0]);
#     789                 :      15992 :         return ret;
#     790                 :      15992 :     }
#     791                 :            : public:
#     792                 :      24529 :     SHDescriptor(std::unique_ptr<DescriptorImpl> desc) : DescriptorImpl({}, std::move(desc), "sh") {}
#     793                 :            : 
#     794                 :            :     std::optional<OutputType> GetOutputType() const override
#     795                 :        532 :     {
#     796                 :        532 :         assert(m_subdescriptor_args.size() == 1);
#     797         [ +  + ]:        532 :         if (m_subdescriptor_args[0]->GetOutputType() == OutputType::BECH32) return OutputType::P2SH_SEGWIT;
#     798                 :         62 :         return OutputType::LEGACY;
#     799                 :         62 :     }
#     800                 :        432 :     bool IsSingleType() const final { return true; }
#     801                 :            : };
#     802                 :            : 
#     803                 :            : /** A parsed wsh(...) descriptor. */
#     804                 :            : class WSHDescriptor final : public DescriptorImpl
#     805                 :            : {
#     806                 :            : protected:
#     807                 :            :     std::vector<CScript> MakeScripts(const std::vector<CPubKey>&, Span<const CScript> scripts, FlatSigningProvider& out) const override
#     808                 :      14403 :     {
#     809                 :      14403 :         auto ret = Vector(GetScriptForDestination(WitnessV0ScriptHash(scripts[0])));
#     810         [ +  - ]:      14403 :         if (ret.size()) out.scripts.emplace(CScriptID(scripts[0]), scripts[0]);
#     811                 :      14403 :         return ret;
#     812                 :      14403 :     }
#     813                 :            : public:
#     814                 :       2981 :     WSHDescriptor(std::unique_ptr<DescriptorImpl> desc) : DescriptorImpl({}, std::move(desc), "wsh") {}
#     815                 :         82 :     std::optional<OutputType> GetOutputType() const override { return OutputType::BECH32; }
#     816                 :         33 :     bool IsSingleType() const final { return true; }
#     817                 :            : };
#     818                 :            : 
#     819                 :            : ////////////////////////////////////////////////////////////////////////////
#     820                 :            : // Parser                                                                 //
#     821                 :            : ////////////////////////////////////////////////////////////////////////////
#     822                 :            : 
#     823                 :            : enum class ParseScriptContext {
#     824                 :            :     TOP,     //!< Top-level context (script goes directly in scriptPubKey)
#     825                 :            :     P2SH,    //!< Inside sh() (script becomes P2SH redeemScript)
#     826                 :            :     P2WPKH,  //!< Inside wpkh() (no script, pubkey only)
#     827                 :            :     P2WSH,   //!< Inside wsh() (script becomes v0 witness script)
#     828                 :            : };
#     829                 :            : 
#     830                 :            : /** Parse a key path, being passed a split list of elements (the first element is ignored). */
#     831                 :            : [[nodiscard]] bool ParseKeyPath(const std::vector<Span<const char>>& split, KeyPath& out, std::string& error)
#     832                 :       2527 : {
#     833         [ +  + ]:      10904 :     for (size_t i = 1; i < split.size(); ++i) {
#     834                 :       8385 :         Span<const char> elem = split[i];
#     835                 :       8385 :         bool hardened = false;
#     836 [ +  - ][ +  + ]:       8385 :         if (elem.size() > 0 && (elem[elem.size() - 1] == '\'' || elem[elem.size() - 1] == 'h')) {
#                 [ +  + ]
#     837                 :       6132 :             elem = elem.first(elem.size() - 1);
#     838                 :       6132 :             hardened = true;
#     839                 :       6132 :         }
#     840                 :       8385 :         uint32_t p;
#     841         [ +  + ]:       8385 :         if (!ParseUInt32(std::string(elem.begin(), elem.end()), &p)) {
#     842                 :          4 :             error = strprintf("Key path value '%s' is not a valid uint32", std::string(elem.begin(), elem.end()));
#     843                 :          4 :             return false;
#     844         [ +  + ]:       8381 :         } else if (p > 0x7FFFFFFFUL) {
#     845                 :          4 :             error = strprintf("Key path value %u is out of range", p);
#     846                 :          4 :             return false;
#     847                 :          4 :         }
#     848                 :       8377 :         out.push_back(p | (((uint32_t)hardened) << 31));
#     849                 :       8377 :     }
#     850                 :       2527 :     return true;
#     851                 :       2527 : }
#     852                 :            : 
#     853                 :            : /** Parse a public key that excludes origin information. */
#     854                 :            : std::unique_ptr<PubkeyProvider> ParsePubkeyInner(uint32_t key_exp_index, const Span<const char>& sp, ParseScriptContext ctx, FlatSigningProvider& out, std::string& error)
#     855                 :       3494 : {
#     856                 :       3494 :     using namespace spanparsing;
#     857                 :            : 
#     858 [ +  + ][ +  + ]:       3494 :     bool permit_uncompressed = ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH;
#     859                 :       3494 :     auto split = Split(sp, '/');
#     860                 :       3494 :     std::string str(split[0].begin(), split[0].end());
#     861         [ +  + ]:       3494 :     if (str.size() == 0) {
#     862                 :          4 :         error = "No key provided";
#     863                 :          4 :         return nullptr;
#     864                 :          4 :     }
#     865         [ +  + ]:       3490 :     if (split.size() == 1) {
#     866         [ +  + ]:       1698 :         if (IsHex(str)) {
#     867                 :       1297 :             std::vector<unsigned char> data = ParseHex(str);
#     868                 :       1297 :             CPubKey pubkey(data);
#     869         [ +  + ]:       1297 :             if (pubkey.IsFullyValid()) {
#     870 [ +  + ][ +  + ]:       1295 :                 if (permit_uncompressed || pubkey.IsCompressed()) {
#     871                 :       1289 :                     return std::make_unique<ConstPubkeyProvider>(key_exp_index, pubkey);
#     872                 :       1289 :                 } else {
#     873                 :          6 :                     error = "Uncompressed keys are not allowed";
#     874                 :          6 :                     return nullptr;
#     875                 :          6 :                 }
#     876                 :          2 :             }
#     877                 :          2 :             error = strprintf("Pubkey '%s' is invalid", str);
#     878                 :          2 :             return nullptr;
#     879                 :          2 :         }
#     880                 :        401 :         CKey key = DecodeSecret(str);
#     881         [ +  + ]:        401 :         if (key.IsValid()) {
#     882 [ +  + ][ +  + ]:        345 :             if (permit_uncompressed || key.IsCompressed()) {
#     883                 :        339 :                 CPubKey pubkey = key.GetPubKey();
#     884                 :        339 :                 out.keys.emplace(pubkey.GetID(), key);
#     885                 :        339 :                 return std::make_unique<ConstPubkeyProvider>(key_exp_index, pubkey);
#     886                 :        339 :             } else {
#     887                 :          6 :                 error = "Uncompressed keys are not allowed";
#     888                 :          6 :                 return nullptr;
#     889                 :          6 :             }
#     890                 :       1848 :         }
#     891                 :        401 :     }
#     892                 :       1848 :     CExtKey extkey = DecodeExtKey(str);
#     893                 :       1848 :     CExtPubKey extpubkey = DecodeExtPubKey(str);
#     894 [ +  + ][ +  + ]:       1848 :     if (!extkey.key.IsValid() && !extpubkey.pubkey.IsValid()) {
#     895                 :          2 :         error = strprintf("key '%s' is not valid", str);
#     896                 :          2 :         return nullptr;
#     897                 :          2 :     }
#     898                 :       1846 :     KeyPath path;
#     899                 :       1846 :     DeriveType type = DeriveType::NO;
#     900         [ +  + ]:       1846 :     if (split.back() == MakeSpan("*").first(1)) {
#     901                 :       1593 :         split.pop_back();
#     902                 :       1593 :         type = DeriveType::UNHARDENED;
#     903 [ +  + ][ +  + ]:       1593 :     } else if (split.back() == MakeSpan("*'").first(2) || split.back() == MakeSpan("*h").first(2)) {
#                 [ +  + ]
#     904                 :         58 :         split.pop_back();
#     905                 :         58 :         type = DeriveType::HARDENED;
#     906                 :         58 :     }
#     907         [ +  + ]:       1846 :     if (!ParseKeyPath(split, path, error)) return nullptr;
#     908         [ +  + ]:       1838 :     if (extkey.key.IsValid()) {
#     909                 :        265 :         extpubkey = extkey.Neuter();
#     910                 :        265 :         out.keys.emplace(extpubkey.pubkey.GetID(), extkey.key);
#     911                 :        265 :     }
#     912                 :       1838 :     return std::make_unique<BIP32PubkeyProvider>(key_exp_index, extpubkey, std::move(path), type);
#     913                 :       1838 : }
#     914                 :            : 
#     915                 :            : /** Parse a public key including origin information (if enabled). */
#     916                 :            : std::unique_ptr<PubkeyProvider> ParsePubkey(uint32_t key_exp_index, const Span<const char>& sp, ParseScriptContext ctx, FlatSigningProvider& out, std::string& error)
#     917                 :       3522 : {
#     918                 :       3522 :     using namespace spanparsing;
#     919                 :            : 
#     920                 :       3522 :     auto origin_split = Split(sp, ']');
#     921         [ +  + ]:       3522 :     if (origin_split.size() > 2) {
#     922                 :          8 :         error = "Multiple ']' characters found for a single pubkey";
#     923                 :          8 :         return nullptr;
#     924                 :          8 :     }
#     925         [ +  + ]:       3514 :     if (origin_split.size() == 1) return ParsePubkeyInner(key_exp_index, origin_split[0], ctx, out, error);
#     926 [ -  + ][ +  + ]:        701 :     if (origin_split[0].empty() || origin_split[0][0] != '[') {
#     927                 :          4 :         error = strprintf("Key origin start '[ character expected but not found, got '%c' instead",
#     928         [ -  + ]:          4 :                           origin_split[0].empty() ? /** empty, implies split char */ ']' : origin_split[0][0]);
#     929                 :          4 :         return nullptr;
#     930                 :          4 :     }
#     931                 :        697 :     auto slash_split = Split(origin_split[0].subspan(1), '/');
#     932         [ +  + ]:        697 :     if (slash_split[0].size() != 8) {
#     933                 :         12 :         error = strprintf("Fingerprint is not 4 bytes (%u characters instead of 8 characters)", slash_split[0].size());
#     934                 :         12 :         return nullptr;
#     935                 :         12 :     }
#     936                 :        685 :     std::string fpr_hex = std::string(slash_split[0].begin(), slash_split[0].end());
#     937         [ +  + ]:        685 :     if (!IsHex(fpr_hex)) {
#     938                 :          4 :         error = strprintf("Fingerprint '%s' is not hex", fpr_hex);
#     939                 :          4 :         return nullptr;
#     940                 :          4 :     }
#     941                 :        681 :     auto fpr_bytes = ParseHex(fpr_hex);
#     942                 :        681 :     KeyOriginInfo info;
#     943                 :        681 :     static_assert(sizeof(info.fingerprint) == 4, "Fingerprint must be 4 bytes");
#     944                 :        681 :     assert(fpr_bytes.size() == 4);
#     945                 :        681 :     std::copy(fpr_bytes.begin(), fpr_bytes.end(), info.fingerprint);
#     946         [ -  + ]:        681 :     if (!ParseKeyPath(slash_split, info.path, error)) return nullptr;
#     947                 :        681 :     auto provider = ParsePubkeyInner(key_exp_index, origin_split[1], ctx, out, error);
#     948         [ +  + ]:        681 :     if (!provider) return nullptr;
#     949                 :        677 :     return std::make_unique<OriginPubkeyProvider>(key_exp_index, std::move(info), std::move(provider));
#     950                 :        677 : }
#     951                 :            : 
#     952                 :            : /** Parse a script in a particular context. */
#     953                 :            : std::unique_ptr<DescriptorImpl> ParseScript(uint32_t& key_exp_index, Span<const char>& sp, ParseScriptContext ctx, FlatSigningProvider& out, std::string& error)
#     954                 :       3836 : {
#     955                 :       3836 :     using namespace spanparsing;
#     956                 :            : 
#     957                 :       3836 :     auto expr = Expr(sp);
#     958                 :       3836 :     bool sorted_multi = false;
#     959         [ +  + ]:       3836 :     if (Func("pk", expr)) {
#     960                 :         33 :         auto pubkey = ParsePubkey(key_exp_index, expr, ctx, out, error);
#     961         [ +  + ]:         33 :         if (!pubkey) return nullptr;
#     962                 :         29 :         ++key_exp_index;
#     963                 :         29 :         return std::make_unique<PKDescriptor>(std::move(pubkey));
#     964                 :         29 :     }
#     965         [ +  + ]:       3803 :     if (Func("pkh", expr)) {
#     966                 :        633 :         auto pubkey = ParsePubkey(key_exp_index, expr, ctx, out, error);
#     967         [ +  + ]:        633 :         if (!pubkey) return nullptr;
#     968                 :        617 :         ++key_exp_index;
#     969                 :        617 :         return std::make_unique<PKHDescriptor>(std::move(pubkey));
#     970                 :        617 :     }
#     971 [ +  + ][ +  + ]:       3170 :     if (ctx == ParseScriptContext::TOP && Func("combo", expr)) {
#                 [ +  + ]
#     972                 :        213 :         auto pubkey = ParsePubkey(key_exp_index, expr, ctx, out, error);
#     973         [ +  + ]:        213 :         if (!pubkey) return nullptr;
#     974                 :        209 :         ++key_exp_index;
#     975                 :        209 :         return std::make_unique<ComboDescriptor>(std::move(pubkey));
#     976         [ +  + ]:       2957 :     } else if (Func("combo", expr)) {
#     977                 :          4 :         error = "Can only have combo() at top level";
#     978                 :          4 :         return nullptr;
#     979                 :          4 :     }
#     980 [ +  + ][ +  + ]:       2953 :     if ((sorted_multi = Func("sortedmulti", expr)) || Func("multi", expr)) {
#                 [ +  + ]
#     981                 :        413 :         auto threshold = Expr(expr);
#     982                 :        413 :         uint32_t thres;
#     983                 :        413 :         std::vector<std::unique_ptr<PubkeyProvider>> providers;
#     984         [ +  + ]:        413 :         if (!ParseUInt32(std::string(threshold.begin(), threshold.end()), &thres)) {
#     985                 :          4 :             error = strprintf("Multi threshold '%s' is not valid", std::string(threshold.begin(), threshold.end()));
#     986                 :          4 :             return nullptr;
#     987                 :          4 :         }
#     988                 :        409 :         size_t script_size = 0;
#     989         [ +  + ]:       1756 :         while (expr.size()) {
#     990         [ -  + ]:       1367 :             if (!Const(",", expr)) {
#     991                 :          0 :                 error = strprintf("Multi: expected ',', got '%c'", expr[0]);
#     992                 :          0 :                 return nullptr;
#     993                 :          0 :             }
#     994                 :       1367 :             auto arg = Expr(expr);
#     995                 :       1367 :             auto pk = ParsePubkey(key_exp_index, arg, ctx, out, error);
#     996         [ +  + ]:       1367 :             if (!pk) return nullptr;
#     997                 :       1347 :             script_size += pk->GetSize() + 1;
#     998                 :       1347 :             providers.emplace_back(std::move(pk));
#     999                 :       1347 :             key_exp_index++;
#    1000                 :       1347 :         }
#    1001 [ -  + ][ -  + ]:        409 :         if (providers.empty() || providers.size() > MAX_PUBKEYS_PER_MULTISIG) {
#    1002                 :          0 :             error = strprintf("Cannot have %u keys in multisig; must have between 1 and %d keys, inclusive", providers.size(), MAX_PUBKEYS_PER_MULTISIG);
#    1003                 :          0 :             return nullptr;
#    1004         [ +  + ]:        389 :         } else if (thres < 1) {
#    1005                 :          4 :             error = strprintf("Multisig threshold cannot be %d, must be at least 1", thres);
#    1006                 :          4 :             return nullptr;
#    1007         [ +  + ]:        385 :         } else if (thres > providers.size()) {
#    1008                 :          4 :             error = strprintf("Multisig threshold cannot be larger than the number of keys; threshold is %d but only %u keys specified", thres, providers.size());
#    1009                 :          4 :             return nullptr;
#    1010                 :          4 :         }
#    1011         [ +  + ]:        381 :         if (ctx == ParseScriptContext::TOP) {
#    1012         [ +  + ]:         26 :             if (providers.size() > 3) {
#    1013                 :          4 :                 error = strprintf("Cannot have %u pubkeys in bare multisig; only at most 3 pubkeys", providers.size());
#    1014                 :          4 :                 return nullptr;
#    1015                 :          4 :             }
#    1016                 :        377 :         }
#    1017         [ +  + ]:        377 :         if (ctx == ParseScriptContext::P2SH) {
#    1018                 :            :             // This limits the maximum number of compressed pubkeys to 15.
#    1019         [ +  + ]:        151 :             if (script_size + 3 > MAX_SCRIPT_ELEMENT_SIZE) {
#    1020                 :          8 :                 error = strprintf("P2SH script is too large, %d bytes is larger than %d bytes", script_size + 3, MAX_SCRIPT_ELEMENT_SIZE);
#    1021                 :          8 :                 return nullptr;
#    1022                 :          8 :             }
#    1023                 :        369 :         }
#    1024                 :        369 :         return std::make_unique<MultisigDescriptor>(thres, std::move(providers), sorted_multi);
#    1025                 :        369 :     }
#    1026 [ +  + ][ +  + ]:       2540 :     if ((ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH) && Func("wpkh", expr)) {
#         [ +  + ][ +  + ]
#    1027                 :       1276 :         auto pubkey = ParsePubkey(key_exp_index, expr, ParseScriptContext::P2WPKH, out, error);
#    1028         [ +  + ]:       1276 :         if (!pubkey) return nullptr;
#    1029                 :       1264 :         key_exp_index++;
#    1030                 :       1264 :         return std::make_unique<WPKHDescriptor>(std::move(pubkey));
#    1031         [ +  + ]:       1264 :     } else if (Func("wpkh", expr)) {
#    1032                 :          4 :         error = "Can only have wpkh() at top level or inside sh()";
#    1033                 :          4 :         return nullptr;
#    1034                 :          4 :     }
#    1035 [ +  + ][ +  + ]:       1260 :     if (ctx == ParseScriptContext::TOP && Func("sh", expr)) {
#                 [ +  + ]
#    1036                 :        930 :         auto desc = ParseScript(key_exp_index, expr, ParseScriptContext::P2SH, out, error);
#    1037 [ +  + ][ -  + ]:        930 :         if (!desc || expr.size()) return nullptr;
#    1038                 :        902 :         return std::make_unique<SHDescriptor>(std::move(desc));
#    1039         [ +  + ]:        902 :     } else if (Func("sh", expr)) {
#    1040                 :          8 :         error = "Can only have sh() at top level";
#    1041                 :          8 :         return nullptr;
#    1042                 :          8 :     }
#    1043 [ +  + ][ +  + ]:        322 :     if ((ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH) && Func("wsh", expr)) {
#         [ +  + ][ +  + ]
#    1044                 :        262 :         auto desc = ParseScript(key_exp_index, expr, ParseScriptContext::P2WSH, out, error);
#    1045 [ +  + ][ -  + ]:        262 :         if (!desc || expr.size()) return nullptr;
#    1046                 :        222 :         return std::make_unique<WSHDescriptor>(std::move(desc));
#    1047         [ +  + ]:        222 :     } else if (Func("wsh", expr)) {
#    1048                 :          4 :         error = "Can only have wsh() at top level or inside sh()";
#    1049                 :          4 :         return nullptr;
#    1050                 :          4 :     }
#    1051 [ +  + ][ +  + ]:         56 :     if (ctx == ParseScriptContext::TOP && Func("addr", expr)) {
#                 [ +  + ]
#    1052                 :         16 :         CTxDestination dest = DecodeDestination(std::string(expr.begin(), expr.end()));
#    1053         [ +  + ]:         16 :         if (!IsValidDestination(dest)) {
#    1054                 :          4 :             error = "Address is not valid";
#    1055                 :          4 :             return nullptr;
#    1056                 :          4 :         }
#    1057                 :         12 :         return std::make_unique<AddressDescriptor>(std::move(dest));
#    1058         [ -  + ]:         40 :     } else if (Func("addr", expr)) {
#    1059                 :          0 :         error = "Can only have addr() at top level";
#    1060                 :          0 :         return nullptr;
#    1061                 :          0 :     }
#    1062 [ +  + ][ +  + ]:         40 :     if (ctx == ParseScriptContext::TOP && Func("raw", expr)) {
#                 [ +  + ]
#    1063                 :         16 :         std::string str(expr.begin(), expr.end());
#    1064         [ +  + ]:         16 :         if (!IsHex(str)) {
#    1065                 :          2 :             error = "Raw script is not hex";
#    1066                 :          2 :             return nullptr;
#    1067                 :          2 :         }
#    1068                 :         14 :         auto bytes = ParseHex(str);
#    1069                 :         14 :         return std::make_unique<RawDescriptor>(CScript(bytes.begin(), bytes.end()));
#    1070         [ -  + ]:         24 :     } else if (Func("raw", expr)) {
#    1071                 :          0 :         error = "Can only have raw() at top level";
#    1072                 :          0 :         return nullptr;
#    1073                 :          0 :     }
#    1074         [ +  + ]:         24 :     if (ctx == ParseScriptContext::P2SH) {
#    1075                 :          4 :         error = "A function is needed within P2SH";
#    1076                 :          4 :         return nullptr;
#    1077         [ +  + ]:         20 :     } else if (ctx == ParseScriptContext::P2WSH) {
#    1078                 :          4 :         error = "A function is needed within P2WSH";
#    1079                 :          4 :         return nullptr;
#    1080                 :          4 :     }
#    1081                 :         16 :     error = strprintf("%s is not a valid descriptor function", std::string(expr.begin(), expr.end()));
#    1082                 :         16 :     return nullptr;
#    1083                 :         16 : }
#    1084                 :            : 
#    1085                 :            : std::unique_ptr<PubkeyProvider> InferPubkey(const CPubKey& pubkey, ParseScriptContext, const SigningProvider& provider)
#    1086                 :     202451 : {
#    1087                 :     202451 :     std::unique_ptr<PubkeyProvider> key_provider = std::make_unique<ConstPubkeyProvider>(0, pubkey);
#    1088                 :     202451 :     KeyOriginInfo info;
#    1089         [ +  + ]:     202451 :     if (provider.GetKeyOrigin(pubkey.GetID(), info)) {
#    1090                 :     202113 :         return std::make_unique<OriginPubkeyProvider>(0, std::move(info), std::move(key_provider));
#    1091                 :     202113 :     }
#    1092                 :        338 :     return key_provider;
#    1093                 :        338 : }
#    1094                 :            : 
#    1095                 :            : std::unique_ptr<DescriptorImpl> InferScript(const CScript& script, ParseScriptContext ctx, const SigningProvider& provider)
#    1096                 :     332571 : {
#    1097                 :     332571 :     std::vector<std::vector<unsigned char>> data;
#    1098                 :     332571 :     TxoutType txntype = Solver(script, data);
#    1099                 :            : 
#    1100         [ +  + ]:     332571 :     if (txntype == TxoutType::PUBKEY) {
#    1101                 :      22148 :         CPubKey pubkey(data[0]);
#    1102         [ +  - ]:      22148 :         if (pubkey.IsValid()) {
#    1103                 :      22148 :             return std::make_unique<PKDescriptor>(InferPubkey(pubkey, ctx, provider));
#    1104                 :      22148 :         }
#    1105                 :     310423 :     }
#    1106         [ +  + ]:     310423 :     if (txntype == TxoutType::PUBKEYHASH) {
#    1107                 :      77647 :         uint160 hash(data[0]);
#    1108                 :      77647 :         CKeyID keyid(hash);
#    1109                 :      77647 :         CPubKey pubkey;
#    1110         [ +  + ]:      77647 :         if (provider.GetPubKey(keyid, pubkey)) {
#    1111                 :      77168 :             return std::make_unique<PKHDescriptor>(InferPubkey(pubkey, ctx, provider));
#    1112                 :      77168 :         }
#    1113                 :     233255 :     }
#    1114 [ +  + ][ +  - ]:     233255 :     if (txntype == TxoutType::WITNESS_V0_KEYHASH && ctx != ParseScriptContext::P2WSH) {
#    1115                 :     124393 :         uint160 hash(data[0]);
#    1116                 :     124393 :         CKeyID keyid(hash);
#    1117                 :     124393 :         CPubKey pubkey;
#    1118         [ +  + ]:     124393 :         if (provider.GetPubKey(keyid, pubkey)) {
#    1119                 :      96829 :             return std::make_unique<WPKHDescriptor>(InferPubkey(pubkey, ctx, provider));
#    1120                 :      96829 :         }
#    1121                 :     136426 :     }
#    1122         [ +  + ]:     136426 :     if (txntype == TxoutType::MULTISIG) {
#    1123                 :       2966 :         std::vector<std::unique_ptr<PubkeyProvider>> providers;
#    1124         [ +  + ]:       9272 :         for (size_t i = 1; i + 1 < data.size(); ++i) {
#    1125                 :       6306 :             CPubKey pubkey(data[i]);
#    1126                 :       6306 :             providers.push_back(InferPubkey(pubkey, ctx, provider));
#    1127                 :       6306 :         }
#    1128                 :       2966 :         return std::make_unique<MultisigDescriptor>((int)data[0][0], std::move(providers));
#    1129                 :       2966 :     }
#    1130 [ +  + ][ +  - ]:     133460 :     if (txntype == TxoutType::SCRIPTHASH && ctx == ParseScriptContext::TOP) {
#    1131                 :      24962 :         uint160 hash(data[0]);
#    1132                 :      24962 :         CScriptID scriptid(hash);
#    1133                 :      24962 :         CScript subscript;
#    1134         [ +  + ]:      24962 :         if (provider.GetCScript(scriptid, subscript)) {
#    1135                 :      23627 :             auto sub = InferScript(subscript, ParseScriptContext::P2SH, provider);
#    1136         [ +  - ]:      23627 :             if (sub) return std::make_unique<SHDescriptor>(std::move(sub));
#    1137                 :     109833 :         }
#    1138                 :      24962 :     }
#    1139 [ +  + ][ +  - ]:     109833 :     if (txntype == TxoutType::WITNESS_V0_SCRIPTHASH && ctx != ParseScriptContext::P2WSH) {
#    1140                 :       3199 :         CScriptID scriptid;
#    1141                 :       3199 :         CRIPEMD160().Write(data[0].data(), data[0].size()).Finalize(scriptid.begin());
#    1142                 :       3199 :         CScript subscript;
#    1143         [ +  + ]:       3199 :         if (provider.GetCScript(scriptid, subscript)) {
#    1144                 :       2759 :             auto sub = InferScript(subscript, ParseScriptContext::P2WSH, provider);
#    1145         [ +  - ]:       2759 :             if (sub) return std::make_unique<WSHDescriptor>(std::move(sub));
#    1146                 :     107074 :         }
#    1147                 :       3199 :     }
#    1148                 :            : 
#    1149                 :     107074 :     CTxDestination dest;
#    1150         [ +  + ]:     107074 :     if (ExtractDestination(script, dest)) {
#    1151         [ +  - ]:      32293 :         if (GetScriptForDestination(dest) == script) {
#    1152                 :      32293 :             return std::make_unique<AddressDescriptor>(std::move(dest));
#    1153                 :      32293 :         }
#    1154                 :      74781 :     }
#    1155                 :            : 
#    1156                 :      74781 :     return std::make_unique<RawDescriptor>(script);
#    1157                 :      74781 : }
#    1158                 :            : 
#    1159                 :            : 
#    1160                 :            : } // namespace
#    1161                 :            : 
#    1162                 :            : /** Check a descriptor checksum, and update desc to be the checksum-less part. */
#    1163                 :            : bool CheckChecksum(Span<const char>& sp, bool require_checksum, std::string& error, std::string* out_checksum = nullptr)
#    1164                 :       3173 : {
#    1165                 :       3173 :     using namespace spanparsing;
#    1166                 :            : 
#    1167                 :       3173 :     auto check_split = Split(sp, '#');
#    1168         [ +  + ]:       3173 :     if (check_split.size() > 2) {
#    1169                 :          4 :         error = "Multiple '#' symbols";
#    1170                 :          4 :         return false;
#    1171                 :          4 :     }
#    1172 [ +  + ][ +  + ]:       3169 :     if (check_split.size() == 1 && require_checksum){
#    1173                 :          7 :         error = "Missing checksum";
#    1174                 :          7 :         return false;
#    1175                 :          7 :     }
#    1176         [ +  + ]:       3162 :     if (check_split.size() == 2) {
#    1177         [ +  + ]:       1514 :         if (check_split[1].size() != 8) {
#    1178                 :         12 :             error = strprintf("Expected 8 character checksum, not %u characters", check_split[1].size());
#    1179                 :         12 :             return false;
#    1180                 :         12 :         }
#    1181                 :       3150 :     }
#    1182                 :       3150 :     auto checksum = DescriptorChecksum(check_split[0]);
#    1183         [ +  + ]:       3150 :     if (checksum.empty()) {
#    1184                 :          2 :         error = "Invalid characters in payload";
#    1185                 :          2 :         return false;
#    1186                 :          2 :     }
#    1187         [ +  + ]:       3148 :     if (check_split.size() == 2) {
#    1188         [ +  + ]:       1500 :         if (!std::equal(checksum.begin(), checksum.end(), check_split[1].begin())) {
#    1189                 :         16 :             error = strprintf("Provided checksum '%s' does not match computed checksum '%s'", std::string(check_split[1].begin(), check_split[1].end()), checksum);
#    1190                 :         16 :             return false;
#    1191                 :         16 :         }
#    1192                 :       3132 :     }
#    1193         [ +  + ]:       3132 :     if (out_checksum) *out_checksum = std::move(checksum);
#    1194                 :       3132 :     sp = check_split[0];
#    1195                 :       3132 :     return true;
#    1196                 :       3132 : }
#    1197                 :            : 
#    1198                 :            : std::unique_ptr<Descriptor> Parse(const std::string& descriptor, FlatSigningProvider& out, std::string& error, bool require_checksum)
#    1199                 :       2677 : {
#    1200                 :       2677 :     Span<const char> sp{descriptor};
#    1201         [ +  + ]:       2677 :     if (!CheckChecksum(sp, require_checksum, error)) return nullptr;
#    1202                 :       2644 :     uint32_t key_exp_index = 0;
#    1203                 :       2644 :     auto ret = ParseScript(key_exp_index, sp, ParseScriptContext::TOP, out, error);
#    1204 [ +  - ][ +  + ]:       2644 :     if (sp.size() == 0 && ret) return std::unique_ptr<Descriptor>(std::move(ret));
#    1205                 :        130 :     return nullptr;
#    1206                 :        130 : }
#    1207                 :            : 
#    1208                 :            : std::string GetDescriptorChecksum(const std::string& descriptor)
#    1209                 :        496 : {
#    1210                 :        496 :     std::string ret;
#    1211                 :        496 :     std::string error;
#    1212                 :        496 :     Span<const char> sp{descriptor};
#    1213         [ +  + ]:        496 :     if (!CheckChecksum(sp, false, error, &ret)) return "";
#    1214                 :        488 :     return ret;
#    1215                 :        488 : }
#    1216                 :            : 
#    1217                 :            : std::unique_ptr<Descriptor> InferDescriptor(const CScript& script, const SigningProvider& provider)
#    1218                 :     306185 : {
#    1219                 :     306185 :     return InferScript(script, ParseScriptContext::TOP, provider);
#    1220                 :     306185 : }
#    1221                 :            : 
#    1222                 :            : void DescriptorCache::CacheParentExtPubKey(uint32_t key_exp_pos, const CExtPubKey& xpub)
#    1223                 :       2965 : {
#    1224                 :       2965 :     m_parent_xpubs[key_exp_pos] = xpub;
#    1225                 :       2965 : }
#    1226                 :            : 
#    1227                 :            : void DescriptorCache::CacheDerivedExtPubKey(uint32_t key_exp_pos, uint32_t der_index, const CExtPubKey& xpub)
#    1228                 :       1636 : {
#    1229                 :       1636 :     auto& xpubs = m_derived_xpubs[key_exp_pos];
#    1230                 :       1636 :     xpubs[der_index] = xpub;
#    1231                 :       1636 : }
#    1232                 :            : 
#    1233                 :            : bool DescriptorCache::GetCachedParentExtPubKey(uint32_t key_exp_pos, CExtPubKey& xpub) const
#    1234                 :     331386 : {
#    1235                 :     331386 :     const auto& it = m_parent_xpubs.find(key_exp_pos);
#    1236         [ +  + ]:     331386 :     if (it == m_parent_xpubs.end()) return false;
#    1237                 :     329730 :     xpub = it->second;
#    1238                 :     329730 :     return true;
#    1239                 :     329730 : }
#    1240                 :            : 
#    1241                 :            : bool DescriptorCache::GetCachedDerivedExtPubKey(uint32_t key_exp_pos, uint32_t der_index, CExtPubKey& xpub) const
#    1242                 :     333007 : {
#    1243                 :     333007 :     const auto& key_exp_it = m_derived_xpubs.find(key_exp_pos);
#    1244         [ +  + ]:     333007 :     if (key_exp_it == m_derived_xpubs.end()) return false;
#    1245                 :       2472 :     const auto& der_it = key_exp_it->second.find(der_index);
#    1246         [ +  + ]:       2472 :     if (der_it == key_exp_it->second.end()) return false;
#    1247                 :        728 :     xpub = der_it->second;
#    1248                 :        728 :     return true;
#    1249                 :        728 : }
#    1250                 :            : 
#    1251                 :            : const ExtPubKeyMap DescriptorCache::GetCachedParentExtPubKeys() const
#    1252                 :      33447 : {
#    1253                 :      33447 :     return m_parent_xpubs;
#    1254                 :      33447 : }
#    1255                 :            : 
#    1256                 :            : const std::unordered_map<uint32_t, ExtPubKeyMap> DescriptorCache::GetCachedDerivedExtPubKeys() const
#    1257                 :      33447 : {
#    1258                 :      33447 :     return m_derived_xpubs;
#    1259                 :      33447 : }

Generated by: LCOV version 1.14