LCOV - code coverage report
Current view: top level - src/script - standard.cpp (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 432 448 96.4 %
Date: 2022-04-21 14:51:19 Functions: 41 41 100.0 %
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: 251 308 81.5 %

           Branch data     Line data    Source code
#       1                 :            : // Copyright (c) 2009-2010 Satoshi Nakamoto
#       2                 :            : // Copyright (c) 2009-2021 The Bitcoin Core developers
#       3                 :            : // Distributed under the MIT software license, see the accompanying
#       4                 :            : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
#       5                 :            : 
#       6                 :            : #include <script/standard.h>
#       7                 :            : 
#       8                 :            : #include <crypto/sha256.h>
#       9                 :            : #include <hash.h>
#      10                 :            : #include <pubkey.h>
#      11                 :            : #include <script/interpreter.h>
#      12                 :            : #include <script/script.h>
#      13                 :            : #include <util/strencodings.h>
#      14                 :            : 
#      15                 :            : #include <string>
#      16                 :            : 
#      17                 :            : typedef std::vector<unsigned char> valtype;
#      18                 :            : 
#      19                 :            : bool fAcceptDatacarrier = DEFAULT_ACCEPT_DATACARRIER;
#      20                 :            : unsigned nMaxDatacarrierBytes = MAX_OP_RETURN_RELAY;
#      21                 :            : 
#      22                 :    1017760 : CScriptID::CScriptID(const CScript& in) : BaseHash(Hash160(in)) {}
#      23                 :       3524 : CScriptID::CScriptID(const ScriptHash& in) : BaseHash(static_cast<uint160>(in)) {}
#      24                 :            : 
#      25                 :     132725 : ScriptHash::ScriptHash(const CScript& in) : BaseHash(Hash160(in)) {}
#      26                 :       1437 : ScriptHash::ScriptHash(const CScriptID& in) : BaseHash(static_cast<uint160>(in)) {}
#      27                 :            : 
#      28                 :      26815 : PKHash::PKHash(const CPubKey& pubkey) : BaseHash(pubkey.GetID()) {}
#      29                 :     148868 : PKHash::PKHash(const CKeyID& pubkey_id) : BaseHash(pubkey_id) {}
#      30                 :            : 
#      31                 :      12501 : WitnessV0KeyHash::WitnessV0KeyHash(const CPubKey& pubkey) : BaseHash(pubkey.GetID()) {}
#      32                 :       1657 : WitnessV0KeyHash::WitnessV0KeyHash(const PKHash& pubkey_hash) : BaseHash(static_cast<uint160>(pubkey_hash)) {}
#      33                 :            : 
#      34                 :            : CKeyID ToKeyID(const PKHash& key_hash)
#      35                 :        652 : {
#      36                 :        652 :     return CKeyID{static_cast<uint160>(key_hash)};
#      37                 :        652 : }
#      38                 :            : 
#      39                 :            : CKeyID ToKeyID(const WitnessV0KeyHash& key_hash)
#      40                 :       1677 : {
#      41                 :       1677 :     return CKeyID{static_cast<uint160>(key_hash)};
#      42                 :       1677 : }
#      43                 :            : 
#      44                 :            : WitnessV0ScriptHash::WitnessV0ScriptHash(const CScript& in)
#      45                 :      21817 : {
#      46                 :      21817 :     CSHA256().Write(in.data(), in.size()).Finalize(begin());
#      47                 :      21817 : }
#      48                 :            : 
#      49                 :            : std::string GetTxnOutputType(TxoutType t)
#      50                 :      84551 : {
#      51         [ -  + ]:      84551 :     switch (t) {
#      52         [ +  + ]:       5760 :     case TxoutType::NONSTANDARD: return "nonstandard";
#      53         [ +  + ]:       6056 :     case TxoutType::PUBKEY: return "pubkey";
#      54         [ +  + ]:       6199 :     case TxoutType::PUBKEYHASH: return "pubkeyhash";
#      55         [ +  + ]:       6192 :     case TxoutType::SCRIPTHASH: return "scripthash";
#      56         [ +  + ]:       5930 :     case TxoutType::MULTISIG: return "multisig";
#      57         [ +  + ]:      20597 :     case TxoutType::NULL_DATA: return "nulldata";
#      58         [ +  + ]:      12440 :     case TxoutType::WITNESS_V0_KEYHASH: return "witness_v0_keyhash";
#      59         [ +  + ]:       5879 :     case TxoutType::WITNESS_V0_SCRIPTHASH: return "witness_v0_scripthash";
#      60         [ +  + ]:       9793 :     case TxoutType::WITNESS_V1_TAPROOT: return "witness_v1_taproot";
#      61         [ +  + ]:       5705 :     case TxoutType::WITNESS_UNKNOWN: return "witness_unknown";
#      62                 :      84551 :     } // no default case, so the compiler can warn about missing cases
#      63                 :          0 :     assert(false);
#      64                 :          0 : }
#      65                 :            : 
#      66                 :            : static bool MatchPayToPubkey(const CScript& script, valtype& pubkey)
#      67                 :    2192968 : {
#      68 [ +  + ][ +  - ]:    2192968 :     if (script.size() == CPubKey::SIZE + 2 && script[0] == CPubKey::SIZE && script.back() == OP_CHECKSIG) {
#                 [ +  - ]
#      69                 :       2257 :         pubkey = valtype(script.begin() + 1, script.begin() + CPubKey::SIZE + 1);
#      70                 :       2257 :         return CPubKey::ValidSize(pubkey);
#      71                 :       2257 :     }
#      72 [ +  + ][ +  - ]:    2190711 :     if (script.size() == CPubKey::COMPRESSED_SIZE + 2 && script[0] == CPubKey::COMPRESSED_SIZE && script.back() == OP_CHECKSIG) {
#                 [ +  - ]
#      73                 :      43163 :         pubkey = valtype(script.begin() + 1, script.begin() + CPubKey::COMPRESSED_SIZE + 1);
#      74                 :      43163 :         return CPubKey::ValidSize(pubkey);
#      75                 :      43163 :     }
#      76                 :    2147548 :     return false;
#      77                 :    2190711 : }
#      78                 :            : 
#      79                 :            : static bool MatchPayToPubkeyHash(const CScript& script, valtype& pubkeyhash)
#      80                 :    2147548 : {
#      81 [ +  + ][ +  - ]:    2147548 :     if (script.size() == 25 && script[0] == OP_DUP && script[1] == OP_HASH160 && script[2] == 20 && script[23] == OP_EQUALVERIFY && script[24] == OP_CHECKSIG) {
#         [ +  - ][ +  - ]
#         [ +  - ][ +  - ]
#      82                 :    2122178 :         pubkeyhash = valtype(script.begin () + 3, script.begin() + 23);
#      83                 :    2122178 :         return true;
#      84                 :    2122178 :     }
#      85                 :      25370 :     return false;
#      86                 :    2147548 : }
#      87                 :            : 
#      88                 :            : /** Test for "small positive integer" script opcodes - OP_1 through OP_16. */
#      89                 :            : static constexpr bool IsSmallInteger(opcodetype opcode)
#      90                 :      32037 : {
#      91 [ +  + ][ +  + ]:      32037 :     return opcode >= OP_1 && opcode <= OP_16;
#      92                 :      32037 : }
#      93                 :            : 
#      94                 :            : /** Retrieve a minimally-encoded number in range [min,max] from an (opcode, data) pair,
#      95                 :            :  *  whether it's OP_n or through a push. */
#      96                 :            : static std::optional<int> GetScriptNumber(opcodetype opcode, valtype data, int min, int max)
#      97                 :      32037 : {
#      98                 :      32037 :     int count;
#      99         [ +  + ]:      32037 :     if (IsSmallInteger(opcode)) {
#     100                 :      31809 :         count = CScript::DecodeOP_N(opcode);
#     101         [ +  + ]:      31809 :     } else if (IsPushdataOp(opcode)) {
#     102         [ +  + ]:        220 :         if (!CheckMinimalPush(data, opcode)) return {};
#     103                 :        212 :         try {
#     104                 :        212 :             count = CScriptNum(data, /* fRequireMinimal = */ true).getint();
#     105                 :        212 :         } catch (const scriptnum_error&) {
#     106                 :          0 :             return {};
#     107                 :          0 :         }
#     108                 :        212 :     } else {
#     109                 :          8 :         return {};
#     110                 :          8 :     }
#     111 [ +  + ][ -  + ]:      32021 :     if (count < min || count > max) return {};
#     112                 :      32017 :     return count;
#     113                 :      32021 : }
#     114                 :            : 
#     115                 :            : static bool MatchMultisig(const CScript& script, int& required_sigs, std::vector<valtype>& pubkeys)
#     116                 :      25370 : {
#     117                 :      25370 :     opcodetype opcode;
#     118                 :      25370 :     valtype data;
#     119                 :            : 
#     120                 :      25370 :     CScript::const_iterator it = script.begin();
#     121 [ +  + ][ +  + ]:      25370 :     if (script.size() < 1 || script.back() != OP_CHECKMULTISIG) return false;
#     122                 :            : 
#     123         [ -  + ]:      15953 :     if (!script.GetOp(it, opcode, data)) return false;
#     124                 :      15953 :     auto req_sigs = GetScriptNumber(opcode, data, 1, MAX_PUBKEYS_PER_MULTISIG);
#     125         [ +  + ]:      15953 :     if (!req_sigs) return false;
#     126                 :      15945 :     required_sigs = *req_sigs;
#     127 [ +  - ][ +  + ]:      49404 :     while (script.GetOp(it, opcode, data) && CPubKey::ValidSize(data)) {
#     128                 :      33459 :         pubkeys.emplace_back(std::move(data));
#     129                 :      33459 :     }
#     130                 :      15945 :     auto num_keys = GetScriptNumber(opcode, data, required_sigs, MAX_PUBKEYS_PER_MULTISIG);
#     131         [ +  + ]:      15945 :     if (!num_keys) return false;
#     132         [ +  + ]:      15933 :     if (pubkeys.size() != static_cast<unsigned long>(*num_keys)) return false;
#     133                 :            : 
#     134                 :      15927 :     return (it + 1 == script.end());
#     135                 :      15933 : }
#     136                 :            : 
#     137                 :            : std::optional<std::pair<int, std::vector<Span<const unsigned char>>>> MatchMultiA(const CScript& script)
#     138                 :        139 : {
#     139                 :        139 :     std::vector<Span<const unsigned char>> keyspans;
#     140                 :            : 
#     141                 :            :     // Redundant, but very fast and selective test.
#     142 [ -  + ][ -  + ]:        139 :     if (script.size() == 0 || script[0] != 32 || script.back() != OP_NUMEQUAL) return {};
#                 [ -  + ]
#     143                 :            : 
#     144                 :            :     // Parse keys
#     145                 :        139 :     auto it = script.begin();
#     146         [ +  + ]:      20397 :     while (script.end() - it >= 34) {
#     147         [ -  + ]:      20258 :         if (*it != 32) return {};
#     148                 :      20258 :         ++it;
#     149                 :      20258 :         keyspans.emplace_back(&*it, 32);
#     150                 :      20258 :         it += 32;
#     151 [ -  + ][ +  + ]:      20258 :         if (*it != (keyspans.size() == 1 ? OP_CHECKSIG : OP_CHECKSIGADD)) return {};
#     152                 :      20258 :         ++it;
#     153                 :      20258 :     }
#     154 [ -  + ][ -  + ]:        139 :     if (keyspans.size() == 0 || keyspans.size() > MAX_PUBKEYS_PER_MULTI_A) return {};
#     155                 :            : 
#     156                 :            :     // Parse threshold.
#     157                 :        139 :     opcodetype opcode;
#     158                 :        139 :     std::vector<unsigned char> data;
#     159         [ -  + ]:        139 :     if (!script.GetOp(it, opcode, data)) return {};
#     160         [ -  + ]:        139 :     if (it == script.end()) return {};
#     161         [ -  + ]:        139 :     if (*it != OP_NUMEQUAL) return {};
#     162                 :        139 :     ++it;
#     163         [ -  + ]:        139 :     if (it != script.end()) return {};
#     164                 :        139 :     auto threshold = GetScriptNumber(opcode, data, 1, (int)keyspans.size());
#     165         [ -  + ]:        139 :     if (!threshold) return {};
#     166                 :            : 
#     167                 :            :     // Construct result.
#     168                 :        139 :     return std::pair{*threshold, std::move(keyspans)};
#     169                 :        139 : }
#     170                 :            : 
#     171                 :            : TxoutType Solver(const CScript& scriptPubKey, std::vector<std::vector<unsigned char>>& vSolutionsRet)
#     172                 :    4746762 : {
#     173                 :    4746762 :     vSolutionsRet.clear();
#     174                 :            : 
#     175                 :            :     // Shortcut for pay-to-script-hash, which are more constrained than the other types:
#     176                 :            :     // it is always OP_HASH160 20 [20 byte hash] OP_EQUAL
#     177         [ +  + ]:    4746762 :     if (scriptPubKey.IsPayToScriptHash())
#     178                 :     147382 :     {
#     179                 :     147382 :         std::vector<unsigned char> hashBytes(scriptPubKey.begin()+2, scriptPubKey.begin()+22);
#     180                 :     147382 :         vSolutionsRet.push_back(hashBytes);
#     181                 :     147382 :         return TxoutType::SCRIPTHASH;
#     182                 :     147382 :     }
#     183                 :            : 
#     184                 :    4599380 :     int witnessversion;
#     185                 :    4599380 :     std::vector<unsigned char> witnessprogram;
#     186         [ +  + ]:    4599380 :     if (scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)) {
#     187 [ +  + ][ +  + ]:    2061916 :         if (witnessversion == 0 && witnessprogram.size() == WITNESS_V0_KEYHASH_SIZE) {
#     188                 :    1908073 :             vSolutionsRet.push_back(std::move(witnessprogram));
#     189                 :    1908073 :             return TxoutType::WITNESS_V0_KEYHASH;
#     190                 :    1908073 :         }
#     191 [ +  + ][ +  + ]:     153843 :         if (witnessversion == 0 && witnessprogram.size() == WITNESS_V0_SCRIPTHASH_SIZE) {
#     192                 :      38387 :             vSolutionsRet.push_back(std::move(witnessprogram));
#     193                 :      38387 :             return TxoutType::WITNESS_V0_SCRIPTHASH;
#     194                 :      38387 :         }
#     195 [ +  + ][ +  + ]:     115456 :         if (witnessversion == 1 && witnessprogram.size() == WITNESS_V1_TAPROOT_SIZE) {
#     196                 :     114143 :             vSolutionsRet.push_back(std::move(witnessprogram));
#     197                 :     114143 :             return TxoutType::WITNESS_V1_TAPROOT;
#     198                 :     114143 :         }
#     199         [ +  + ]:       1313 :         if (witnessversion != 0) {
#     200                 :       1310 :             vSolutionsRet.push_back(std::vector<unsigned char>{(unsigned char)witnessversion});
#     201                 :       1310 :             vSolutionsRet.push_back(std::move(witnessprogram));
#     202                 :       1310 :             return TxoutType::WITNESS_UNKNOWN;
#     203                 :       1310 :         }
#     204                 :          3 :         return TxoutType::NONSTANDARD;
#     205                 :       1313 :     }
#     206                 :            : 
#     207                 :            :     // Provably prunable, data-carrying output
#     208                 :            :     //
#     209                 :            :     // So long as script passes the IsUnspendable() test and all but the first
#     210                 :            :     // byte passes the IsPushOnly() test we don't care what exactly is in the
#     211                 :            :     // script.
#     212 [ +  + ][ +  + ]:    2537464 :     if (scriptPubKey.size() >= 1 && scriptPubKey[0] == OP_RETURN && scriptPubKey.IsPushOnly(scriptPubKey.begin()+1)) {
#         [ +  + ][ +  + ]
#     213                 :     344505 :         return TxoutType::NULL_DATA;
#     214                 :     344505 :     }
#     215                 :            : 
#     216                 :    2192959 :     std::vector<unsigned char> data;
#     217         [ +  + ]:    2192959 :     if (MatchPayToPubkey(scriptPubKey, data)) {
#     218                 :      45420 :         vSolutionsRet.push_back(std::move(data));
#     219                 :      45420 :         return TxoutType::PUBKEY;
#     220                 :      45420 :     }
#     221                 :            : 
#     222         [ +  + ]:    2147539 :     if (MatchPayToPubkeyHash(scriptPubKey, data)) {
#     223                 :    2122178 :         vSolutionsRet.push_back(std::move(data));
#     224                 :    2122178 :         return TxoutType::PUBKEYHASH;
#     225                 :    2122178 :     }
#     226                 :            : 
#     227                 :      25361 :     int required;
#     228                 :      25361 :     std::vector<std::vector<unsigned char>> keys;
#     229         [ +  + ]:      25361 :     if (MatchMultisig(scriptPubKey, required, keys)) {
#     230                 :      15927 :         vSolutionsRet.push_back({static_cast<unsigned char>(required)}); // safe as required is in range 1..20
#     231                 :      15927 :         vSolutionsRet.insert(vSolutionsRet.end(), keys.begin(), keys.end());
#     232                 :      15927 :         vSolutionsRet.push_back({static_cast<unsigned char>(keys.size())}); // safe as size is in range 1..20
#     233                 :      15927 :         return TxoutType::MULTISIG;
#     234                 :      15927 :     }
#     235                 :            : 
#     236                 :       9434 :     vSolutionsRet.clear();
#     237                 :       9434 :     return TxoutType::NONSTANDARD;
#     238                 :      25361 : }
#     239                 :            : 
#     240                 :            : bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet)
#     241                 :     607614 : {
#     242                 :     607614 :     std::vector<valtype> vSolutions;
#     243                 :     607614 :     TxoutType whichType = Solver(scriptPubKey, vSolutions);
#     244                 :            : 
#     245         [ -  + ]:     607614 :     switch (whichType) {
#     246         [ +  + ]:       2086 :     case TxoutType::PUBKEY: {
#     247                 :       2086 :         CPubKey pubKey(vSolutions[0]);
#     248         [ -  + ]:       2086 :         if (!pubKey.IsValid())
#     249                 :          0 :             return false;
#     250                 :            : 
#     251                 :       2086 :         addressRet = PKHash(pubKey);
#     252                 :       2086 :         return true;
#     253                 :       2086 :     }
#     254         [ +  + ]:     130994 :     case TxoutType::PUBKEYHASH: {
#     255                 :     130994 :         addressRet = PKHash(uint160(vSolutions[0]));
#     256                 :     130994 :         return true;
#     257                 :       2086 :     }
#     258         [ +  + ]:      15503 :     case TxoutType::SCRIPTHASH: {
#     259                 :      15503 :         addressRet = ScriptHash(uint160(vSolutions[0]));
#     260                 :      15503 :         return true;
#     261                 :       2086 :     }
#     262         [ +  + ]:     327780 :     case TxoutType::WITNESS_V0_KEYHASH: {
#     263                 :     327780 :         WitnessV0KeyHash hash;
#     264                 :     327780 :         std::copy(vSolutions[0].begin(), vSolutions[0].end(), hash.begin());
#     265                 :     327780 :         addressRet = hash;
#     266                 :     327780 :         return true;
#     267                 :       2086 :     }
#     268         [ +  + ]:       1766 :     case TxoutType::WITNESS_V0_SCRIPTHASH: {
#     269                 :       1766 :         WitnessV0ScriptHash hash;
#     270                 :       1766 :         std::copy(vSolutions[0].begin(), vSolutions[0].end(), hash.begin());
#     271                 :       1766 :         addressRet = hash;
#     272                 :       1766 :         return true;
#     273                 :       2086 :     }
#     274         [ +  + ]:       8738 :     case TxoutType::WITNESS_V1_TAPROOT: {
#     275                 :       8738 :         WitnessV1Taproot tap;
#     276                 :       8738 :         std::copy(vSolutions[0].begin(), vSolutions[0].end(), tap.begin());
#     277                 :       8738 :         addressRet = tap;
#     278                 :       8738 :         return true;
#     279                 :       2086 :     }
#     280         [ +  + ]:         28 :     case TxoutType::WITNESS_UNKNOWN: {
#     281                 :         28 :         WitnessUnknown unk;
#     282                 :         28 :         unk.version = vSolutions[0][0];
#     283                 :         28 :         std::copy(vSolutions[1].begin(), vSolutions[1].end(), unk.program);
#     284                 :         28 :         unk.length = vSolutions[1].size();
#     285                 :         28 :         addressRet = unk;
#     286                 :         28 :         return true;
#     287                 :       2086 :     }
#     288         [ +  + ]:        377 :     case TxoutType::MULTISIG:
#     289         [ +  + ]:     120500 :     case TxoutType::NULL_DATA:
#     290         [ +  + ]:     120719 :     case TxoutType::NONSTANDARD:
#     291                 :     120719 :         return false;
#     292                 :     607614 :     } // no default case, so the compiler can warn about missing cases
#     293                 :          0 :     assert(false);
#     294                 :          0 : }
#     295                 :            : 
#     296                 :            : namespace {
#     297                 :            : class CScriptVisitor
#     298                 :            : {
#     299                 :            : public:
#     300                 :            :     CScript operator()(const CNoDestination& dest) const
#     301                 :         33 :     {
#     302                 :         33 :         return CScript();
#     303                 :         33 :     }
#     304                 :            : 
#     305                 :            :     CScript operator()(const PKHash& keyID) const
#     306                 :     693251 :     {
#     307                 :     693251 :         return CScript() << OP_DUP << OP_HASH160 << ToByteVector(keyID) << OP_EQUALVERIFY << OP_CHECKSIG;
#     308                 :     693251 :     }
#     309                 :            : 
#     310                 :            :     CScript operator()(const ScriptHash& scriptID) const
#     311                 :     133651 :     {
#     312                 :     133651 :         return CScript() << OP_HASH160 << ToByteVector(scriptID) << OP_EQUAL;
#     313                 :     133651 :     }
#     314                 :            : 
#     315                 :            :     CScript operator()(const WitnessV0KeyHash& id) const
#     316                 :     540169 :     {
#     317                 :     540169 :         return CScript() << OP_0 << ToByteVector(id);
#     318                 :     540169 :     }
#     319                 :            : 
#     320                 :            :     CScript operator()(const WitnessV0ScriptHash& id) const
#     321                 :      23095 :     {
#     322                 :      23095 :         return CScript() << OP_0 << ToByteVector(id);
#     323                 :      23095 :     }
#     324                 :            : 
#     325                 :            :     CScript operator()(const WitnessV1Taproot& tap) const
#     326                 :      66104 :     {
#     327                 :      66104 :         return CScript() << OP_1 << ToByteVector(tap);
#     328                 :      66104 :     }
#     329                 :            : 
#     330                 :            :     CScript operator()(const WitnessUnknown& id) const
#     331                 :         50 :     {
#     332                 :         50 :         return CScript() << CScript::EncodeOP_N(id.version) << std::vector<unsigned char>(id.program, id.program + id.length);
#     333                 :         50 :     }
#     334                 :            : };
#     335                 :            : } // namespace
#     336                 :            : 
#     337                 :            : CScript GetScriptForDestination(const CTxDestination& dest)
#     338                 :    1456353 : {
#     339                 :    1456353 :     return std::visit(CScriptVisitor(), dest);
#     340                 :    1456353 : }
#     341                 :            : 
#     342                 :            : CScript GetScriptForRawPubKey(const CPubKey& pubKey)
#     343                 :      99084 : {
#     344                 :      99084 :     return CScript() << std::vector<unsigned char>(pubKey.begin(), pubKey.end()) << OP_CHECKSIG;
#     345                 :      99084 : }
#     346                 :            : 
#     347                 :            : CScript GetScriptForMultisig(int nRequired, const std::vector<CPubKey>& keys)
#     348                 :      24443 : {
#     349                 :      24443 :     CScript script;
#     350                 :            : 
#     351                 :      24443 :     script << nRequired;
#     352         [ +  + ]:      24443 :     for (const CPubKey& key : keys)
#     353                 :     127116 :         script << ToByteVector(key);
#     354                 :      24443 :     script << keys.size() << OP_CHECKMULTISIG;
#     355                 :            : 
#     356                 :      24443 :     return script;
#     357                 :      24443 : }
#     358                 :            : 
#     359                 :      31202 : bool IsValidDestination(const CTxDestination& dest) {
#     360                 :      31202 :     return dest.index() != 0;
#     361                 :      31202 : }
#     362                 :            : 
#     363                 :            : /*static*/ TaprootBuilder::NodeInfo TaprootBuilder::Combine(NodeInfo&& a, NodeInfo&& b)
#     364                 :      23275 : {
#     365                 :      23275 :     NodeInfo ret;
#     366                 :            :     /* Iterate over all tracked leaves in a, add b's hash to their Merkle branch, and move them to ret. */
#     367         [ +  + ]:      42918 :     for (auto& leaf : a.leaves) {
#     368                 :      42918 :         leaf.merkle_branch.push_back(b.hash);
#     369                 :      42918 :         ret.leaves.emplace_back(std::move(leaf));
#     370                 :      42918 :     }
#     371                 :            :     /* Iterate over all tracked leaves in b, add a's hash to their Merkle branch, and move them to ret. */
#     372         [ +  + ]:      29763 :     for (auto& leaf : b.leaves) {
#     373                 :      29763 :         leaf.merkle_branch.push_back(a.hash);
#     374                 :      29763 :         ret.leaves.emplace_back(std::move(leaf));
#     375                 :      29763 :     }
#     376                 :            :     /* Lexicographically sort a and b's hash, and compute parent hash. */
#     377         [ +  + ]:      23275 :     if (a.hash < b.hash) {
#     378                 :       5220 :         ret.hash = (CHashWriter(HASHER_TAPBRANCH) << a.hash << b.hash).GetSHA256();
#     379                 :      18055 :     } else {
#     380                 :      18055 :         ret.hash = (CHashWriter(HASHER_TAPBRANCH) << b.hash << a.hash).GetSHA256();
#     381                 :      18055 :     }
#     382                 :      23275 :     return ret;
#     383                 :      23275 : }
#     384                 :            : 
#     385                 :            : void TaprootSpendData::Merge(TaprootSpendData other)
#     386                 :      64051 : {
#     387                 :            :     // TODO: figure out how to better deal with conflicting information
#     388                 :            :     // being merged.
#     389 [ +  - ][ +  - ]:      64051 :     if (internal_key.IsNull() && !other.internal_key.IsNull()) {
#     390                 :      64051 :         internal_key = other.internal_key;
#     391                 :      64051 :     }
#     392 [ +  - ][ +  + ]:      64051 :     if (merkle_root.IsNull() && !other.merkle_root.IsNull()) {
#     393                 :      17016 :         merkle_root = other.merkle_root;
#     394                 :      17016 :     }
#     395         [ +  + ]:      64051 :     for (auto& [key, control_blocks] : other.scripts) {
#     396                 :      26024 :         scripts[key].merge(std::move(control_blocks));
#     397                 :      26024 :     }
#     398                 :      64051 : }
#     399                 :            : 
#     400                 :            : void TaprootBuilder::Insert(TaprootBuilder::NodeInfo&& node, int depth)
#     401                 :      38053 : {
#     402                 :      38053 :     assert(depth >= 0 && (size_t)depth <= TAPROOT_CONTROL_MAX_NODE_COUNT);
#     403                 :            :     /* We cannot insert a leaf at a lower depth while a deeper branch is unfinished. Doing
#     404                 :            :      * so would mean the Add() invocations do not correspond to a DFS traversal of a
#     405                 :            :      * binary tree. */
#     406         [ -  + ]:      38053 :     if ((size_t)depth + 1 < m_branch.size()) {
#     407                 :          0 :         m_valid = false;
#     408                 :          0 :         return;
#     409                 :          0 :     }
#     410                 :            :     /* As long as an entry in the branch exists at the specified depth, combine it and propagate up.
#     411                 :            :      * The 'node' variable is overwritten here with the newly combined node. */
#     412 [ +  - ][ +  + ]:      61328 :     while (m_valid && m_branch.size() > (size_t)depth && m_branch[depth].has_value()) {
#                 [ +  + ]
#     413                 :      23275 :         node = Combine(std::move(node), std::move(*m_branch[depth]));
#     414                 :      23275 :         m_branch.pop_back();
#     415         [ -  + ]:      23275 :         if (depth == 0) m_valid = false; /* Can't propagate further up than the root */
#     416                 :      23275 :         --depth;
#     417                 :      23275 :     }
#     418         [ +  - ]:      38053 :     if (m_valid) {
#     419                 :            :         /* Make sure the branch is big enough to place the new node. */
#     420         [ +  + ]:      38053 :         if (m_branch.size() <= (size_t)depth) m_branch.resize((size_t)depth + 1);
#     421                 :      38053 :         assert(!m_branch[depth].has_value());
#     422                 :          0 :         m_branch[depth] = std::move(node);
#     423                 :      38053 :     }
#     424                 :      38053 : }
#     425                 :            : 
#     426                 :            : /*static*/ bool TaprootBuilder::ValidDepths(const std::vector<int>& depths)
#     427                 :        975 : {
#     428                 :        975 :     std::vector<bool> branch;
#     429         [ +  + ]:       1426 :     for (int depth : depths) {
#     430                 :            :         // This inner loop corresponds to effectively the same logic on branch
#     431                 :            :         // as what Insert() performs on the m_branch variable. Instead of
#     432                 :            :         // storing a NodeInfo object, just remember whether or not there is one
#     433                 :            :         // at that depth.
#     434 [ -  + ][ +  + ]:       1426 :         if (depth < 0 || (size_t)depth > TAPROOT_CONTROL_MAX_NODE_COUNT) return false;
#     435         [ +  + ]:       1424 :         if ((size_t)depth + 1 < branch.size()) return false;
#     436 [ +  + ][ +  + ]:       2374 :         while (branch.size() > (size_t)depth && branch[depth]) {
#                 [ +  + ]
#     437                 :        998 :             branch.pop_back();
#     438         [ +  + ]:        998 :             if (depth == 0) return false;
#     439                 :        986 :             --depth;
#     440                 :        986 :         }
#     441         [ +  + ]:       1376 :         if (branch.size() <= (size_t)depth) branch.resize((size_t)depth + 1);
#     442                 :       1376 :         assert(!branch[depth]);
#     443                 :          0 :         branch[depth] = true;
#     444                 :       1376 :     }
#     445                 :            :     // And this check corresponds to the IsComplete() check on m_branch.
#     446 [ +  + ][ +  + ]:        925 :     return branch.size() == 0 || (branch.size() == 1 && branch[0]);
#                 [ +  - ]
#     447                 :        975 : }
#     448                 :            : 
#     449                 :            : TaprootBuilder& TaprootBuilder::Add(int depth, const CScript& script, int leaf_version, bool track)
#     450                 :      38051 : {
#     451                 :      38051 :     assert((leaf_version & ~TAPROOT_LEAF_MASK) == 0);
#     452         [ -  + ]:      38051 :     if (!IsValid()) return *this;
#     453                 :            :     /* Construct NodeInfo object with leaf hash and (if track is true) also leaf information. */
#     454                 :      38051 :     NodeInfo node;
#     455                 :      38051 :     node.hash = (CHashWriter{HASHER_TAPLEAF} << uint8_t(leaf_version) << script).GetSHA256();
#     456         [ +  - ]:      38051 :     if (track) node.leaves.emplace_back(LeafInfo{script, leaf_version, {}});
#     457                 :            :     /* Insert into the branch. */
#     458                 :      38051 :     Insert(std::move(node), depth);
#     459                 :      38051 :     return *this;
#     460                 :      38051 : }
#     461                 :            : 
#     462                 :            : TaprootBuilder& TaprootBuilder::AddOmitted(int depth, const uint256& hash)
#     463                 :          2 : {
#     464         [ -  + ]:          2 :     if (!IsValid()) return *this;
#     465                 :            :     /* Construct NodeInfo object with the hash directly, and insert it into the branch. */
#     466                 :          2 :     NodeInfo node;
#     467                 :          2 :     node.hash = hash;
#     468                 :          2 :     Insert(std::move(node), depth);
#     469                 :          2 :     return *this;
#     470                 :          2 : }
#     471                 :            : 
#     472                 :            : TaprootBuilder& TaprootBuilder::Finalize(const XOnlyPubKey& internal_key)
#     473                 :      61284 : {
#     474                 :            :     /* Can only call this function when IsComplete() is true. */
#     475                 :      61284 :     assert(IsComplete());
#     476                 :          0 :     m_internal_key = internal_key;
#     477         [ +  + ]:      61284 :     auto ret = m_internal_key.CreateTapTweak(m_branch.size() == 0 ? nullptr : &m_branch[0]->hash);
#     478                 :      61284 :     assert(ret.has_value());
#     479                 :          0 :     std::tie(m_output_key, m_parity) = *ret;
#     480                 :      61284 :     return *this;
#     481                 :      61284 : }
#     482                 :            : 
#     483                 :      61298 : WitnessV1Taproot TaprootBuilder::GetOutput() { return WitnessV1Taproot{m_output_key}; }
#     484                 :            : 
#     485                 :            : TaprootSpendData TaprootBuilder::GetSpendData() const
#     486                 :      61282 : {
#     487                 :      61282 :     assert(IsComplete());
#     488                 :          0 :     TaprootSpendData spd;
#     489         [ +  + ]:      61282 :     spd.merkle_root = m_branch.size() == 0 ? uint256() : m_branch[0]->hash;
#     490                 :      61282 :     spd.internal_key = m_internal_key;
#     491         [ +  + ]:      61282 :     if (m_branch.size()) {
#     492                 :            :         // If any script paths exist, they have been combined into the root m_branch[0]
#     493                 :            :         // by now. Compute the control block for each of its tracked leaves, and put them in
#     494                 :            :         // spd.scripts.
#     495         [ +  + ]:      38047 :         for (const auto& leaf : m_branch[0]->leaves) {
#     496                 :      38047 :             std::vector<unsigned char> control_block;
#     497                 :      38047 :             control_block.resize(TAPROOT_CONTROL_BASE_SIZE + TAPROOT_CONTROL_NODE_SIZE * leaf.merkle_branch.size());
#     498         [ +  + ]:      38047 :             control_block[0] = leaf.leaf_version | (m_parity ? 1 : 0);
#     499                 :      38047 :             std::copy(m_internal_key.begin(), m_internal_key.end(), control_block.begin() + 1);
#     500         [ +  + ]:      38047 :             if (leaf.merkle_branch.size()) {
#     501                 :      31125 :                 std::copy(leaf.merkle_branch[0].begin(),
#     502                 :      31125 :                           leaf.merkle_branch[0].begin() + TAPROOT_CONTROL_NODE_SIZE * leaf.merkle_branch.size(),
#     503                 :      31125 :                           control_block.begin() + TAPROOT_CONTROL_BASE_SIZE);
#     504                 :      31125 :             }
#     505                 :      38047 :             spd.scripts[{leaf.script, leaf.leaf_version}].insert(std::move(control_block));
#     506                 :      38047 :         }
#     507                 :      14776 :     }
#     508                 :      61282 :     return spd;
#     509                 :      61282 : }
#     510                 :            : 
#     511                 :            : std::optional<std::vector<std::tuple<int, CScript, int>>> InferTaprootTree(const TaprootSpendData& spenddata, const XOnlyPubKey& output)
#     512                 :        117 : {
#     513                 :            :     // Verify that the output matches the assumed Merkle root and internal key.
#     514         [ +  + ]:        117 :     auto tweak = spenddata.internal_key.CreateTapTweak(spenddata.merkle_root.IsNull() ? nullptr : &spenddata.merkle_root);
#     515 [ -  + ][ -  + ]:        117 :     if (!tweak || tweak->first != output) return std::nullopt;
#     516                 :            :     // If the Merkle root is 0, the tree is empty, and we're done.
#     517                 :        117 :     std::vector<std::tuple<int, CScript, int>> ret;
#     518         [ +  + ]:        117 :     if (spenddata.merkle_root.IsNull()) return ret;
#     519                 :            : 
#     520                 :            :     /** Data structure to represent the nodes of the tree we're going to build. */
#     521                 :         96 :     struct TreeNode {
#     522                 :            :         /** Hash of this node, if known; 0 otherwise. */
#     523                 :         96 :         uint256 hash;
#     524                 :            :         /** The left and right subtrees (note that their order is irrelevant). */
#     525                 :         96 :         std::unique_ptr<TreeNode> sub[2];
#     526                 :            :         /** If this is known to be a leaf node, a pointer to the (script, leaf_ver) pair.
#     527                 :            :          *  nullptr otherwise. */
#     528                 :         96 :         const std::pair<CScript, int>* leaf = nullptr;
#     529                 :            :         /** Whether or not this node has been explored (is known to be a leaf, or known to have children). */
#     530                 :         96 :         bool explored = false;
#     531                 :            :         /** Whether or not this node is an inner node (unknown until explored = true). */
#     532                 :         96 :         bool inner;
#     533                 :            :         /** Whether or not we have produced output for this subtree. */
#     534                 :         96 :         bool done = false;
#     535                 :         96 :     };
#     536                 :            : 
#     537                 :            :     // Build tree from the provided branches.
#     538                 :         96 :     TreeNode root;
#     539                 :         96 :     root.hash = spenddata.merkle_root;
#     540         [ +  + ]:        140 :     for (const auto& [key, control_blocks] : spenddata.scripts) {
#     541                 :        140 :         const auto& [script, leaf_ver] = key;
#     542         [ +  + ]:        184 :         for (const auto& control : control_blocks) {
#     543                 :            :             // Skip script records with nonsensical leaf version.
#     544 [ -  + ][ -  + ]:        184 :             if (leaf_ver < 0 || leaf_ver >= 0x100 || leaf_ver & 1) continue;
#                 [ -  + ]
#     545                 :            :             // Skip script records with invalid control block sizes.
#     546 [ -  + ][ -  + ]:        184 :             if (control.size() < TAPROOT_CONTROL_BASE_SIZE || control.size() > TAPROOT_CONTROL_MAX_SIZE ||
#     547         [ -  + ]:        184 :                 ((control.size() - TAPROOT_CONTROL_BASE_SIZE) % TAPROOT_CONTROL_NODE_SIZE) != 0) continue;
#     548                 :            :             // Skip script records that don't match the control block.
#     549         [ -  + ]:        184 :             if ((control[0] & TAPROOT_LEAF_MASK) != leaf_ver) continue;
#     550                 :            :             // Skip script records that don't match the provided Merkle root.
#     551                 :        184 :             const uint256 leaf_hash = ComputeTapleafHash(leaf_ver, script);
#     552                 :        184 :             const uint256 merkle_root = ComputeTaprootMerkleRoot(control, leaf_hash);
#     553         [ -  + ]:        184 :             if (merkle_root != spenddata.merkle_root) continue;
#     554                 :            : 
#     555                 :        184 :             TreeNode* node = &root;
#     556                 :        184 :             size_t levels = (control.size() - TAPROOT_CONTROL_BASE_SIZE) / TAPROOT_CONTROL_NODE_SIZE;
#     557         [ +  + ]:        448 :             for (size_t depth = 0; depth < levels; ++depth) {
#     558                 :            :                 // Can't descend into a node which we already know is a leaf.
#     559 [ +  + ][ -  + ]:        264 :                 if (node->explored && !node->inner) return std::nullopt;
#     560                 :            : 
#     561                 :            :                 // Extract partner hash from Merkle branch in control block.
#     562                 :        264 :                 uint256 hash;
#     563                 :        264 :                 std::copy(control.begin() + TAPROOT_CONTROL_BASE_SIZE + (levels - 1 - depth) * TAPROOT_CONTROL_NODE_SIZE,
#     564                 :        264 :                           control.begin() + TAPROOT_CONTROL_BASE_SIZE + (levels - depth) * TAPROOT_CONTROL_NODE_SIZE,
#     565                 :        264 :                           hash.begin());
#     566                 :            : 
#     567         [ +  + ]:        264 :                 if (node->sub[0]) {
#     568                 :            :                     // Descend into the existing left or right branch.
#     569                 :        160 :                     bool desc = false;
#     570         [ +  - ]:        191 :                     for (int i = 0; i < 2; ++i) {
#     571 [ +  + ][ +  + ]:        191 :                         if (node->sub[i]->hash == hash || (node->sub[i]->hash.IsNull() && node->sub[1-i]->hash != hash)) {
#                 [ +  + ]
#     572                 :        160 :                             node->sub[i]->hash = hash;
#     573                 :        160 :                             node = &*node->sub[1-i];
#     574                 :        160 :                             desc = true;
#     575                 :        160 :                             break;
#     576                 :        160 :                         }
#     577                 :        191 :                     }
#     578         [ -  + ]:        160 :                     if (!desc) return std::nullopt; // This probably requires a hash collision to hit.
#     579                 :        160 :                 } else {
#     580                 :            :                     // We're in an unexplored node. Create subtrees and descend.
#     581                 :        104 :                     node->explored = true;
#     582                 :        104 :                     node->inner = true;
#     583                 :        104 :                     node->sub[0] = std::make_unique<TreeNode>();
#     584                 :        104 :                     node->sub[1] = std::make_unique<TreeNode>();
#     585                 :        104 :                     node->sub[1]->hash = hash;
#     586                 :        104 :                     node = &*node->sub[0];
#     587                 :        104 :                 }
#     588                 :        264 :             }
#     589                 :            :             // Cannot turn a known inner node into a leaf.
#     590         [ -  + ]:        184 :             if (node->sub[0]) return std::nullopt;
#     591                 :        184 :             node->explored = true;
#     592                 :        184 :             node->inner = false;
#     593                 :        184 :             node->leaf = &key;
#     594                 :        184 :             node->hash = leaf_hash;
#     595                 :        184 :         }
#     596                 :        140 :     }
#     597                 :            : 
#     598                 :            :     // Recursive processing to turn the tree into flattened output. Use an explicit stack here to avoid
#     599                 :            :     // overflowing the call stack (the tree may be 128 levels deep).
#     600                 :         96 :     std::vector<TreeNode*> stack{&root};
#     601         [ +  + ]:        676 :     while (!stack.empty()) {
#     602                 :        580 :         TreeNode& node = *stack.back();
#     603         [ -  + ]:        580 :         if (!node.explored) {
#     604                 :            :             // Unexplored node, which means the tree is incomplete.
#     605                 :          0 :             return std::nullopt;
#     606         [ +  + ]:        580 :         } else if (!node.inner) {
#     607                 :            :             // Leaf node; produce output.
#     608                 :        212 :             ret.emplace_back(stack.size() - 1, node.leaf->first, node.leaf->second);
#     609                 :        212 :             node.done = true;
#     610                 :        212 :             stack.pop_back();
#     611 [ +  + ][ +  + ]:        368 :         } else if (node.sub[0]->done && !node.sub[1]->done && !node.sub[1]->explored && !node.sub[1]->hash.IsNull() &&
#         [ +  + ][ +  + ]
#                 [ +  - ]
#     612         [ +  - ]:        368 :                    (CHashWriter{HASHER_TAPBRANCH} << node.sub[1]->hash << node.sub[1]->hash).GetSHA256() == node.hash) {
#     613                 :            :             // Whenever there are nodes with two identical subtrees under it, we run into a problem:
#     614                 :            :             // the control blocks for the leaves underneath those will be identical as well, and thus
#     615                 :            :             // they will all be matched to the same path in the tree. The result is that at the location
#     616                 :            :             // where the duplicate occurred, the left child will contain a normal tree that can be explored
#     617                 :            :             // and processed, but the right one will remain unexplored.
#     618                 :            :             //
#     619                 :            :             // This situation can be detected, by encountering an inner node with unexplored right subtree
#     620                 :            :             // with known hash, and H_TapBranch(hash, hash) is equal to the parent node (this node)'s hash.
#     621                 :            :             //
#     622                 :            :             // To deal with this, simply process the left tree a second time (set its done flag to false;
#     623                 :            :             // noting that the done flag of its children have already been set to false after processing
#     624                 :            :             // those). To avoid ending up in an infinite loop, set the done flag of the right (unexplored)
#     625                 :            :             // subtree to true.
#     626                 :         20 :             node.sub[0]->done = false;
#     627                 :         20 :             node.sub[1]->done = true;
#     628 [ +  + ][ +  + ]:        348 :         } else if (node.sub[0]->done && node.sub[1]->done) {
#     629                 :            :             // An internal node which we're finished with.
#     630                 :        116 :             node.sub[0]->done = false;
#     631                 :        116 :             node.sub[1]->done = false;
#     632                 :        116 :             node.done = true;
#     633                 :        116 :             stack.pop_back();
#     634         [ +  + ]:        232 :         } else if (!node.sub[0]->done) {
#     635                 :            :             // An internal node whose left branch hasn't been processed yet. Do so first.
#     636                 :        136 :             stack.push_back(&*node.sub[0]);
#     637         [ +  - ]:        136 :         } else if (!node.sub[1]->done) {
#     638                 :            :             // An internal node whose right branch hasn't been processed yet. Do so first.
#     639                 :         96 :             stack.push_back(&*node.sub[1]);
#     640                 :         96 :         }
#     641                 :        580 :     }
#     642                 :            : 
#     643                 :         96 :     return ret;
#     644                 :         96 : }

Generated by: LCOV version 0-eol-96201-ge66f56f4af6a