LCOV - code coverage report
Current view: top level - src/script - standard.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 169 178 94.9 %
Date: 2025-02-23 09:33:43 Functions: 18 19 94.7 %

          Line data    Source code
       1             : // Copyright (c) 2009-2010 Satoshi Nakamoto
       2             : // Copyright (c) 2009-2014 The Bitcoin developers
       3             : // Copyright (c) 2017-2021 The PIVX Core developers
       4             : // Distributed under the MIT software license, see the accompanying
       5             : // file COPYING or https://www.opensource.org/licenses/mit-license.php.
       6             : 
       7             : #include "script/standard.h"
       8             : 
       9             : #include "pubkey.h"
      10             : #include "script/script.h"
      11             : 
      12             : typedef std::vector<unsigned char> valtype;
      13             : 
      14             : unsigned nMaxDatacarrierBytes = MAX_OP_RETURN_RELAY;
      15             : 
      16        1818 : CScriptID::CScriptID(const CScript& in) : uint160(Hash160(in.begin(), in.end())) {}
      17             : 
      18        1599 : const char* GetTxnOutputType(txnouttype t)
      19             : {
      20        1599 :     switch (t)
      21             :     {
      22             :     case TX_NONSTANDARD: return "nonstandard";
      23           1 :     case TX_PUBKEY: return "pubkey";
      24        1490 :     case TX_PUBKEYHASH: return "pubkeyhash";
      25           0 :     case TX_EXCHANGEADDR: return "exchangeaddress";
      26          15 :     case TX_SCRIPTHASH: return "scripthash";
      27           4 :     case TX_MULTISIG: return "multisig";
      28          52 :     case TX_COLDSTAKE: return "coldstake";
      29           4 :     case TX_NULL_DATA: return "nulldata";
      30             :     }
      31           0 :     return nullptr;
      32             : }
      33             : 
      34    14634285 : static bool MatchPayToPubkey(const CScript& script, valtype& pubkey)
      35             : {
      36    14662217 :     if (script.size() == CPubKey::PUBLIC_KEY_SIZE + 2 && script[0] == CPubKey::PUBLIC_KEY_SIZE && script.back() == OP_CHECKSIG) {
      37        2478 :         pubkey = valtype(script.begin() + 1, script.begin() + CPubKey::PUBLIC_KEY_SIZE + 1);
      38        1239 :         return CPubKey::ValidSize(pubkey);
      39             :     }
      40    14674526 :     if (script.size() == CPubKey::COMPRESSED_PUBLIC_KEY_SIZE + 2 && script[0] == CPubKey::COMPRESSED_PUBLIC_KEY_SIZE && script.back() == OP_CHECKSIG) {
      41       41446 :         pubkey = valtype(script.begin() + 1, script.begin() + CPubKey::COMPRESSED_PUBLIC_KEY_SIZE + 1);
      42       20723 :         return CPubKey::ValidSize(pubkey);
      43             :     }
      44             :     return false;
      45             : }
      46             : 
      47    14612345 : static bool MatchPayToPubkeyHash(const CScript& script, valtype& pubkeyhash)
      48             : {
      49    87483141 :     if (script.size() == 25 && script[0] == OP_DUP && script[1] == OP_HASH160 && script[2] == 20 && script[23] == OP_EQUALVERIFY && script[24] == OP_CHECKSIG) {
      50    29146932 :         pubkeyhash = valtype(script.begin () + 3, script.begin() + 23);
      51    14573466 :         return true;
      52             :     }
      53             :     return false;
      54             : }
      55             : 
      56       38429 : static bool MatchPayToColdStaking(const CScript& script, valtype& stakerPubKeyHash, valtype& ownerPubKeyHash)
      57             : {
      58       38429 :     if (script.IsPayToColdStaking()) {
      59        8139 :         stakerPubKeyHash = valtype(script.begin () + 6, script.begin() + 26);
      60        8139 :         ownerPubKeyHash = valtype(script.begin () + 28, script.begin() + 48);
      61        2713 :         return true;
      62             :     }
      63             :     return false;
      64             : }
      65             : 
      66             : /** Test for "small positive integer" script opcodes - OP_1 through OP_16. */
      67        1402 : static constexpr bool IsSmallInteger(opcodetype opcode)
      68             : {
      69        1402 :     return opcode >= OP_1 && opcode <= OP_16;
      70             : }
      71             : 
      72       35716 : static bool MatchMultisig(const CScript& script, unsigned int& required, std::vector<valtype>& pubkeys)
      73             : {
      74       35716 :     opcodetype opcode;
      75       71432 :     valtype data;
      76       35716 :     CScript::const_iterator it = script.begin();
      77       72171 :     if (script.size() < 1 || script.back() != OP_CHECKMULTISIG) return false;
      78             : 
      79         702 :     if (!script.GetOp(it, opcode, data) || !IsSmallInteger(opcode)) return false;
      80         700 :     required = CScript::DecodeOP_N(opcode);
      81        2876 :     while (script.GetOp(it, opcode, data) && CPubKey::ValidSize(data)) {
      82        2176 :         pubkeys.emplace_back(std::move(data));
      83             :     }
      84         700 :     if (!IsSmallInteger(opcode)) return false;
      85         698 :     unsigned int keys = CScript::DecodeOP_N(opcode);
      86         698 :     if (pubkeys.size() != keys || keys < required) return false;
      87        1386 :     return (it + 1 == script.end());
      88             : }
      89             : 
      90    15076754 : bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<std::vector<unsigned char> >& vSolutionsRet)
      91             : {
      92    15116367 :     if (scriptPubKey.empty())
      93             :         return false;
      94             : 
      95    14780358 :     vSolutionsRet.clear();
      96             : 
      97             :     // Shortcut for pay-to-script-hash, which are more constrained than the other types:
      98             :     // it is always OP_HASH160 20 [20 byte hash] OP_EQUAL
      99    14780358 :     if (scriptPubKey.IsPayToScriptHash())
     100             :     {
     101      131785 :         typeRet = TX_SCRIPTHASH;
     102      395355 :         std::vector<unsigned char> hashBytes(scriptPubKey.begin()+2, scriptPubKey.begin()+22);
     103      131785 :         vSolutionsRet.push_back(hashBytes);
     104      131785 :         return true;
     105             :     }
     106             : 
     107             :     // Provably prunable, data-carrying output
     108             :     //
     109             :     // So long as script passes the IsUnspendable() test and all but the first
     110             :     // byte passes the IsPushOnly() test we don't care what exactly is in the
     111             :     // script.
     112    29336817 :     if (scriptPubKey.size() >= 1 && scriptPubKey[0] == OP_RETURN && scriptPubKey.IsPushOnly(scriptPubKey.begin()+1)) {
     113       14274 :         typeRet = TX_NULL_DATA;
     114       14274 :         return true;
     115             :     }
     116             : 
     117    29711039 :     std::vector<unsigned char> data;
     118    14634285 :     if (MatchPayToPubkey(scriptPubKey, data)) {
     119       21962 :         typeRet = TX_PUBKEY;
     120       21962 :         vSolutionsRet.push_back(std::move(data));
     121             :         return true;
     122             :     }
     123             : 
     124    14612345 :     if (MatchPayToPubkeyHash(scriptPubKey, data)) {
     125    14573466 :         typeRet = TX_PUBKEYHASH;
     126    14573466 :         vSolutionsRet.push_back(std::move(data));
     127             :         return true;
     128             :     }
     129             : 
     130       38895 :     if (scriptPubKey.IsPayToExchangeAddress())
     131             :     {
     132         466 :         typeRet = TX_EXCHANGEADDR;
     133        1398 :         std::vector<unsigned char> hashBytes(scriptPubKey.begin()+4, scriptPubKey.begin()+24);
     134         466 :         vSolutionsRet.push_back(hashBytes);
     135         466 :         return true;
     136             :     }
     137             : 
     138             : 
     139    14672760 :     std::vector<unsigned char> data1;
     140       38429 :     if (MatchPayToColdStaking(scriptPubKey, data, data1)) {
     141        2713 :         typeRet = TX_COLDSTAKE;
     142        2713 :         vSolutionsRet.push_back(std::move(data));
     143       38429 :         vSolutionsRet.push_back(std::move(data1));
     144             :         return true;
     145             :     }
     146             : 
     147       35716 :     unsigned int required;
     148       71432 :     std::vector<std::vector<unsigned char>> keys;
     149       35716 :     if (MatchMultisig(scriptPubKey, required, keys)) {
     150         693 :         typeRet = TX_MULTISIG;
     151        1386 :         vSolutionsRet.push_back({static_cast<unsigned char>(required)}); // safe as required is in range 1..16
     152         693 :         vSolutionsRet.insert(vSolutionsRet.end(), keys.begin(), keys.end());
     153        1386 :         vSolutionsRet.push_back({static_cast<unsigned char>(keys.size())}); // safe as size is in range 1..16
     154         693 :         return true;
     155             :     }
     156             : 
     157       35023 :     vSolutionsRet.clear();
     158       35023 :     typeRet = TX_NONSTANDARD;
     159       35023 :     return false;
     160             : }
     161             : 
     162     3122441 : bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet, bool fColdStake)
     163             : {
     164     6244882 :     std::vector<valtype> vSolutions;
     165     3122441 :     txnouttype whichType;
     166     3122441 :     if (!Solver(scriptPubKey, whichType, vSolutions))
     167             :         return false;
     168             : 
     169     3121059 :     if (whichType == TX_PUBKEY) {
     170        1328 :         CPubKey pubKey(vSolutions[0]);
     171        2656 :         if (!pubKey.IsValid())
     172             :             return false;
     173             : 
     174        1328 :         addressRet = pubKey.GetID();
     175        1328 :         return true;
     176             : 
     177     3119732 :     } else if (whichType == TX_PUBKEYHASH) {
     178     3119403 :         addressRet = CKeyID(uint160(vSolutions[0]));
     179     3119403 :         return true;
     180             : 
     181         333 :     } else if (whichType == TX_SCRIPTHASH) {
     182          81 :         addressRet = CScriptID(uint160(vSolutions[0]));
     183          81 :         return true;
     184         252 :     } else if (whichType == TX_EXCHANGEADDR) {
     185          12 :         addressRet = CExchangeKeyID(uint160(vSolutions[0]));
     186          12 :         return true;
     187         240 :     } else if (whichType == TX_COLDSTAKE) {
     188         203 :         addressRet = CKeyID(uint160(vSolutions[!fColdStake]));
     189         203 :         return true;
     190             :     }
     191             :     // Multisig txns have more than one address...
     192             :     return false;
     193             : }
     194             : 
     195     1136701 : bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<CTxDestination>& addressRet, int& nRequiredRet)
     196             : {
     197     1136701 :     addressRet.clear();
     198     1136701 :     typeRet = TX_NONSTANDARD;
     199     2273392 :     std::vector<valtype> vSolutions;
     200     1136701 :     if (!Solver(scriptPubKey, typeRet, vSolutions))
     201             :         return false;
     202     1134299 :     if (typeRet == TX_NULL_DATA){
     203             :         // This is data, not addresses
     204             :         return false;
     205             :     }
     206             : 
     207     1134248 :     if (typeRet == TX_MULTISIG)
     208             :     {
     209          19 :         nRequiredRet = vSolutions.front()[0];
     210          69 :         for (unsigned int i = 1; i < vSolutions.size()-1; i++)
     211             :         {
     212          50 :             CPubKey pubKey(vSolutions[i]);
     213          50 :             if (!pubKey.IsValid())
     214           0 :                 continue;
     215             : 
     216         100 :             CTxDestination address = pubKey.GetID();
     217          50 :             addressRet.push_back(address);
     218             :         }
     219             : 
     220          19 :         if (addressRet.empty())
     221           0 :             return false;
     222             : 
     223     1134226 :     } else if (typeRet == TX_COLDSTAKE)
     224             :     {
     225         222 :         if (vSolutions.size() < 2)
     226             :             return false;
     227         222 :         nRequiredRet = 2;
     228         222 :         addressRet.push_back(CKeyID(uint160(vSolutions[0])));
     229         222 :         addressRet.push_back(CKeyID(uint160(vSolutions[1])));
     230         222 :         return true;
     231             : 
     232             :     } else
     233             :     {
     234     1134005 :         nRequiredRet = 1;
     235     2268010 :         CTxDestination address;
     236     1134005 :         if (!ExtractDestination(scriptPubKey, address))
     237           0 :            return false;
     238     1134005 :         addressRet.push_back(address);
     239             :     }
     240             : 
     241             :     return true;
     242             : }
     243             : 
     244             : namespace
     245             : {
     246             : class CScriptVisitor : public boost::static_visitor<bool>
     247             : {
     248             : private:
     249             :     CScript *script;
     250             : public:
     251       46990 :     explicit CScriptVisitor(CScript *scriptin) { script = scriptin; }
     252             : 
     253          23 :     bool operator()(const CNoDestination &dest) const {
     254          23 :         script->clear();
     255          23 :         return false;
     256             :     }
     257             : 
     258       46851 :     bool operator()(const CKeyID &keyID) const {
     259       46851 :         script->clear();
     260       46851 :         *script << OP_DUP << OP_HASH160 << ToByteVector(keyID) << OP_EQUALVERIFY << OP_CHECKSIG;
     261       46851 :         return true;
     262             :     }
     263             : 
     264           6 :     bool operator()(const CExchangeKeyID &keyID) const {
     265           6 :         script->clear();
     266           6 :         *script << OP_EXCHANGEADDR << OP_DUP << OP_HASH160 << ToByteVector(keyID) << OP_EQUALVERIFY << OP_CHECKSIG;
     267           6 :         return true;
     268             :     }
     269             : 
     270         110 :     bool operator()(const CScriptID &scriptID) const {
     271         110 :         script->clear();
     272         110 :         *script << OP_HASH160 << ToByteVector(scriptID) << OP_EQUAL;
     273         110 :         return true;
     274             :     }
     275             : };
     276             : }
     277             : 
     278       46990 : CScript GetScriptForDestination(const CTxDestination& dest)
     279             : {
     280       46990 :     CScript script;
     281             : 
     282       46990 :     boost::apply_visitor(CScriptVisitor(&script), dest);
     283       46990 :     return script;
     284             : }
     285             : 
     286       26911 : CScript GetScriptForRawPubKey(const CPubKey& pubKey)
     287             : {
     288       80733 :     return CScript() << std::vector<unsigned char>(pubKey.begin(), pubKey.end()) << OP_CHECKSIG;
     289             : }
     290             : 
     291           4 : CScript GetScriptForStakeDelegation(const CKeyID& stakingKey, const CKeyID& spendingKey)
     292             : {
     293           4 :     CScript script;
     294           4 :     script << OP_DUP << OP_HASH160 << OP_ROT <<
     295           4 :             OP_IF << OP_CHECKCOLDSTAKEVERIFY << ToByteVector(stakingKey) <<
     296           8 :             OP_ELSE << ToByteVector(spendingKey) << OP_ENDIF <<
     297           4 :             OP_EQUALVERIFY << OP_CHECKSIG;
     298           4 :     return script;
     299             : }
     300             : 
     301          32 : CScript GetScriptForStakeDelegationLOF(const CKeyID& stakingKey, const CKeyID& spendingKey)
     302             : {
     303          32 :     CScript script;
     304          32 :     script << OP_DUP << OP_HASH160 << OP_ROT <<
     305          32 :             OP_IF << OP_CHECKCOLDSTAKEVERIFY_LOF << ToByteVector(stakingKey) <<
     306          64 :             OP_ELSE << ToByteVector(spendingKey) << OP_ENDIF <<
     307          32 :             OP_EQUALVERIFY << OP_CHECKSIG;
     308          32 :     return script;
     309             : }
     310             : 
     311          25 : CScript GetScriptForMultisig(int nRequired, const std::vector<CPubKey>& keys)
     312             : {
     313          25 :     CScript script;
     314             : 
     315          50 :     script << CScript::EncodeOP_N(nRequired);
     316         127 :     for (const CPubKey& key : keys)
     317         204 :         script << ToByteVector(key);
     318          50 :     script << CScript::EncodeOP_N(keys.size()) << OP_CHECKMULTISIG;
     319          25 :     return script;
     320             : }
     321             : 
     322           0 : CScript GetScriptForOpReturn(const uint256& message)
     323             : {
     324           0 :     CScript script;
     325           0 :     script << OP_RETURN << ToByteVector(message);
     326           0 :     return script;
     327             : }
     328             : 
     329       16799 : bool IsValidDestination(const CTxDestination& dest) {
     330       16799 :     return dest.which() != 0;
     331             : }
     332             : 

Generated by: LCOV version 1.14