LCOV - code coverage report
Current view: top level - src/script - standard.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 114 120 95.0 %
Date: 2015-10-12 22:39:14 Functions: 13 14 92.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2009-2010 Satoshi Nakamoto
       2             : // Copyright (c) 2009-2014 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 "pubkey.h"
       9             : #include "script/script.h"
      10             : #include "util.h"
      11             : #include "utilstrencodings.h"
      12             : 
      13             : #include <boost/foreach.hpp>
      14             : 
      15             : using namespace std;
      16             : 
      17             : typedef vector<unsigned char> valtype;
      18             : 
      19             : unsigned nMaxDatacarrierBytes = MAX_OP_RETURN_RELAY;
      20             : 
      21         237 : CScriptID::CScriptID(const CScript& in) : uint160(Hash160(in.begin(), in.end())) {}
      22             : 
      23         114 : const char* GetTxnOutputType(txnouttype t)
      24             : {
      25         114 :     switch (t)
      26             :     {
      27             :     case TX_NONSTANDARD: return "nonstandard";
      28           4 :     case TX_PUBKEY: return "pubkey";
      29          89 :     case TX_PUBKEYHASH: return "pubkeyhash";
      30           9 :     case TX_SCRIPTHASH: return "scripthash";
      31           3 :     case TX_MULTISIG: return "multisig";
      32           4 :     case TX_NULL_DATA: return "nulldata";
      33             :     }
      34           0 :     return NULL;
      35             : }
      36             : 
      37             : /**
      38             :  * Return public keys or hashes from scriptPubKey, for 'standard' transaction types.
      39             :  */
      40       37305 : bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, vector<vector<unsigned char> >& vSolutionsRet)
      41             : {
      42             :     // Templates
      43       37401 :     static multimap<txnouttype, CScript> mTemplates;
      44       37305 :     if (mTemplates.empty())
      45             :     {
      46             :         // Standard tx, sender provides pubkey, receiver adds signature
      47         576 :         mTemplates.insert(make_pair(TX_PUBKEY, CScript() << OP_PUBKEY << OP_CHECKSIG));
      48             : 
      49             :         // Bitcoin address tx, sender provides hash of pubkey, receiver provides signature and pubkey
      50         576 :         mTemplates.insert(make_pair(TX_PUBKEYHASH, CScript() << OP_DUP << OP_HASH160 << OP_PUBKEYHASH << OP_EQUALVERIFY << OP_CHECKSIG));
      51             : 
      52             :         // Sender provides N pubkeys, receivers provides M signatures
      53         576 :         mTemplates.insert(make_pair(TX_MULTISIG, CScript() << OP_SMALLINTEGER << OP_PUBKEYS << OP_SMALLINTEGER << OP_CHECKMULTISIG));
      54             :     }
      55             : 
      56             :     vSolutionsRet.clear();
      57             : 
      58             :     // Shortcut for pay-to-script-hash, which are more constrained than the other types:
      59             :     // it is always OP_HASH160 20 [20 byte hash] OP_EQUAL
      60       37305 :     if (scriptPubKey.IsPayToScriptHash())
      61             :     {
      62         484 :         typeRet = TX_SCRIPTHASH;
      63        2904 :         vector<unsigned char> hashBytes(scriptPubKey.begin()+2, scriptPubKey.begin()+22);
      64         484 :         vSolutionsRet.push_back(hashBytes);
      65         484 :         return true;
      66             :     }
      67             : 
      68             :     // Provably prunable, data-carrying output
      69             :     //
      70             :     // So long as script passes the IsUnspendable() test and all but the first
      71             :     // byte passes the IsPushOnly() test we don't care what exactly is in the
      72             :     // script.
      73       73678 :     if (scriptPubKey.size() >= 1 && scriptPubKey[0] == OP_RETURN && scriptPubKey.IsPushOnly(scriptPubKey.begin()+1)) {
      74          17 :         typeRet = TX_NULL_DATA;
      75          17 :         return true;
      76             :     }
      77             : 
      78             :     // Scan templates
      79       36804 :     const CScript& script1 = scriptPubKey;
      80      396570 :     BOOST_FOREACH(const PAIRTYPE(txnouttype, CScript)& tplate, mTemplates)
      81             :     {
      82       53649 :         const CScript& script2 = tplate.second;
      83             :         vSolutionsRet.clear();
      84             : 
      85             :         opcodetype opcode1, opcode2;
      86             :         vector<unsigned char> vch1, vch2;
      87             : 
      88             :         // Compare
      89      107298 :         CScript::const_iterator pc1 = script1.begin();
      90      107298 :         CScript::const_iterator pc2 = script2.begin();
      91             :         while (true)
      92             :         {
      93      598999 :             if (pc1 == script1.end() && pc2 == script2.end())
      94             :             {
      95             :                 // Found a match
      96       36537 :                 typeRet = tplate.first;
      97       36537 :                 if (typeRet == TX_MULTISIG)
      98             :                 {
      99             :                     // Additional checks for TX_MULTISIG:
     100         138 :                     unsigned char m = vSolutionsRet.front()[0];
     101         138 :                     unsigned char n = vSolutionsRet.back()[0];
     102         273 :                     if (m < 1 || n < 1 || m > n || vSolutionsRet.size()-2 != n)
     103             :                         return false;
     104             :                 }
     105       36533 :                 return true;
     106             :             }
     107      138506 :             if (!script1.GetOp(pc1, opcode1, vch1))
     108             :                 break;
     109      137979 :             if (!script2.GetOp(pc2, opcode2, vch2))
     110             :                 break;
     111             : 
     112             :             // Template matching opcodes:
     113      137979 :             if (opcode2 == OP_PUBKEYS)
     114             :             {
     115        1032 :                 while (vch1.size() >= 33 && vch1.size() <= 65)
     116             :                 {
     117         372 :                     vSolutionsRet.push_back(vch1);
     118         372 :                     if (!script1.GetOp(pc1, opcode1, vch1))
     119             :                         break;
     120             :                 }
     121         145 :                 if (!script2.GetOp(pc2, opcode2, vch2))
     122             :                     break;
     123             :                 // Normal situation is to fall through
     124             :                 // to other if/else statements
     125             :             }
     126             : 
     127      137979 :             if (opcode2 == OP_PUBKEY)
     128             :             {
     129       73302 :                 if (vch1.size() < 33 || vch1.size() > 65)
     130             :                     break;
     131       20364 :                 vSolutionsRet.push_back(vch1);
     132             :             }
     133      101328 :             else if (opcode2 == OP_PUBKEYHASH)
     134             :             {
     135       32070 :                 if (vch1.size() != sizeof(uint160))
     136             :                     break;
     137       16035 :                 vSolutionsRet.push_back(vch1);
     138             :             }
     139       85293 :             else if (opcode2 == OP_SMALLINTEGER)
     140             :             {   // Single-byte small integer pushed onto vSolutions
     141         397 :                 if (opcode1 == OP_0 ||
     142             :                     (opcode1 >= OP_1 && opcode1 <= OP_16))
     143             :                 {
     144         353 :                     char n = (char)CScript::DecodeOP_N(opcode1);
     145        1059 :                     vSolutionsRet.push_back(valtype(1, n));
     146             :                 }
     147             :                 else
     148             :                     break;
     149             :             }
     150      169538 :             else if (opcode1 != opcode2 || vch1 != vch2)
     151             :             {
     152             :                 // Others must match exactly
     153             :                 break;
     154             :             }
     155             :         }
     156             :     }
     157             : 
     158             :     vSolutionsRet.clear();
     159         267 :     typeRet = TX_NONSTANDARD;
     160         267 :     return false;
     161             : }
     162             : 
     163          24 : int ScriptSigArgsExpected(txnouttype t, const std::vector<std::vector<unsigned char> >& vSolutions)
     164             : {
     165          24 :     switch (t)
     166             :     {
     167             :     case TX_NONSTANDARD:
     168             :     case TX_NULL_DATA:
     169             :         return -1;
     170             :     case TX_PUBKEY:
     171           6 :         return 1;
     172             :     case TX_PUBKEYHASH:
     173           9 :         return 2;
     174             :     case TX_MULTISIG:
     175           6 :         if (vSolutions.size() < 1 || vSolutions[0].size() < 1)
     176             :             return -1;
     177           2 :         return vSolutions[0][0] + 1;
     178             :     case TX_SCRIPTHASH:
     179           7 :         return 1; // doesn't include args needed by the script
     180             :     }
     181             :     return -1;
     182             : }
     183             : 
     184        1545 : bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet)
     185             : {
     186             :     vector<valtype> vSolutions;
     187             :     txnouttype whichType;
     188        1545 :     if (!Solver(scriptPubKey, whichType, vSolutions))
     189             :         return false;
     190             : 
     191        1545 :     if (whichType == TX_PUBKEY)
     192             :     {
     193         992 :         CPubKey pubKey(vSolutions[0]);
     194         992 :         if (!pubKey.IsValid())
     195             :             return false;
     196             : 
     197        1984 :         addressRet = pubKey.GetID();
     198         992 :         return true;
     199             :     }
     200         553 :     else if (whichType == TX_PUBKEYHASH)
     201             :     {
     202        1076 :         addressRet = CKeyID(uint160(vSolutions[0]));
     203         538 :         return true;
     204             :     }
     205          15 :     else if (whichType == TX_SCRIPTHASH)
     206             :     {
     207          28 :         addressRet = CScriptID(uint160(vSolutions[0]));
     208          14 :         return true;
     209             :     }
     210             :     // Multisig txns have more than one address...
     211        1545 :     return false;
     212             : }
     213             : 
     214         115 : bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, vector<CTxDestination>& addressRet, int& nRequiredRet)
     215             : {
     216         115 :     addressRet.clear();
     217         115 :     typeRet = TX_NONSTANDARD;
     218             :     vector<valtype> vSolutions;
     219         115 :     if (!Solver(scriptPubKey, typeRet, vSolutions))
     220             :         return false;
     221         110 :     if (typeRet == TX_NULL_DATA){
     222             :         // This is data, not addresses
     223             :         return false;
     224             :     }
     225             : 
     226         106 :     if (typeRet == TX_MULTISIG)
     227             :     {
     228           4 :         nRequiredRet = vSolutions.front()[0];
     229          28 :         for (unsigned int i = 1; i < vSolutions.size()-1; i++)
     230             :         {
     231          20 :             CPubKey pubKey(vSolutions[i]);
     232          10 :             if (!pubKey.IsValid())
     233           0 :                 continue;
     234             : 
     235          20 :             CTxDestination address = pubKey.GetID();
     236          10 :             addressRet.push_back(address);
     237             :         }
     238             : 
     239           4 :         if (addressRet.empty())
     240             :             return false;
     241             :     }
     242             :     else
     243             :     {
     244         102 :         nRequiredRet = 1;
     245             :         CTxDestination address;
     246         102 :         if (!ExtractDestination(scriptPubKey, address))
     247           0 :            return false;
     248         102 :         addressRet.push_back(address);
     249             :     }
     250             : 
     251         115 :     return true;
     252             : }
     253             : 
     254             : namespace
     255             : {
     256        2542 : class CScriptVisitor : public boost::static_visitor<bool>
     257             : {
     258             : private:
     259             :     CScript *script;
     260             : public:
     261        2542 :     CScriptVisitor(CScript *scriptin) { script = scriptin; }
     262             : 
     263           0 :     bool operator()(const CNoDestination &dest) const {
     264           0 :         script->clear();
     265           0 :         return false;
     266             :     }
     267             : 
     268        2496 :     bool operator()(const CKeyID &keyID) const {
     269        2496 :         script->clear();
     270        4992 :         *script << OP_DUP << OP_HASH160 << ToByteVector(keyID) << OP_EQUALVERIFY << OP_CHECKSIG;
     271        2496 :         return true;
     272             :     }
     273             : 
     274          46 :     bool operator()(const CScriptID &scriptID) const {
     275          46 :         script->clear();
     276          92 :         *script << OP_HASH160 << ToByteVector(scriptID) << OP_EQUAL;
     277          46 :         return true;
     278             :     }
     279             : };
     280             : }
     281             : 
     282        2542 : CScript GetScriptForDestination(const CTxDestination& dest)
     283             : {
     284             :     CScript script;
     285             : 
     286        2542 :     boost::apply_visitor(CScriptVisitor(&script), dest);
     287        2542 :     return script;
     288             : }
     289             : 
     290        1394 : CScript GetScriptForRawPubKey(const CPubKey& pubKey)
     291             : {
     292        8364 :     return CScript() << std::vector<unsigned char>(pubKey.begin(), pubKey.end()) << OP_CHECKSIG;
     293             : }
     294             : 
     295          15 : CScript GetScriptForMultisig(int nRequired, const std::vector<CPubKey>& keys)
     296             : {
     297             :     CScript script;
     298             : 
     299          15 :     script << CScript::EncodeOP_N(nRequired);
     300         255 :     BOOST_FOREACH(const CPubKey& key, keys)
     301          72 :         script << ToByteVector(key);
     302          30 :     script << CScript::EncodeOP_N(keys.size()) << OP_CHECKMULTISIG;
     303          15 :     return script;
     304         330 : }

Generated by: LCOV version 1.11