LCOV - code coverage report
Current view: top level - src/script - sign.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 127 128 99.2 %
Date: 2015-10-12 22:39:14 Functions: 19 20 95.0 %
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/sign.h"
       7             : 
       8             : #include "key.h"
       9             : #include "keystore.h"
      10             : #include "policy/policy.h"
      11             : #include "primitives/transaction.h"
      12             : #include "script/standard.h"
      13             : #include "uint256.h"
      14             : 
      15             : #include <boost/foreach.hpp>
      16             : 
      17             : using namespace std;
      18             : 
      19             : typedef vector<unsigned char> valtype;
      20             : 
      21        2066 : TransactionSignatureCreator::TransactionSignatureCreator(const CKeyStore* keystoreIn, const CTransaction* txToIn, unsigned int nInIn, int nHashTypeIn) : BaseSignatureCreator(keystoreIn), txTo(txToIn), nIn(nInIn), nHashType(nHashTypeIn), checker(txTo, nIn) {}
      22             : 
      23         749 : bool TransactionSignatureCreator::CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& address, const CScript& scriptCode) const
      24             : {
      25             :     CKey key;
      26         749 :     if (!keystore->GetKey(address, key))
      27             :         return false;
      28             : 
      29         744 :     uint256 hash = SignatureHash(scriptCode, *txTo, nIn, nHashType);
      30         744 :     if (!key.Sign(hash, vchSig))
      31             :         return false;
      32         744 :     vchSig.push_back((unsigned char)nHashType);
      33         744 :     return true;
      34             : }
      35             : 
      36         937 : static bool Sign1(const CKeyID& address, const BaseSignatureCreator& creator, const CScript& scriptCode, CScript& scriptSigRet)
      37             : {
      38             :     vector<unsigned char> vchSig;
      39         937 :     if (!creator.CreateSig(vchSig, address, scriptCode))
      40             :         return false;
      41         932 :     scriptSigRet << vchSig;
      42             :     return true;
      43             : }
      44             : 
      45          26 : static bool SignN(const vector<valtype>& multisigdata, const BaseSignatureCreator& creator, const CScript& scriptCode, CScript& scriptSigRet)
      46             : {
      47          26 :     int nSigned = 0;
      48          26 :     int nRequired = multisigdata.front()[0];
      49         136 :     for (unsigned int i = 1; i < multisigdata.size()-1 && nSigned < nRequired; i++)
      50             :     {
      51          84 :         const valtype& pubkey = multisigdata[i];
      52          42 :         CKeyID keyID = CPubKey(pubkey).GetID();
      53          42 :         if (Sign1(keyID, creator, scriptCode, scriptSigRet))
      54          39 :             ++nSigned;
      55             :     }
      56          26 :     return nSigned==nRequired;
      57             : }
      58             : 
      59             : /**
      60             :  * Sign scriptPubKey using signature made with creator.
      61             :  * Signatures are returned in scriptSigRet (or returns false if scriptPubKey can't be signed),
      62             :  * unless whichTypeRet is TX_SCRIPTHASH, in which case scriptSigRet is the redemption script.
      63             :  * Returns false if scriptPubKey could not be completely satisfied.
      64             :  */
      65         946 : static bool SignStep(const BaseSignatureCreator& creator, const CScript& scriptPubKey,
      66             :                      CScript& scriptSigRet, txnouttype& whichTypeRet)
      67             : {
      68             :     scriptSigRet.clear();
      69             : 
      70             :     vector<valtype> vSolutions;
      71         946 :     if (!Solver(scriptPubKey, whichTypeRet, vSolutions))
      72             :         return false;
      73             : 
      74             :     CKeyID keyID;
      75         945 :     switch (whichTypeRet)
      76             :     {
      77             :     case TX_NONSTANDARD:
      78             :     case TX_NULL_DATA:
      79             :         return false;
      80             :     case TX_PUBKEY:
      81         588 :         keyID = CPubKey(vSolutions[0]).GetID();
      82         294 :         return Sign1(keyID, creator, scriptPubKey, scriptSigRet);
      83             :     case TX_PUBKEYHASH:
      84        1202 :         keyID = CKeyID(uint160(vSolutions[0]));
      85         601 :         if (!Sign1(keyID, creator, scriptPubKey, scriptSigRet))
      86             :             return false;
      87             :         else
      88             :         {
      89             :             CPubKey vch;
      90         599 :             creator.KeyStore().GetPubKey(keyID, vch);
      91        1198 :             scriptSigRet << ToByteVector(vch);
      92             :         }
      93         599 :         return true;
      94             :     case TX_SCRIPTHASH:
      95          48 :         return creator.KeyStore().GetCScript(uint160(vSolutions[0]), scriptSigRet);
      96             : 
      97             :     case TX_MULTISIG:
      98          26 :         scriptSigRet << OP_0; // workaround CHECKMULTISIG bug
      99          26 :         return (SignN(vSolutions, creator, scriptPubKey, scriptSigRet));
     100             :     }
     101         946 :     return false;
     102             : }
     103             : 
     104         923 : bool ProduceSignature(const BaseSignatureCreator& creator, const CScript& fromPubKey, CScript& scriptSig)
     105             : {
     106             :     txnouttype whichType;
     107         923 :     if (!SignStep(creator, fromPubKey, scriptSig, whichType))
     108             :         return false;
     109             : 
     110         919 :     if (whichType == TX_SCRIPTHASH)
     111             :     {
     112             :         // Solver returns the subscript that need to be evaluated;
     113             :         // the final scriptSig is the signatures from that
     114             :         // and then the serialized subscript:
     115             :         CScript subscript = scriptSig;
     116             : 
     117             :         txnouttype subType;
     118             :         bool fSolved =
     119          23 :             SignStep(creator, subscript, scriptSig, subType) && subType != TX_SCRIPTHASH;
     120             :         // Append serialized subscript whether or not it is completely signed:
     121          46 :         scriptSig << static_cast<valtype>(subscript);
     122          23 :         if (!fSolved) return false;
     123             :     }
     124             : 
     125             :     // Test solution
     126         918 :     return VerifyScript(scriptSig, fromPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, creator.Checker());
     127             : }
     128             : 
     129         139 : bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, int nHashType)
     130             : {
     131         278 :     assert(nIn < txTo.vin.size());
     132         278 :     CTxIn& txin = txTo.vin[nIn];
     133             : 
     134         139 :     CTransaction txToConst(txTo);
     135             :     TransactionSignatureCreator creator(&keystore, &txToConst, nIn, nHashType);
     136             : 
     137         278 :     return ProduceSignature(creator, fromPubKey, txin.scriptSig);
     138             : }
     139             : 
     140          83 : bool SignSignature(const CKeyStore &keystore, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType)
     141             : {
     142         166 :     assert(nIn < txTo.vin.size());
     143         166 :     CTxIn& txin = txTo.vin[nIn];
     144         166 :     assert(txin.prevout.n < txFrom.vout.size());
     145         166 :     const CTxOut& txout = txFrom.vout[txin.prevout.n];
     146             : 
     147          83 :     return SignSignature(keystore, txout.scriptPubKey, txTo, nIn, nHashType);
     148             : }
     149             : 
     150          65 : static CScript PushAll(const vector<valtype>& values)
     151             : {
     152             :     CScript result;
     153         979 :     BOOST_FOREACH(const valtype& v, values)
     154         109 :         result << v;
     155          65 :     return result;
     156             : }
     157             : 
     158          10 : static CScript CombineMultisig(const CScript& scriptPubKey, const BaseSignatureChecker& checker,
     159             :                                const vector<valtype>& vSolutions,
     160             :                                const vector<valtype>& sigs1, const vector<valtype>& sigs2)
     161             : {
     162             :     // Combine all the signatures we've got:
     163             :     set<valtype> allsigs;
     164         200 :     BOOST_FOREACH(const valtype& v, sigs1)
     165             :     {
     166          25 :         if (!v.empty())
     167             :             allsigs.insert(v);
     168             :     }
     169         170 :     BOOST_FOREACH(const valtype& v, sigs2)
     170             :     {
     171          20 :         if (!v.empty())
     172             :             allsigs.insert(v);
     173             :     }
     174             : 
     175             :     // Build a map of pubkey -> signature by matching sigs to pubkeys:
     176          20 :     assert(vSolutions.size() > 1);
     177          10 :     unsigned int nSigsRequired = vSolutions.front()[0];
     178          10 :     unsigned int nPubKeys = vSolutions.size()-2;
     179             :     map<valtype, valtype> sigs;
     180         168 :     BOOST_FOREACH(const valtype& sig, allsigs)
     181             :     {
     182          15 :         for (unsigned int i = 0; i < nPubKeys; i++)
     183             :         {
     184          66 :             const valtype& pubkey = vSolutions[i+1];
     185          33 :             if (sigs.count(pubkey))
     186             :                 continue; // Already got a sig for this pubkey
     187             : 
     188          30 :             if (checker.CheckSig(sig, pubkey, scriptPubKey))
     189             :             {
     190          18 :                 sigs[pubkey] = sig;
     191             :                 break;
     192             :             }
     193             :         }
     194             :     }
     195             :     // Now build a merged CScript:
     196          10 :     unsigned int nSigsHave = 0;
     197          10 :     CScript result; result << OP_0; // pop-one-too-many workaround
     198          25 :     for (unsigned int i = 0; i < nPubKeys && nSigsHave < nSigsRequired; i++)
     199             :     {
     200          75 :         if (sigs.count(vSolutions[i+1]))
     201             :         {
     202          36 :             result << sigs[vSolutions[i+1]];
     203          18 :             ++nSigsHave;
     204             :         }
     205             :     }
     206             :     // Fill any missing with OP_0:
     207          12 :     for (unsigned int i = nSigsHave; i < nSigsRequired; i++)
     208           2 :         result << OP_0;
     209             : 
     210          10 :     return result;
     211             : }
     212             : 
     213          78 : static CScript CombineSignatures(const CScript& scriptPubKey, const BaseSignatureChecker& checker,
     214             :                                  const txnouttype txType, const vector<valtype>& vSolutions,
     215             :                                  vector<valtype>& sigs1, vector<valtype>& sigs2)
     216             : {
     217          78 :     switch (txType)
     218             :     {
     219             :     case TX_NONSTANDARD:
     220             :     case TX_NULL_DATA:
     221             :         // Don't know anything about this, assume bigger one is correct:
     222           3 :         if (sigs1.size() >= sigs2.size())
     223           1 :             return PushAll(sigs1);
     224           0 :         return PushAll(sigs2);
     225             :     case TX_PUBKEY:
     226             :     case TX_PUBKEYHASH:
     227             :         // Signatures are bigger than placeholders or empty scripts:
     228         112 :         if (sigs1.empty() || sigs1[0].empty())
     229           5 :             return PushAll(sigs2);
     230          53 :         return PushAll(sigs1);
     231             :     case TX_SCRIPTHASH:
     232          23 :         if (sigs1.empty() || sigs1.back().empty())
     233           2 :             return PushAll(sigs2);
     234          13 :         else if (sigs2.empty() || sigs2.back().empty())
     235           4 :             return PushAll(sigs1);
     236             :         else
     237             :         {
     238             :             // Recur to combine:
     239           3 :             valtype spk = sigs1.back();
     240           9 :             CScript pubKey2(spk.begin(), spk.end());
     241             : 
     242             :             txnouttype txType2;
     243           3 :             vector<vector<unsigned char> > vSolutions2;
     244           3 :             Solver(pubKey2, txType2, vSolutions2);
     245           3 :             sigs1.pop_back();
     246           3 :             sigs2.pop_back();
     247           3 :             CScript result = CombineSignatures(pubKey2, checker, txType2, vSolutions2, sigs1, sigs2);
     248           3 :             result << spk;
     249             :             return result;
     250             :         }
     251             :     case TX_MULTISIG:
     252          10 :         return CombineMultisig(scriptPubKey, checker, vSolutions, sigs1, sigs2);
     253             :     }
     254             : 
     255             :     return CScript();
     256             : }
     257             : 
     258          75 : CScript CombineSignatures(const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn,
     259             :                           const CScript& scriptSig1, const CScript& scriptSig2)
     260             : {
     261             :     TransactionSignatureChecker checker(&txTo, nIn);
     262         150 :     return CombineSignatures(scriptPubKey, checker, scriptSig1, scriptSig2);
     263             : }
     264             : 
     265          75 : CScript CombineSignatures(const CScript& scriptPubKey, const BaseSignatureChecker& checker,
     266             :                           const CScript& scriptSig1, const CScript& scriptSig2)
     267             : {
     268             :     txnouttype txType;
     269             :     vector<vector<unsigned char> > vSolutions;
     270          75 :     Solver(scriptPubKey, txType, vSolutions);
     271             : 
     272          75 :     vector<valtype> stack1;
     273         225 :     EvalScript(stack1, scriptSig1, SCRIPT_VERIFY_STRICTENC, BaseSignatureChecker());
     274          75 :     vector<valtype> stack2;
     275         225 :     EvalScript(stack2, scriptSig2, SCRIPT_VERIFY_STRICTENC, BaseSignatureChecker());
     276             : 
     277         150 :     return CombineSignatures(scriptPubKey, checker, txType, vSolutions, stack1, stack2);
     278             : }
     279             : 
     280             : namespace {
     281             : /** Dummy signature checker which accepts all signatures. */
     282         220 : class DummySignatureChecker : public BaseSignatureChecker
     283             : {
     284             : public:
     285         220 :     DummySignatureChecker() {}
     286             : 
     287         187 :     bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode) const
     288             :     {
     289         187 :         return true;
     290             :     }
     291             : };
     292         110 : const DummySignatureChecker dummyChecker;
     293             : }
     294             : 
     295         188 : const BaseSignatureChecker& DummySignatureCreator::Checker() const
     296             : {
     297         188 :     return dummyChecker;
     298             : }
     299             : 
     300         188 : bool DummySignatureCreator::CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode) const
     301             : {
     302             :     // Create a dummy signature that is a valid DER-encoding
     303         376 :     vchSig.assign(72, '\000');
     304         188 :     vchSig[0] = 0x30;
     305         188 :     vchSig[1] = 69;
     306         188 :     vchSig[2] = 0x02;
     307         188 :     vchSig[3] = 33;
     308         188 :     vchSig[4] = 0x01;
     309         188 :     vchSig[4 + 33] = 0x02;
     310         188 :     vchSig[5 + 33] = 32;
     311         188 :     vchSig[6 + 33] = 0x01;
     312         188 :     vchSig[6 + 33 + 32] = SIGHASH_ALL;
     313         188 :     return true;
     314         330 : }

Generated by: LCOV version 1.11