LCOV - code coverage report
Current view: top level - src/script - sign.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 206 230 89.6 %
Date: 2025-02-23 09:33:43 Functions: 22 29 75.9 %

          Line data    Source code
       1             : // Copyright (c) 2009-2010 Satoshi Nakamoto
       2             : // Copyright (c) 2009-2014 The Bitcoin developers
       3             : // Copyright (c) 2016-2022 The PIVX Core developers
       4             : // Distributed under the MIT software license, see the accompanying
       5             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       6             : 
       7             : #include "script/sign.h"
       8             : 
       9             : #include "key.h"
      10             : #include "keystore.h"
      11             : #include "policy/policy.h"
      12             : #include "primitives/transaction.h"
      13             : #include "script/standard.h"
      14             : #include "uint256.h"
      15             : #include "util/system.h"
      16             : 
      17             : typedef std::vector<unsigned char> valtype;
      18             : 
      19      211377 : TransactionSignatureCreator::TransactionSignatureCreator(const CKeyStore* keystoreIn, const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, int nHashTypeIn) : BaseSignatureCreator(keystoreIn), txTo(txToIn), nIn(nInIn), nHashType(nHashTypeIn), amount(amountIn), checker(txTo, nIn, amountIn) {}
      20             : 
      21      211391 : bool TransactionSignatureCreator::CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& address, const CScript& scriptCode, SigVersion sigversion) const
      22             : {
      23      422782 :     CKey key;
      24      211391 :     if (!keystore->GetKey(address, key))
      25             :         return false;
      26             : 
      27      211383 :     uint256 hash;
      28      211383 :     try {
      29      211383 :         hash = SignatureHash(scriptCode, *txTo, nIn, nHashType, amount, sigversion);
      30           0 :     } catch (const std::logic_error& ex) {
      31           0 :         return false;
      32             :     }
      33             : 
      34      211383 :     if (!key.Sign(hash, vchSig))
      35             :         return false;
      36      211383 :     vchSig.push_back((unsigned char)nHashType);
      37      211383 :     return true;
      38             : }
      39             : 
      40     3533307 : static bool Sign1(const CKeyID& address, const BaseSignatureCreator& creator, const CScript& scriptCode, std::vector<valtype>& ret, SigVersion sigversion)
      41             : {
      42     7066604 :     std::vector<unsigned char> vchSig;
      43     3533307 :     if (!creator.CreateSig(vchSig, address, scriptCode, sigversion))
      44             :         return false;
      45     3533295 :     ret.emplace_back(vchSig);
      46             :     return true;
      47             : }
      48             : 
      49         278 : static bool SignN(const std::vector<valtype>& multisigdata, const BaseSignatureCreator& creator, const CScript& scriptCode, std::vector<valtype>& ret, SigVersion sigversion)
      50             : {
      51         278 :     int nSigned = 0;
      52         278 :     int nRequired = multisigdata.front()[0];
      53         845 :     for (unsigned int i = 1; i < multisigdata.size()-1 && nSigned < nRequired; i++)
      54             :     {
      55         567 :         const valtype& pubkey = multisigdata[i];
      56         567 :         CKeyID keyID = CPubKey(pubkey).GetID();
      57         567 :         if (Sign1(keyID, creator, scriptCode, ret, sigversion))
      58         561 :             ++nSigned;
      59             :     }
      60         278 :     return nSigned==nRequired;
      61             : }
      62             : 
      63             : /**
      64             :  * Sign scriptPubKey using signature made with creator.
      65             :  * Signatures are returned in scriptSigRet (or returns false if scriptPubKey can't be signed),
      66             :  * unless whichTypeRet is TX_SCRIPTHASH, in which case scriptSigRet is the redemption script.
      67             :  * Returns false if scriptPubKey could not be completely satisfied.
      68             :  */
      69     3533454 : static bool SignStep(const BaseSignatureCreator& creator, const CScript& scriptPubKey,
      70             :                      std::vector<valtype>& ret, txnouttype& whichTypeRet, SigVersion sigversion, bool fColdStake)
      71             : {
      72     7066918 :     CScript scriptRet;
      73     3533454 :     uint160 h160;
      74     3533454 :     ret.clear();
      75             : 
      76     7066918 :     std::vector<valtype> vSolutions;
      77     3533454 :     if (!Solver(scriptPubKey, whichTypeRet, vSolutions))
      78             :         return false;
      79             : 
      80     3533454 :     CKeyID keyID;
      81     3533454 :     switch (whichTypeRet)
      82             :     {
      83             :     case TX_NONSTANDARD:
      84             :     case TX_NULL_DATA:
      85             :         return false;
      86        8351 :     case TX_PUBKEY:
      87        8351 :         keyID = CPubKey(vSolutions[0]).GetID();
      88        8351 :         return Sign1(keyID, creator, scriptPubKey, ret, sigversion);
      89     3524180 :     case TX_PUBKEYHASH:
      90     3524180 :     case TX_EXCHANGEADDR:
      91     3524180 :         keyID = CKeyID(uint160(vSolutions[0]));
      92     3524180 :         if (!Sign1(keyID, creator, scriptPubKey, ret, sigversion))
      93             :             return false;
      94             :         else
      95             :         {
      96     3524170 :             CPubKey vch;
      97     3524170 :             creator.KeyStore().GetPubKey(keyID, vch);
      98     7048350 :             ret.push_back(ToByteVector(vch));
      99             :         }
     100     3524170 :         return true;
     101         441 :     case TX_SCRIPTHASH:
     102         441 :         if (creator.KeyStore().GetCScript(uint160(vSolutions[0]), scriptRet)) {
     103         839 :             ret.emplace_back(scriptRet.begin(), scriptRet.end());
     104         281 :             return true;
     105             :         }
     106             :         return false;
     107             : 
     108         278 :     case TX_MULTISIG:
     109         278 :         ret.push_back(valtype()); // workaround CHECKMULTISIG bug
     110         278 :         return (SignN(vSolutions, creator, scriptPubKey, ret, sigversion));
     111             : 
     112         210 :     case TX_COLDSTAKE:
     113         210 :         if (fColdStake) {
     114             :             // sign with the cold staker key
     115          80 :             keyID = CKeyID(uint160(vSolutions[0]));
     116             :         } else {
     117             :             // sign with the owner key
     118         130 :             keyID = CKeyID(uint160(vSolutions[1]));
     119             :         }
     120         210 :         if (!Sign1(keyID, creator, scriptPubKey, ret, sigversion))
     121           0 :             return error("*** %s: failed to sign with the %s key.",
     122           0 :                     __func__, fColdStake ? "cold staker" : "owner");
     123         210 :         CPubKey vch;
     124         210 :         if (!creator.KeyStore().GetPubKey(keyID, vch))
     125           0 :             return error("%s : Unable to get public key from keyID", __func__);
     126             : 
     127     3533664 :         valtype oper;
     128         210 :         oper.reserve(4);
     129         340 :         oper.emplace_back((fColdStake ? (int) OP_TRUE : OP_FALSE));
     130         210 :         ret.emplace_back(oper);
     131         210 :         ret.emplace_back(ToByteVector(vch));
     132         210 :         return true;
     133             :     }
     134           0 :     LogPrintf("*** solver no case met \n");
     135             :     return false;
     136             : }
     137             : 
     138     3736082 : static CScript PushAll(const std::vector<valtype>& values)
     139             : {
     140     3736082 :     CScript result;
     141    11200371 :     for (const valtype& v : values) {
     142     7464289 :         if (v.size() == 0) {
     143         298 :             result << OP_0;
     144     7463995 :         } else if (v.size() == 1 && v[0] >= 1 && v[0] <= 16) {
     145           0 :             result << CScript::EncodeOP_N(v[0]);
     146             :         } else {
     147     7463995 :             result << v;
     148             :         }
     149             :     }
     150     3736082 :     return result;
     151             : }
     152             : 
     153     3533171 : bool ProduceSignature(const BaseSignatureCreator& creator, const CScript& fromPubKey, SignatureData& sigdata, SigVersion sigversion, bool fColdStake, ScriptError* serror)
     154             : {
     155     3533171 :     CScript script = fromPubKey;
     156     3533171 :     bool solved = true;
     157     7066352 :     std::vector<valtype> result;
     158     3533171 :     txnouttype whichType;
     159     3533171 :     solved = SignStep(creator, script, result, whichType, sigversion, fColdStake);
     160     7066352 :     CScript subscript;
     161             : 
     162     3533171 :     if (solved && whichType == TX_SCRIPTHASH)
     163             :     {
     164             :         // Solver returns the subscript that needs to be evaluated;
     165             :         // the final scriptSig is the signatures from that
     166             :         // and then the serialized subscript:
     167         281 :         script = subscript = CScript(result[0].begin(), result[0].end());
     168         281 :         solved = solved && SignStep(creator, script, result, whichType, sigversion, fColdStake) && whichType != TX_SCRIPTHASH;
     169         839 :         result.emplace_back(subscript.begin(), subscript.end());
     170             :     }
     171             : 
     172     3533171 :     sigdata.scriptSig = PushAll(result);
     173             : 
     174             :     // Test solution
     175     7066432 :     return solved && VerifyScript(sigdata.scriptSig, fromPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, creator.Checker(), sigversion, serror);
     176             : }
     177             : 
     178      202885 : SignatureData DataFromTransaction(const CMutableTransaction& tx, unsigned int nIn)
     179             : {
     180      202885 :     SignatureData data;
     181      202885 :     assert(tx.vin.size() > nIn);
     182      202885 :     data.scriptSig = tx.vin[nIn].scriptSig;
     183      202885 :     return data;
     184             : }
     185             : 
     186      214987 : void UpdateTransaction(CMutableTransaction& tx, unsigned int nIn, const SignatureData& data)
     187             : {
     188      214987 :     assert(tx.vin.size() > nIn);
     189      214987 :     tx.vin[nIn].scriptSig = data.scriptSig;
     190      214987 : }
     191             : 
     192        6560 : bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, const CAmount& amount, int nHashType, bool fColdStake)
     193             : {
     194        6560 :     assert(nIn < txTo.vin.size());
     195             : 
     196        6560 :     CTransaction txToConst(txTo);
     197       13120 :     TransactionSignatureCreator creator(&keystore, &txToConst, nIn, amount, nHashType);
     198             : 
     199       13120 :     SignatureData sigdata;
     200        8566 :     bool ret = ProduceSignature(creator, fromPubKey, sigdata, txToConst.GetRequiredSigVersion(), fColdStake);
     201        6560 :     UpdateTransaction(txTo, nIn, sigdata);
     202       13120 :     return ret;
     203             : }
     204             : 
     205        2060 : bool SignSignature(const CKeyStore &keystore, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType, bool fColdStake)
     206             : {
     207        2060 :     assert(nIn < txTo.vin.size());
     208        2060 :     CTxIn& txin = txTo.vin[nIn];
     209        2060 :     assert(txin.prevout.n < txFrom.vout.size());
     210        2060 :     const CTxOut& txout = txFrom.vout[txin.prevout.n];
     211             : 
     212        2060 :     return SignSignature(keystore, txout.scriptPubKey, txTo, nIn, txout.nValue, nHashType, fColdStake);
     213             : }
     214             : 
     215          11 : static std::vector<valtype> CombineMultisig(const CScript& scriptPubKey, const BaseSignatureChecker& checker,
     216             :                                const std::vector<valtype>& vSolutions,
     217             :                                const std::vector<valtype>& sigs1, const std::vector<valtype>& sigs2, SigVersion sigversion)
     218             : {
     219             :     // Combine all the signatures we've got:
     220          11 :     std::set<valtype> allsigs;
     221          38 :     for (const valtype& v : sigs1)
     222             :     {
     223          27 :         if (!v.empty())
     224          38 :             allsigs.insert(v);
     225             :     }
     226          33 :     for (const valtype& v : sigs2)
     227             :     {
     228          22 :         if (!v.empty())
     229          33 :             allsigs.insert(v);
     230             :     }
     231             : 
     232             :     // Build a map of pubkey -> signature by matching sigs to pubkeys:
     233          11 :     assert(vSolutions.size() > 1);
     234          11 :     unsigned int nSigsRequired = vSolutions.front()[0];
     235          11 :     unsigned int nPubKeys = vSolutions.size()-2;
     236          22 :     std::map<valtype, valtype> sigs;
     237          31 :     for (const valtype& sig : allsigs)
     238             :     {
     239          36 :         for (unsigned int i = 0; i < nPubKeys; i++)
     240             :         {
     241          36 :             const valtype& pubkey = vSolutions[i+1];
     242          36 :             if (sigs.count(pubkey))
     243           6 :                 continue; // Already got a sig for this pubkey
     244             : 
     245          30 :             if (checker.CheckSig(sig, pubkey, scriptPubKey, sigversion))
     246             :             {
     247          20 :                 sigs[pubkey] = sig;
     248             :                 break;
     249             :             }
     250             :         }
     251             :     }
     252             :     // Now build a merged CScript:
     253          11 :     unsigned int nSigsHave = 0;
     254          11 :     std::vector<valtype> result; result.emplace_back(); // pop-one-too-many workaround
     255          38 :     for (unsigned int i = 0; i < nPubKeys && nSigsHave < nSigsRequired; i++)
     256             :     {
     257          34 :         if (sigs.count(vSolutions[i+1]))
     258             :         {
     259          20 :             result.push_back(sigs[vSolutions[i+1]]);
     260          20 :             ++nSigsHave;
     261             :         }
     262             :     }
     263             :     // Fill any missing with OP_0:
     264          13 :     for (unsigned int i = nSigsHave; i < nSigsRequired; i++)
     265           2 :         result.push_back(valtype());
     266             : 
     267          22 :     return result;
     268             : }
     269             : 
     270             : namespace
     271             : {
     272      202908 : struct Stacks
     273             : {
     274             :     std::vector<valtype> script;
     275             : 
     276           0 :     Stacks() {}
     277          11 :     explicit Stacks(const std::vector<valtype>& scriptSigStack_) : script(scriptSigStack_) {}
     278      405808 :     explicit Stacks(const SignatureData& data, SigVersion sigversion) {
     279      405808 :         EvalScript(script, data.scriptSig, SCRIPT_VERIFY_STRICTENC, BaseSignatureChecker(), sigversion);
     280      405808 :     }
     281             : 
     282      202904 :     SignatureData Output() const {
     283      202904 :         SignatureData result;
     284      202904 :         result.scriptSig = PushAll(script);
     285      202904 :         return result;
     286             :     }
     287             : };
     288             : }
     289             : 
     290      202908 : static Stacks CombineSignatures(const CScript& scriptPubKey, const BaseSignatureChecker& checker,
     291             :                                  const txnouttype txType, const std::vector<valtype>& vSolutions,
     292             :                                  Stacks sigs1, Stacks sigs2, SigVersion sigversion)
     293             : {
     294      202908 :     switch (txType)
     295             :     {
     296           1 :     case TX_NONSTANDARD:
     297           1 :     case TX_NULL_DATA:
     298             :         // Don't know anything about this, assume bigger one is correct:
     299           1 :         if (sigs1.script.size() >= sigs2.script.size())
     300           1 :             return sigs1;
     301           0 :         return sigs2;
     302      202883 :     case TX_PUBKEY:
     303      202883 :     case TX_PUBKEYHASH:
     304      202883 :     case TX_EXCHANGEADDR:
     305      202883 :     case TX_COLDSTAKE:
     306             :         // Signatures are bigger than placeholders or empty scripts:
     307      202883 :         if (sigs1.script.empty() || sigs1.script[0].empty())
     308           5 :             return sigs2;
     309      202878 :         return sigs1;
     310          13 :     case TX_SCRIPTHASH:
     311          13 :         if (sigs1.script.empty() || sigs1.script.back().empty())
     312           2 :             return sigs2;
     313          11 :         else if (sigs2.script.empty() || sigs2.script.back().empty())
     314           7 :             return sigs1;
     315             :         else
     316             :         {
     317             :             // Recur to combine:
     318           8 :             valtype spk = sigs1.script.back();
     319           8 :             CScript pubKey2(spk.begin(), spk.end());
     320             : 
     321           4 :             txnouttype txType2;
     322           8 :             std::vector<std::vector<unsigned char> > vSolutions2;
     323           4 :             Solver(pubKey2, txType2, vSolutions2);
     324           4 :             sigs1.script.pop_back();
     325           4 :             sigs2.script.pop_back();
     326          12 :             Stacks result = CombineSignatures(pubKey2, checker, txType2, vSolutions2, sigs1, sigs2, sigversion);
     327           4 :             result.script.push_back(spk);
     328           4 :             return result;
     329             :         }
     330          11 :     case TX_MULTISIG:
     331          11 :         return Stacks(CombineMultisig(scriptPubKey, checker, vSolutions, sigs1.script, sigs2.script, sigversion));
     332             :     }
     333             : 
     334      202908 :     return Stacks();
     335             : }
     336             : 
     337      202904 : SignatureData CombineSignatures(const CScript& scriptPubKey, const BaseSignatureChecker& checker,
     338             :                           const SignatureData& scriptSig1, const SignatureData& scriptSig2)
     339             : {
     340      202904 :     txnouttype txType;
     341      202904 :     std::vector<std::vector<unsigned char> > vSolutions;
     342      202904 :     Solver(scriptPubKey, txType, vSolutions);
     343             : 
     344      405808 :     return CombineSignatures(scriptPubKey, checker, txType, vSolutions, Stacks(scriptSig1, SIGVERSION_BASE), Stacks(scriptSig2, SIGVERSION_BASE), SIGVERSION_BASE).Output();
     345             : }
     346             : 
     347             : namespace {
     348             : /** Dummy signature checker which accepts all signatures. */
     349             : class DummySignatureChecker : public BaseSignatureChecker
     350             : {
     351             : public:
     352             :     DummySignatureChecker() {}
     353             : 
     354     6640058 :     bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const
     355             :     {
     356     6640058 :         return true;
     357             :     }
     358             : };
     359             : const DummySignatureChecker dummyChecker;
     360             : }
     361             : 
     362     6639598 : const BaseSignatureChecker& DummySignatureCreator::Checker() const
     363             : {
     364     6639598 :     return dummyChecker;
     365             : }
     366             : 
     367     3321950 : bool DummySignatureCreator::CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode, SigVersion sigversion) const
     368             : {
     369             :     // Create a dummy signature that is a valid DER-encoding
     370     3321950 :     vchSig.assign(72, '\000');
     371     3321950 :     vchSig[0] = 0x30;
     372     3321950 :     vchSig[1] = 69;
     373     3321950 :     vchSig[2] = 0x02;
     374     3321950 :     vchSig[3] = 33;
     375     3321950 :     vchSig[4] = 0x01;
     376     3321950 :     vchSig[4 + 33] = 0x02;
     377     3321950 :     vchSig[5 + 33] = 32;
     378     3321950 :     vchSig[6 + 33] = 0x01;
     379     3321950 :     vchSig[6 + 33 + 32] = SIGHASH_ALL;
     380     3321950 :     return true;
     381             : }
     382             : 
     383             : template<typename M, typename K, typename V>
     384        9012 : bool LookupHelper(const M& map, const K& key, V& value)
     385             : {
     386        9012 :     auto it = map.find(key);
     387        9012 :     if (it != map.end()) {
     388        9012 :         value = it->second;
     389        9012 :         return true;
     390             :     }
     391             :     return false;
     392             : }
     393             : 
     394     3318188 : bool IsSolvable(const CKeyStore& store, const CScript& script, bool fColdStaking)
     395             : {
     396             :     // This check is to make sure that the script we created can actually be solved for and signed by us
     397             :     // if we were to have the private keys. This is just to make sure that the script is valid and that,
     398             :     // if found in a transaction, we would still accept and relay that transaction. In particular,
     399     6636376 :     DummySignatureCreator creator(&store);
     400     6636376 :     SignatureData sigs;
     401     3318188 :     if (ProduceSignature(creator, script, sigs, SIGVERSION_BASE, fColdStaking)) {
     402             :         // VerifyScript check is just defensive, and should never fail.
     403     3317958 :         assert(VerifyScript(sigs.scriptSig, script, STANDARD_SCRIPT_VERIFY_FLAGS, creator.Checker(), SIGVERSION_BASE));
     404             :         return true;
     405             :     }
     406             :     return false;
     407             : }
     408             : 
     409           0 : bool PublicOnlySigningProvider::GetCScript(const CScriptID &scriptid, CScript& script) const
     410             : {
     411           0 :     return m_provider->GetCScript(scriptid, script);
     412             : }
     413             : 
     414           0 : bool PublicOnlySigningProvider::GetPubKey(const CKeyID &address, CPubKey& pubkey) const
     415             : {
     416           0 :     return m_provider->GetPubKey(address, pubkey);
     417             : }
     418             : 
     419           0 : bool FlatSigningProvider::GetCScript(const CScriptID& scriptid, CScript& script) const { return LookupHelper(scripts, scriptid, script); }
     420           0 : bool FlatSigningProvider::GetPubKey(const CKeyID& keyid, CPubKey& pubkey) const { return LookupHelper(pubkeys, keyid, pubkey); }
     421        9012 : bool FlatSigningProvider::GetKey(const CKeyID& keyid, CKey& key) const { return LookupHelper(keys, keyid, key); }
     422             : 
     423           0 : FlatSigningProvider Merge(const FlatSigningProvider& a, const FlatSigningProvider& b)
     424             : {
     425           0 :     FlatSigningProvider ret;
     426           0 :     ret.scripts = a.scripts;
     427           0 :     ret.scripts.insert(b.scripts.begin(), b.scripts.end());
     428           0 :     ret.pubkeys = a.pubkeys;
     429           0 :     ret.pubkeys.insert(b.pubkeys.begin(), b.pubkeys.end());
     430           0 :     ret.keys = a.keys;
     431           0 :     ret.keys.insert(b.keys.begin(), b.keys.end());
     432           0 :     return ret;
     433             : }

Generated by: LCOV version 1.14