LCOV - code coverage report
Current view: top level - src/script - standard.cpp (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 246 258 95.3 %
Date: 2021-06-29 14:35:33 Functions: 32 32 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: 140 156 89.7 %

           Branch data     Line data    Source code
#       1                 :            : // Copyright (c) 2009-2010 Satoshi Nakamoto
#       2                 :            : // Copyright (c) 2009-2020 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 <pubkey.h>
#      10                 :            : #include <script/script.h>
#      11                 :            : 
#      12                 :            : #include <string>
#      13                 :            : 
#      14                 :            : typedef std::vector<unsigned char> valtype;
#      15                 :            : 
#      16                 :            : bool fAcceptDatacarrier = DEFAULT_ACCEPT_DATACARRIER;
#      17                 :            : unsigned nMaxDatacarrierBytes = MAX_OP_RETURN_RELAY;
#      18                 :            : 
#      19                 :     990768 : CScriptID::CScriptID(const CScript& in) : BaseHash(Hash160(in)) {}
#      20                 :       2624 : CScriptID::CScriptID(const ScriptHash& in) : BaseHash(static_cast<uint160>(in)) {}
#      21                 :            : 
#      22                 :     106714 : ScriptHash::ScriptHash(const CScript& in) : BaseHash(Hash160(in)) {}
#      23                 :       1252 : ScriptHash::ScriptHash(const CScriptID& in) : BaseHash(static_cast<uint160>(in)) {}
#      24                 :            : 
#      25                 :      33358 : PKHash::PKHash(const CPubKey& pubkey) : BaseHash(pubkey.GetID()) {}
#      26                 :     131874 : PKHash::PKHash(const CKeyID& pubkey_id) : BaseHash(pubkey_id) {}
#      27                 :            : 
#      28                 :      12357 : WitnessV0KeyHash::WitnessV0KeyHash(const CPubKey& pubkey) : BaseHash(pubkey.GetID()) {}
#      29                 :       1486 : WitnessV0KeyHash::WitnessV0KeyHash(const PKHash& pubkey_hash) : BaseHash(static_cast<uint160>(pubkey_hash)) {}
#      30                 :            : 
#      31                 :            : CKeyID ToKeyID(const PKHash& key_hash)
#      32                 :        636 : {
#      33                 :        636 :     return CKeyID{static_cast<uint160>(key_hash)};
#      34                 :        636 : }
#      35                 :            : 
#      36                 :            : CKeyID ToKeyID(const WitnessV0KeyHash& key_hash)
#      37                 :       1665 : {
#      38                 :       1665 :     return CKeyID{static_cast<uint160>(key_hash)};
#      39                 :       1665 : }
#      40                 :            : 
#      41                 :            : WitnessV0ScriptHash::WitnessV0ScriptHash(const CScript& in)
#      42                 :      14733 : {
#      43                 :      14733 :     CSHA256().Write(in.data(), in.size()).Finalize(begin());
#      44                 :      14733 : }
#      45                 :            : 
#      46                 :            : std::string GetTxnOutputType(TxoutType t)
#      47                 :      24599 : {
#      48         [ -  + ]:      24599 :     switch (t) {
#      49         [ +  + ]:       1377 :     case TxoutType::NONSTANDARD: return "nonstandard";
#      50         [ +  + ]:       2855 :     case TxoutType::PUBKEY: return "pubkey";
#      51         [ +  + ]:       1681 :     case TxoutType::PUBKEYHASH: return "pubkeyhash";
#      52         [ +  + ]:       1777 :     case TxoutType::SCRIPTHASH: return "scripthash";
#      53         [ +  + ]:       1552 :     case TxoutType::MULTISIG: return "multisig";
#      54         [ +  + ]:       2975 :     case TxoutType::NULL_DATA: return "nulldata";
#      55         [ +  + ]:       8091 :     case TxoutType::WITNESS_V0_KEYHASH: return "witness_v0_keyhash";
#      56         [ +  + ]:       1584 :     case TxoutType::WITNESS_V0_SCRIPTHASH: return "witness_v0_scripthash";
#      57         [ +  + ]:       1353 :     case TxoutType::WITNESS_V1_TAPROOT: return "witness_v1_taproot";
#      58         [ +  + ]:       1354 :     case TxoutType::WITNESS_UNKNOWN: return "witness_unknown";
#      59                 :          0 :     } // no default case, so the compiler can warn about missing cases
#      60                 :          0 :     assert(false);
#      61                 :          0 : }
#      62                 :            : 
#      63                 :            : static bool MatchPayToPubkey(const CScript& script, valtype& pubkey)
#      64                 :    2705012 : {
#      65 [ +  + ][ +  - ]:    2705012 :     if (script.size() == CPubKey::SIZE + 2 && script[0] == CPubKey::SIZE && script.back() == OP_CHECKSIG) {
#                 [ +  - ]
#      66                 :       2078 :         pubkey = valtype(script.begin() + 1, script.begin() + CPubKey::SIZE + 1);
#      67                 :       2078 :         return CPubKey::ValidSize(pubkey);
#      68                 :       2078 :     }
#      69 [ +  + ][ +  - ]:    2702934 :     if (script.size() == CPubKey::COMPRESSED_SIZE + 2 && script[0] == CPubKey::COMPRESSED_SIZE && script.back() == OP_CHECKSIG) {
#                 [ +  - ]
#      70                 :      45537 :         pubkey = valtype(script.begin() + 1, script.begin() + CPubKey::COMPRESSED_SIZE + 1);
#      71                 :      45537 :         return CPubKey::ValidSize(pubkey);
#      72                 :      45537 :     }
#      73                 :    2657397 :     return false;
#      74                 :    2657397 : }
#      75                 :            : 
#      76                 :            : static bool MatchPayToPubkeyHash(const CScript& script, valtype& pubkeyhash)
#      77                 :    2657397 : {
#      78 [ +  + ][ +  - ]:    2657397 :     if (script.size() == 25 && script[0] == OP_DUP && script[1] == OP_HASH160 && script[2] == 20 && script[23] == OP_EQUALVERIFY && script[24] == OP_CHECKSIG) {
#         [ +  + ][ +  - ]
#         [ +  + ][ +  + ]
#      79                 :    2410874 :         pubkeyhash = valtype(script.begin () + 3, script.begin() + 23);
#      80                 :    2410874 :         return true;
#      81                 :    2410874 :     }
#      82                 :     246523 :     return false;
#      83                 :     246523 : }
#      84                 :            : 
#      85                 :            : /** Test for "small positive integer" script opcodes - OP_1 through OP_16. */
#      86                 :            : static constexpr bool IsSmallInteger(opcodetype opcode)
#      87                 :      22880 : {
#      88 [ +  + ][ +  + ]:      22880 :     return opcode >= OP_1 && opcode <= OP_16;
#      89                 :      22880 : }
#      90                 :            : 
#      91                 :            : static constexpr bool IsPushdataOp(opcodetype opcode)
#      92                 :        228 : {
#      93 [ +  + ][ +  + ]:        228 :     return opcode > OP_FALSE && opcode <= OP_PUSHDATA4;
#      94                 :        228 : }
#      95                 :            : 
#      96                 :            : static constexpr bool IsValidMultisigKeyCount(int n_keys)
#      97                 :      22864 : {
#      98 [ +  - ][ +  - ]:      22864 :     return n_keys > 0 && n_keys <= MAX_PUBKEYS_PER_MULTISIG;
#      99                 :      22864 : }
#     100                 :            : 
#     101                 :            : static bool GetMultisigKeyCount(opcodetype opcode, valtype data, int& count)
#     102                 :      22880 : {
#     103         [ +  + ]:      22880 :     if (IsSmallInteger(opcode)) {
#     104                 :      22652 :         count = CScript::DecodeOP_N(opcode);
#     105                 :      22652 :         return IsValidMultisigKeyCount(count);
#     106                 :      22652 :     }
#     107                 :            : 
#     108         [ +  + ]:        228 :     if (IsPushdataOp(opcode)) {
#     109         [ +  + ]:        220 :         if (!CheckMinimalPush(data, opcode)) return false;
#     110                 :        212 :         try {
#     111                 :        212 :             count = CScriptNum(data, /* fRequireMinimal = */ true).getint();
#     112                 :        212 :             return IsValidMultisigKeyCount(count);
#     113                 :        212 :         } catch (const scriptnum_error&) {
#     114                 :          0 :             return false;
#     115                 :          0 :         }
#     116                 :          8 :     }
#     117                 :            : 
#     118                 :          8 :     return false;
#     119                 :          8 : }
#     120                 :            : 
#     121                 :            : static bool MatchMultisig(const CScript& script, int& required_sigs, std::vector<valtype>& pubkeys)
#     122                 :     246523 : {
#     123                 :     246523 :     opcodetype opcode;
#     124                 :     246523 :     valtype data;
#     125                 :     246523 :     int num_keys;
#     126                 :            : 
#     127                 :     246523 :     CScript::const_iterator it = script.begin();
#     128 [ +  + ][ +  + ]:     246523 :     if (script.size() < 1 || script.back() != OP_CHECKMULTISIG) return false;
#     129                 :            : 
#     130 [ +  + ][ -  + ]:      11444 :     if (!script.GetOp(it, opcode, data) || !GetMultisigKeyCount(opcode, data, required_sigs)) return false;
#                 [ +  + ]
#     131 [ +  - ][ +  + ]:      36164 :     while (script.GetOp(it, opcode, data) && CPubKey::ValidSize(data)) {
#     132                 :      24728 :         pubkeys.emplace_back(std::move(data));
#     133                 :      24728 :     }
#     134         [ +  + ]:      11436 :     if (!GetMultisigKeyCount(opcode, data, num_keys)) return false;
#     135                 :            : 
#     136 [ +  + ][ +  + ]:      11428 :     if (pubkeys.size() != static_cast<unsigned long>(num_keys) || num_keys < required_sigs) return false;
#     137                 :            : 
#     138                 :      11418 :     return (it + 1 == script.end());
#     139                 :      11418 : }
#     140                 :            : 
#     141                 :            : TxoutType Solver(const CScript& scriptPubKey, std::vector<std::vector<unsigned char>>& vSolutionsRet)
#     142                 :    5219947 : {
#     143                 :    5219947 :     vSolutionsRet.clear();
#     144                 :            : 
#     145                 :            :     // Shortcut for pay-to-script-hash, which are more constrained than the other types:
#     146                 :            :     // it is always OP_HASH160 20 [20 byte hash] OP_EQUAL
#     147         [ +  + ]:    5219947 :     if (scriptPubKey.IsPayToScriptHash())
#     148                 :     176139 :     {
#     149                 :     176139 :         std::vector<unsigned char> hashBytes(scriptPubKey.begin()+2, scriptPubKey.begin()+22);
#     150                 :     176139 :         vSolutionsRet.push_back(hashBytes);
#     151                 :     176139 :         return TxoutType::SCRIPTHASH;
#     152                 :     176139 :     }
#     153                 :            : 
#     154                 :    5043808 :     int witnessversion;
#     155                 :    5043808 :     std::vector<unsigned char> witnessprogram;
#     156         [ +  + ]:    5043808 :     if (scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)) {
#     157 [ +  + ][ +  + ]:    1970763 :         if (witnessversion == 0 && witnessprogram.size() == WITNESS_V0_KEYHASH_SIZE) {
#     158                 :    1911734 :             vSolutionsRet.push_back(witnessprogram);
#     159                 :    1911734 :             return TxoutType::WITNESS_V0_KEYHASH;
#     160                 :    1911734 :         }
#     161 [ +  + ][ +  + ]:      59029 :         if (witnessversion == 0 && witnessprogram.size() == WITNESS_V0_SCRIPTHASH_SIZE) {
#     162                 :      39119 :             vSolutionsRet.push_back(witnessprogram);
#     163                 :      39119 :             return TxoutType::WITNESS_V0_SCRIPTHASH;
#     164                 :      39119 :         }
#     165 [ +  + ][ +  + ]:      19910 :         if (witnessversion == 1 && witnessprogram.size() == WITNESS_V1_TAPROOT_SIZE) {
#     166                 :      18825 :             vSolutionsRet.push_back(std::vector<unsigned char>{(unsigned char)witnessversion});
#     167                 :      18825 :             vSolutionsRet.push_back(std::move(witnessprogram));
#     168                 :      18825 :             return TxoutType::WITNESS_V1_TAPROOT;
#     169                 :      18825 :         }
#     170         [ +  + ]:       1085 :         if (witnessversion != 0) {
#     171                 :       1082 :             vSolutionsRet.push_back(std::vector<unsigned char>{(unsigned char)witnessversion});
#     172                 :       1082 :             vSolutionsRet.push_back(std::move(witnessprogram));
#     173                 :       1082 :             return TxoutType::WITNESS_UNKNOWN;
#     174                 :       1082 :         }
#     175                 :          3 :         return TxoutType::NONSTANDARD;
#     176                 :          3 :     }
#     177                 :            : 
#     178                 :            :     // Provably prunable, data-carrying output
#     179                 :            :     //
#     180                 :            :     // So long as script passes the IsUnspendable() test and all but the first
#     181                 :            :     // byte passes the IsPushOnly() test we don't care what exactly is in the
#     182                 :            :     // script.
#     183 [ +  + ][ +  + ]:    3073045 :     if (scriptPubKey.size() >= 1 && scriptPubKey[0] == OP_RETURN && scriptPubKey.IsPushOnly(scriptPubKey.begin()+1)) {
#         [ +  + ][ +  + ]
#     184                 :     368042 :         return TxoutType::NULL_DATA;
#     185                 :     368042 :     }
#     186                 :            : 
#     187                 :    2705003 :     std::vector<unsigned char> data;
#     188         [ +  + ]:    2705003 :     if (MatchPayToPubkey(scriptPubKey, data)) {
#     189                 :      47615 :         vSolutionsRet.push_back(std::move(data));
#     190                 :      47615 :         return TxoutType::PUBKEY;
#     191                 :      47615 :     }
#     192                 :            : 
#     193         [ +  + ]:    2657388 :     if (MatchPayToPubkeyHash(scriptPubKey, data)) {
#     194                 :    2410874 :         vSolutionsRet.push_back(std::move(data));
#     195                 :    2410874 :         return TxoutType::PUBKEYHASH;
#     196                 :    2410874 :     }
#     197                 :            : 
#     198                 :     246514 :     int required;
#     199                 :     246514 :     std::vector<std::vector<unsigned char>> keys;
#     200         [ +  + ]:     246514 :     if (MatchMultisig(scriptPubKey, required, keys)) {
#     201                 :      11418 :         vSolutionsRet.push_back({static_cast<unsigned char>(required)}); // safe as required is in range 1..20
#     202                 :      11418 :         vSolutionsRet.insert(vSolutionsRet.end(), keys.begin(), keys.end());
#     203                 :      11418 :         vSolutionsRet.push_back({static_cast<unsigned char>(keys.size())}); // safe as size is in range 1..20
#     204                 :      11418 :         return TxoutType::MULTISIG;
#     205                 :      11418 :     }
#     206                 :            : 
#     207                 :     235096 :     vSolutionsRet.clear();
#     208                 :     235096 :     return TxoutType::NONSTANDARD;
#     209                 :     235096 : }
#     210                 :            : 
#     211                 :            : bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet)
#     212                 :     663760 : {
#     213                 :     663760 :     std::vector<valtype> vSolutions;
#     214                 :     663760 :     TxoutType whichType = Solver(scriptPubKey, vSolutions);
#     215                 :            : 
#     216         [ -  + ]:     663760 :     switch (whichType) {
#     217         [ +  + ]:       2952 :     case TxoutType::PUBKEY: {
#     218                 :       2952 :         CPubKey pubKey(vSolutions[0]);
#     219         [ -  + ]:       2952 :         if (!pubKey.IsValid())
#     220                 :          0 :             return false;
#     221                 :            : 
#     222                 :       2952 :         addressRet = PKHash(pubKey);
#     223                 :       2952 :         return true;
#     224                 :       2952 :     }
#     225         [ +  + ]:     131539 :     case TxoutType::PUBKEYHASH: {
#     226                 :     131539 :         addressRet = PKHash(uint160(vSolutions[0]));
#     227                 :     131539 :         return true;
#     228                 :       2952 :     }
#     229         [ +  + ]:      11787 :     case TxoutType::SCRIPTHASH: {
#     230                 :      11787 :         addressRet = ScriptHash(uint160(vSolutions[0]));
#     231                 :      11787 :         return true;
#     232                 :       2952 :     }
#     233         [ +  + ]:     354964 :     case TxoutType::WITNESS_V0_KEYHASH: {
#     234                 :     354964 :         WitnessV0KeyHash hash;
#     235                 :     354964 :         std::copy(vSolutions[0].begin(), vSolutions[0].end(), hash.begin());
#     236                 :     354964 :         addressRet = hash;
#     237                 :     354964 :         return true;
#     238                 :       2952 :     }
#     239         [ +  + ]:       2952 :     case TxoutType::WITNESS_V0_SCRIPTHASH: {
#     240                 :       1778 :         WitnessV0ScriptHash hash;
#     241                 :       1778 :         std::copy(vSolutions[0].begin(), vSolutions[0].end(), hash.begin());
#     242                 :       1778 :         addressRet = hash;
#     243                 :       1778 :         return true;
#     244                 :       2952 :     }
#     245         [ +  + ]:       2952 :     case TxoutType::WITNESS_UNKNOWN:
#     246         [ +  + ]:       2517 :     case TxoutType::WITNESS_V1_TAPROOT: {
#     247                 :       2517 :         WitnessUnknown unk;
#     248                 :       2517 :         unk.version = vSolutions[0][0];
#     249                 :       2517 :         std::copy(vSolutions[1].begin(), vSolutions[1].end(), unk.program);
#     250                 :       2517 :         unk.length = vSolutions[1].size();
#     251                 :       2517 :         addressRet = unk;
#     252                 :       2517 :         return true;
#     253                 :        155 :     }
#     254         [ +  + ]:        359 :     case TxoutType::MULTISIG:
#     255         [ +  + ]:     156439 :     case TxoutType::NULL_DATA:
#     256         [ +  + ]:     158223 :     case TxoutType::NONSTANDARD:
#     257                 :     158223 :         return false;
#     258                 :          0 :     } // no default case, so the compiler can warn about missing cases
#     259                 :          0 :     assert(false);
#     260                 :          0 : }
#     261                 :            : 
#     262                 :            : // TODO: from v23 ("addresses" and "reqSigs" deprecated) "ExtractDestinations" should be removed
#     263                 :            : bool ExtractDestinations(const CScript& scriptPubKey, TxoutType& typeRet, std::vector<CTxDestination>& addressRet, int& nRequiredRet)
#     264                 :      10426 : {
#     265                 :      10426 :     addressRet.clear();
#     266                 :      10426 :     std::vector<valtype> vSolutions;
#     267                 :      10426 :     typeRet = Solver(scriptPubKey, vSolutions);
#     268         [ +  + ]:      10426 :     if (typeRet == TxoutType::NONSTANDARD) {
#     269                 :         24 :         return false;
#     270         [ +  + ]:      10402 :     } else if (typeRet == TxoutType::NULL_DATA) {
#     271                 :            :         // This is data, not addresses
#     272                 :       1624 :         return false;
#     273                 :       1624 :     }
#     274                 :            : 
#     275         [ +  + ]:       8778 :     if (typeRet == TxoutType::MULTISIG)
#     276                 :          6 :     {
#     277                 :          6 :         nRequiredRet = vSolutions.front()[0];
#     278         [ +  + ]:         21 :         for (unsigned int i = 1; i < vSolutions.size()-1; i++)
#     279                 :         15 :         {
#     280                 :         15 :             CPubKey pubKey(vSolutions[i]);
#     281         [ -  + ]:         15 :             if (!pubKey.IsValid())
#     282                 :          0 :                 continue;
#     283                 :            : 
#     284                 :         15 :             CTxDestination address = PKHash(pubKey);
#     285                 :         15 :             addressRet.push_back(address);
#     286                 :         15 :         }
#     287                 :            : 
#     288         [ -  + ]:          6 :         if (addressRet.empty())
#     289                 :          0 :             return false;
#     290                 :       8772 :     }
#     291                 :       8772 :     else
#     292                 :       8772 :     {
#     293                 :       8772 :         nRequiredRet = 1;
#     294                 :       8772 :         CTxDestination address;
#     295         [ -  + ]:       8772 :         if (!ExtractDestination(scriptPubKey, address))
#     296                 :          0 :            return false;
#     297                 :       8772 :         addressRet.push_back(address);
#     298                 :       8772 :     }
#     299                 :            : 
#     300                 :       8778 :     return true;
#     301                 :       8778 : }
#     302                 :            : 
#     303                 :            : namespace {
#     304                 :            : class CScriptVisitor
#     305                 :            : {
#     306                 :            : public:
#     307                 :            :     CScript operator()(const CNoDestination& dest) const
#     308                 :         35 :     {
#     309                 :         35 :         return CScript();
#     310                 :         35 :     }
#     311                 :            : 
#     312                 :            :     CScript operator()(const PKHash& keyID) const
#     313                 :     716087 :     {
#     314                 :     716087 :         return CScript() << OP_DUP << OP_HASH160 << ToByteVector(keyID) << OP_EQUALVERIFY << OP_CHECKSIG;
#     315                 :     716087 :     }
#     316                 :            : 
#     317                 :            :     CScript operator()(const ScriptHash& scriptID) const
#     318                 :     109692 :     {
#     319                 :     109692 :         return CScript() << OP_HASH160 << ToByteVector(scriptID) << OP_EQUAL;
#     320                 :     109692 :     }
#     321                 :            : 
#     322                 :            :     CScript operator()(const WitnessV0KeyHash& id) const
#     323                 :     525100 :     {
#     324                 :     525100 :         return CScript() << OP_0 << ToByteVector(id);
#     325                 :     525100 :     }
#     326                 :            : 
#     327                 :            :     CScript operator()(const WitnessV0ScriptHash& id) const
#     328                 :      16347 :     {
#     329                 :      16347 :         return CScript() << OP_0 << ToByteVector(id);
#     330                 :      16347 :     }
#     331                 :            : 
#     332                 :            :     CScript operator()(const WitnessUnknown& id) const
#     333                 :       5036 :     {
#     334                 :       5036 :         return CScript() << CScript::EncodeOP_N(id.version) << std::vector<unsigned char>(id.program, id.program + id.length);
#     335                 :       5036 :     }
#     336                 :            : };
#     337                 :            : } // namespace
#     338                 :            : 
#     339                 :            : CScript GetScriptForDestination(const CTxDestination& dest)
#     340                 :    1372297 : {
#     341                 :    1372297 :     return std::visit(CScriptVisitor(), dest);
#     342                 :    1372297 : }
#     343                 :            : 
#     344                 :            : CScript GetScriptForRawPubKey(const CPubKey& pubKey)
#     345                 :     118553 : {
#     346                 :     118553 :     return CScript() << std::vector<unsigned char>(pubKey.begin(), pubKey.end()) << OP_CHECKSIG;
#     347                 :     118553 : }
#     348                 :            : 
#     349                 :            : CScript GetScriptForMultisig(int nRequired, const std::vector<CPubKey>& keys)
#     350                 :      17306 : {
#     351                 :      17306 :     CScript script;
#     352                 :            : 
#     353                 :      17306 :     script << nRequired;
#     354         [ +  + ]:      17306 :     for (const CPubKey& key : keys)
#     355                 :     110402 :         script << ToByteVector(key);
#     356                 :      17306 :     script << keys.size() << OP_CHECKMULTISIG;
#     357                 :            : 
#     358                 :      17306 :     return script;
#     359                 :      17306 : }
#     360                 :            : 
#     361                 :      31417 : bool IsValidDestination(const CTxDestination& dest) {
#     362                 :      31417 :     return dest.index() != 0;
#     363                 :      31417 : }

Generated by: LCOV version 1.14