LCOV - code coverage report
Current view: top level - src/script - standard.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 179 192 93.2 %
Date: 2020-09-26 01:30:44 Functions: 38 38 100.0 %

          Line data    Source code
       1             : // Copyright (c) 2009-2010 Satoshi Nakamoto
       2             : // Copyright (c) 2009-2019 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     1147936 : CScriptID::CScriptID(const CScript& in) : BaseHash(Hash160(in)) {}
      20        3190 : CScriptID::CScriptID(const ScriptHash& in) : BaseHash(static_cast<uint160>(in)) {}
      21             : 
      22       93336 : ScriptHash::ScriptHash(const CScript& in) : BaseHash(Hash160(in)) {}
      23        2504 : ScriptHash::ScriptHash(const CScriptID& in) : BaseHash(static_cast<uint160>(in)) {}
      24             : 
      25       58750 : PKHash::PKHash(const CPubKey& pubkey) : BaseHash(pubkey.GetID()) {}
      26      165232 : PKHash::PKHash(const CKeyID& pubkey_id) : BaseHash(pubkey_id) {}
      27             : 
      28       19930 : WitnessV0KeyHash::WitnessV0KeyHash(const CPubKey& pubkey) : BaseHash(pubkey.GetID()) {}
      29        3174 : WitnessV0KeyHash::WitnessV0KeyHash(const PKHash& pubkey_hash) : BaseHash(static_cast<uint160>(pubkey_hash)) {}
      30             : 
      31         541 : CKeyID ToKeyID(const PKHash& key_hash)
      32             : {
      33         541 :     return CKeyID{static_cast<uint160>(key_hash)};
      34           0 : }
      35             : 
      36        1331 : CKeyID ToKeyID(const WitnessV0KeyHash& key_hash)
      37             : {
      38        1331 :     return CKeyID{static_cast<uint160>(key_hash)};
      39           0 : }
      40             : 
      41       24768 : WitnessV0ScriptHash::WitnessV0ScriptHash(const CScript& in)
      42       24768 : {
      43       12384 :     CSHA256().Write(in.data(), in.size()).Finalize(begin());
      44       24768 : }
      45             : 
      46       46731 : std::string GetTxnOutputType(TxoutType t)
      47             : {
      48       46731 :     switch (t)
      49             :     {
      50          36 :     case TxoutType::NONSTANDARD: return "nonstandard";
      51          30 :     case TxoutType::PUBKEY: return "pubkey";
      52       31426 :     case TxoutType::PUBKEYHASH: return "pubkeyhash";
      53        8462 :     case TxoutType::SCRIPTHASH: return "scripthash";
      54         224 :     case TxoutType::MULTISIG: return "multisig";
      55         102 :     case TxoutType::NULL_DATA: return "nulldata";
      56        6242 :     case TxoutType::WITNESS_V0_KEYHASH: return "witness_v0_keyhash";
      57         183 :     case TxoutType::WITNESS_V0_SCRIPTHASH: return "witness_v0_scripthash";
      58          26 :     case TxoutType::WITNESS_UNKNOWN: return "witness_unknown";
      59             :     } // no default case, so the compiler can warn about missing cases
      60           0 :     assert(false);
      61       46731 : }
      62             : 
      63     2065497 : static bool MatchPayToPubkey(const CScript& script, valtype& pubkey)
      64             : {
      65     2065497 :     if (script.size() == CPubKey::SIZE + 2 && script[0] == CPubKey::SIZE && script.back() == OP_CHECKSIG) {
      66        2091 :         pubkey = valtype(script.begin() + 1, script.begin() + CPubKey::SIZE + 1);
      67        2091 :         return CPubKey::ValidSize(pubkey);
      68             :     }
      69     2063406 :     if (script.size() == CPubKey::COMPRESSED_SIZE + 2 && script[0] == CPubKey::COMPRESSED_SIZE && script.back() == OP_CHECKSIG) {
      70       27139 :         pubkey = valtype(script.begin() + 1, script.begin() + CPubKey::COMPRESSED_SIZE + 1);
      71       27139 :         return CPubKey::ValidSize(pubkey);
      72             :     }
      73     2036267 :     return false;
      74     2065497 : }
      75             : 
      76     2036267 : static bool MatchPayToPubkeyHash(const CScript& script, valtype& pubkeyhash)
      77             : {
      78     2036267 :     if (script.size() == 25 && script[0] == OP_DUP && script[1] == OP_HASH160 && script[2] == 20 && script[23] == OP_EQUALVERIFY && script[24] == OP_CHECKSIG) {
      79     1768079 :         pubkeyhash = valtype(script.begin () + 3, script.begin() + 23);
      80     1768079 :         return true;
      81             :     }
      82      268188 :     return false;
      83     2036267 : }
      84             : 
      85             : /** Test for "small positive integer" script opcodes - OP_1 through OP_16. */
      86       21790 : static constexpr bool IsSmallInteger(opcodetype opcode)
      87             : {
      88       21790 :     return opcode >= OP_1 && opcode <= OP_16;
      89             : }
      90             : 
      91      268188 : static bool MatchMultisig(const CScript& script, unsigned int& required, std::vector<valtype>& pubkeys)
      92             : {
      93      268188 :     opcodetype opcode;
      94      268188 :     valtype data;
      95      268188 :     CScript::const_iterator it = script.begin();
      96      268188 :     if (script.size() < 1 || script.back() != OP_CHECKMULTISIG) return false;
      97             : 
      98       10896 :     if (!script.GetOp(it, opcode, data) || !IsSmallInteger(opcode)) return false;
      99       10894 :     required = CScript::DecodeOP_N(opcode);
     100       32234 :     while (script.GetOp(it, opcode, data) && CPubKey::ValidSize(data)) {
     101       21340 :         pubkeys.emplace_back(std::move(data));
     102             :     }
     103       10894 :     if (!IsSmallInteger(opcode)) return false;
     104       10892 :     unsigned int keys = CScript::DecodeOP_N(opcode);
     105       10892 :     if (pubkeys.size() != keys || keys < required) return false;
     106       10887 :     return (it + 1 == script.end());
     107      268188 : }
     108             : 
     109     3563264 : TxoutType Solver(const CScript& scriptPubKey, std::vector<std::vector<unsigned char>>& vSolutionsRet)
     110             : {
     111     3563264 :     vSolutionsRet.clear();
     112             : 
     113             :     // Shortcut for pay-to-script-hash, which are more constrained than the other types:
     114             :     // it is always OP_HASH160 20 [20 byte hash] OP_EQUAL
     115     3563264 :     if (scriptPubKey.IsPayToScriptHash())
     116             :     {
     117      188051 :         std::vector<unsigned char> hashBytes(scriptPubKey.begin()+2, scriptPubKey.begin()+22);
     118      188051 :         vSolutionsRet.push_back(hashBytes);
     119             :         return TxoutType::SCRIPTHASH;
     120      188051 :     }
     121             : 
     122     3375212 :     int witnessversion;
     123     3375212 :     std::vector<unsigned char> witnessprogram;
     124     3375212 :     if (scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)) {
     125      981718 :         if (witnessversion == 0 && witnessprogram.size() == WITNESS_V0_KEYHASH_SIZE) {
     126      944539 :             vSolutionsRet.push_back(witnessprogram);
     127      944540 :             return TxoutType::WITNESS_V0_KEYHASH;
     128             :         }
     129       37178 :         if (witnessversion == 0 && witnessprogram.size() == WITNESS_V0_SCRIPTHASH_SIZE) {
     130       36996 :             vSolutionsRet.push_back(witnessprogram);
     131       36996 :             return TxoutType::WITNESS_V0_SCRIPTHASH;
     132             :         }
     133         182 :         if (witnessversion != 0) {
     134         180 :             vSolutionsRet.push_back(std::vector<unsigned char>{(unsigned char)witnessversion});
     135         180 :             vSolutionsRet.push_back(std::move(witnessprogram));
     136         180 :             return TxoutType::WITNESS_UNKNOWN;
     137             :         }
     138           2 :         return TxoutType::NONSTANDARD;
     139             :     }
     140             : 
     141             :     // Provably prunable, data-carrying output
     142             :     //
     143             :     // So long as script passes the IsUnspendable() test and all but the first
     144             :     // byte passes the IsPushOnly() test we don't care what exactly is in the
     145             :     // script.
     146     2393494 :     if (scriptPubKey.size() >= 1 && scriptPubKey[0] == OP_RETURN && scriptPubKey.IsPushOnly(scriptPubKey.begin()+1)) {
     147      327997 :         return TxoutType::NULL_DATA;
     148             :     }
     149             : 
     150     2065497 :     std::vector<unsigned char> data;
     151     2065497 :     if (MatchPayToPubkey(scriptPubKey, data)) {
     152       29230 :         vSolutionsRet.push_back(std::move(data));
     153       29230 :         return TxoutType::PUBKEY;
     154             :     }
     155             : 
     156     2036267 :     if (MatchPayToPubkeyHash(scriptPubKey, data)) {
     157     1768079 :         vSolutionsRet.push_back(std::move(data));
     158     1768079 :         return TxoutType::PUBKEYHASH;
     159             :     }
     160             : 
     161      268188 :     unsigned int required;
     162      268188 :     std::vector<std::vector<unsigned char>> keys;
     163      268188 :     if (MatchMultisig(scriptPubKey, required, keys)) {
     164       10887 :         vSolutionsRet.push_back({static_cast<unsigned char>(required)}); // safe as required is in range 1..16
     165       10887 :         vSolutionsRet.insert(vSolutionsRet.end(), keys.begin(), keys.end());
     166       10887 :         vSolutionsRet.push_back({static_cast<unsigned char>(keys.size())}); // safe as size is in range 1..16
     167       10887 :         return TxoutType::MULTISIG;
     168             :     }
     169             : 
     170      257301 :     vSolutionsRet.clear();
     171      257301 :     return TxoutType::NONSTANDARD;
     172     3563262 : }
     173             : 
     174      491791 : bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet)
     175             : {
     176      491791 :     std::vector<valtype> vSolutions;
     177      491791 :     TxoutType whichType = Solver(scriptPubKey, vSolutions);
     178             : 
     179      491791 :     if (whichType == TxoutType::PUBKEY) {
     180         183 :         CPubKey pubKey(vSolutions[0]);
     181         183 :         if (!pubKey.IsValid())
     182           0 :             return false;
     183             : 
     184         183 :         addressRet = PKHash(pubKey);
     185         183 :         return true;
     186         183 :     }
     187      491608 :     else if (whichType == TxoutType::PUBKEYHASH)
     188             :     {
     189      221780 :         addressRet = PKHash(uint160(vSolutions[0]));
     190      221780 :         return true;
     191             :     }
     192      269828 :     else if (whichType == TxoutType::SCRIPTHASH)
     193             :     {
     194       17851 :         addressRet = ScriptHash(uint160(vSolutions[0]));
     195       17851 :         return true;
     196      251977 :     } else if (whichType == TxoutType::WITNESS_V0_KEYHASH) {
     197      154723 :         WitnessV0KeyHash hash;
     198      154723 :         std::copy(vSolutions[0].begin(), vSolutions[0].end(), hash.begin());
     199      154723 :         addressRet = hash;
     200             :         return true;
     201      251977 :     } else if (whichType == TxoutType::WITNESS_V0_SCRIPTHASH) {
     202        2006 :         WitnessV0ScriptHash hash;
     203        2006 :         std::copy(vSolutions[0].begin(), vSolutions[0].end(), hash.begin());
     204        2006 :         addressRet = hash;
     205             :         return true;
     206       97254 :     } else if (whichType == TxoutType::WITNESS_UNKNOWN) {
     207          17 :         WitnessUnknown unk;
     208          17 :         unk.version = vSolutions[0][0];
     209          17 :         std::copy(vSolutions[1].begin(), vSolutions[1].end(), unk.program);
     210          17 :         unk.length = vSolutions[1].size();
     211          17 :         addressRet = unk;
     212             :         return true;
     213          17 :     }
     214             :     // Multisig txns have more than one address...
     215       95231 :     return false;
     216      491791 : }
     217             : 
     218       45992 : bool ExtractDestinations(const CScript& scriptPubKey, TxoutType& typeRet, std::vector<CTxDestination>& addressRet, int& nRequiredRet)
     219             : {
     220       45992 :     addressRet.clear();
     221       45992 :     std::vector<valtype> vSolutions;
     222       45992 :     typeRet = Solver(scriptPubKey, vSolutions);
     223       45992 :     if (typeRet == TxoutType::NONSTANDARD) {
     224          11 :         return false;
     225       45981 :     } else if (typeRet == TxoutType::NULL_DATA) {
     226             :         // This is data, not addresses
     227          78 :         return false;
     228             :     }
     229             : 
     230       45903 :     if (typeRet == TxoutType::MULTISIG)
     231             :     {
     232           4 :         nRequiredRet = vSolutions.front()[0];
     233          14 :         for (unsigned int i = 1; i < vSolutions.size()-1; i++)
     234             :         {
     235          10 :             CPubKey pubKey(vSolutions[i]);
     236          10 :             if (!pubKey.IsValid())
     237           0 :                 continue;
     238             : 
     239          10 :             CTxDestination address = PKHash(pubKey);
     240          10 :             addressRet.push_back(address);
     241          10 :         }
     242             : 
     243           4 :         if (addressRet.empty())
     244           0 :             return false;
     245             :     }
     246             :     else
     247             :     {
     248       45899 :         nRequiredRet = 1;
     249       45899 :         CTxDestination address;
     250       45899 :         if (!ExtractDestination(scriptPubKey, address))
     251           0 :            return false;
     252       45899 :         addressRet.push_back(address);
     253       45899 :     }
     254             : 
     255       45903 :     return true;
     256       45992 : }
     257             : 
     258             : namespace
     259             : {
     260             : class CScriptVisitor : public boost::static_visitor<CScript>
     261             : {
     262             : public:
     263          28 :     CScript operator()(const CNoDestination& dest) const
     264             :     {
     265          28 :         return CScript();
     266             :     }
     267             : 
     268      395918 :     CScript operator()(const PKHash& keyID) const
     269             :     {
     270      395918 :         return CScript() << OP_DUP << OP_HASH160 << ToByteVector(keyID) << OP_EQUALVERIFY << OP_CHECKSIG;
     271           0 :     }
     272             : 
     273       49158 :     CScript operator()(const ScriptHash& scriptID) const
     274             :     {
     275       49158 :         return CScript() << OP_HASH160 << ToByteVector(scriptID) << OP_EQUAL;
     276           0 :     }
     277             : 
     278      225065 :     CScript operator()(const WitnessV0KeyHash& id) const
     279             :     {
     280      225065 :         return CScript() << OP_0 << ToByteVector(id);
     281           0 :     }
     282             : 
     283       15024 :     CScript operator()(const WitnessV0ScriptHash& id) const
     284             :     {
     285       15024 :         return CScript() << OP_0 << ToByteVector(id);
     286           0 :     }
     287             : 
     288          37 :     CScript operator()(const WitnessUnknown& id) const
     289             :     {
     290          37 :         return CScript() << CScript::EncodeOP_N(id.version) << std::vector<unsigned char>(id.program, id.program + id.length);
     291           0 :     }
     292             : };
     293             : } // namespace
     294             : 
     295      685230 : CScript GetScriptForDestination(const CTxDestination& dest)
     296             : {
     297      685230 :     return boost::apply_visitor(CScriptVisitor(), dest);
     298             : }
     299             : 
     300       66224 : CScript GetScriptForRawPubKey(const CPubKey& pubKey)
     301             : {
     302       66224 :     return CScript() << std::vector<unsigned char>(pubKey.begin(), pubKey.end()) << OP_CHECKSIG;
     303           0 : }
     304             : 
     305       12556 : CScript GetScriptForMultisig(int nRequired, const std::vector<CPubKey>& keys)
     306             : {
     307       12556 :     CScript script;
     308             : 
     309       12556 :     script << CScript::EncodeOP_N(nRequired);
     310       48323 :     for (const CPubKey& key : keys)
     311       35767 :         script << ToByteVector(key);
     312       12556 :     script << CScript::EncodeOP_N(keys.size()) << OP_CHECKMULTISIG;
     313             :     return script;
     314       12556 : }
     315             : 
     316       21156 : bool IsValidDestination(const CTxDestination& dest) {
     317       21156 :     return dest.which() != 0;
     318             : }

Generated by: LCOV version 1.15