LCOV - code coverage report
Current view: top level - src/script - sign.cpp (source / functions) Hit Total Coverage
Test: test_dash_coverage.info Lines: 240 278 86.3 %
Date: 2026-06-25 07:23:51 Functions: 37 44 84.1 %

          Line data    Source code
       1             : // Copyright (c) 2009-2010 Satoshi Nakamoto
       2             : // Copyright (c) 2009-2021 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 <consensus/amount.h>
       9             : #include <key.h>
      10             : #include <policy/policy.h>
      11             : #include <primitives/transaction.h>
      12             : #include <script/keyorigin.h>
      13             : #include <script/signingprovider.h>
      14             : #include <script/standard.h>
      15             : #include <uint256.h>
      16             : #include <util/translation.h>
      17             : 
      18             : typedef std::vector<unsigned char> valtype;
      19             : 
      20         678 : MutableTransactionSignatureCreator::MutableTransactionSignatureCreator(const CMutableTransaction& tx, unsigned int input_idx, const CAmount& amount, int hash_type)
      21         339 :     : m_txto{tx}, nIn{input_idx}, nHashType{hash_type}, amount{amount}, checker{&m_txto, nIn, amount, MissingDataBehavior::FAIL},
      22         339 :       m_txdata(nullptr)
      23         678 : {
      24         678 : }
      25             : 
      26        1324 : MutableTransactionSignatureCreator::MutableTransactionSignatureCreator(const CMutableTransaction& tx, unsigned int input_idx, const CAmount& amount, const PrecomputedTransactionData* txdata, int hash_type)
      27         662 :     : m_txto{tx}, nIn{input_idx}, nHashType{hash_type}, amount{amount},
      28         662 :       checker{txdata ? MutableTransactionSignatureChecker{&m_txto, nIn, amount, *txdata, MissingDataBehavior::FAIL} :
      29           0 :                        MutableTransactionSignatureChecker{&m_txto, nIn, amount, MissingDataBehavior::FAIL}},
      30         662 :       m_txdata(txdata)
      31        1324 : {
      32        1324 : }
      33             : 
      34        1029 : bool MutableTransactionSignatureCreator::CreateSig(const SigningProvider& provider, std::vector<unsigned char>& vchSig, const CKeyID& address, const CScript& scriptCode, SigVersion sigversion) const
      35             : {
      36        1029 :     CKey key;
      37        1029 :     if (!provider.GetKey(address, key))
      38          38 :         return false;
      39             : 
      40         991 :     uint256 hash = SignatureHash(scriptCode, m_txto, nIn, nHashType, amount, sigversion, m_txdata);
      41         991 :     if (!key.Sign(hash, vchSig))
      42           0 :         return false;
      43         991 :     vchSig.push_back((unsigned char)nHashType);
      44         991 :     return true;
      45        1029 : }
      46             : 
      47         170 : static bool GetCScript(const SigningProvider& provider, const SignatureData& sigdata, const CScriptID& scriptid, CScript& script)
      48             : {
      49         170 :     if (provider.GetCScript(scriptid, script)) {
      50         167 :         return true;
      51             :     }
      52             :     // Look for scripts in SignatureData
      53           3 :     if (CScriptID(sigdata.redeem_script) == scriptid) {
      54           2 :         script = sigdata.redeem_script;
      55           2 :         return true;
      56             :     }
      57           1 :     return false;
      58         170 : }
      59             : 
      60        4240 : static bool GetPubKey(const SigningProvider& provider, const SignatureData& sigdata, const CKeyID& address, CPubKey& pubkey)
      61             : {
      62             :     // Look for pubkey in all partial sigs
      63        4240 :     const auto it = sigdata.signatures.find(address);
      64        4240 :     if (it != sigdata.signatures.end()) {
      65           0 :         pubkey = it->second.first;
      66           0 :         return true;
      67             :     }
      68             :     // Look for pubkey in pubkey list
      69        4240 :     const auto& pk_it = sigdata.misc_pubkeys.find(address);
      70        4240 :     if (pk_it != sigdata.misc_pubkeys.end()) {
      71           0 :         pubkey = pk_it->second.first;
      72           0 :         return true;
      73             :     }
      74             :     // Query the underlying provider
      75        4240 :     return provider.GetPubKey(address, pubkey);
      76        4240 : }
      77             : 
      78        5060 : static bool CreateSig(const BaseSignatureCreator& creator, SignatureData& sigdata, const SigningProvider& provider, std::vector<unsigned char>& sig_out, const CPubKey& pubkey, const CScript& scriptcode, SigVersion sigversion)
      79             : {
      80        5060 :     CKeyID keyid = pubkey.GetID();
      81        5060 :     const auto it = sigdata.signatures.find(keyid);
      82        5060 :     if (it != sigdata.signatures.end()) {
      83          14 :         sig_out = it->second.second;
      84          14 :         return true;
      85             :     }
      86        5046 :     KeyOriginInfo info;
      87        5046 :     if (provider.GetKeyOrigin(keyid, info)) {
      88        4724 :         sigdata.misc_pubkeys.emplace(keyid, std::make_pair(pubkey, std::move(info)));
      89        4724 :     }
      90        5046 :     if (creator.CreateSig(provider, sig_out, keyid, scriptcode, sigversion)) {
      91        5008 :         auto i = sigdata.signatures.emplace(keyid, SigPair(pubkey, sig_out));
      92        5008 :         assert(i.second);
      93        5008 :         return true;
      94             :     }
      95             :     // Could not make signature or signature not found, add keyid to missing
      96          38 :     sigdata.missing_sigs.push_back(keyid);
      97          38 :     return false;
      98        5060 : }
      99             : 
     100             : /**
     101             :  * Sign scriptPubKey using signature made with creator.
     102             :  * Signatures are returned in scriptSigRet (or returns false if scriptPubKey can't be signed),
     103             :  * unless whichTypeRet is TxoutType::SCRIPTHASH, in which case scriptSigRet is the redemption script.
     104             :  * Returns false if scriptPubKey could not be completely satisfied.
     105             :  */
     106        5059 : static bool SignStep(const SigningProvider& provider, const BaseSignatureCreator& creator, const CScript& scriptPubKey,
     107             :                      std::vector<valtype>& ret, TxoutType& whichTypeRet, SigVersion sigversion, SignatureData& sigdata)
     108             : {
     109        5059 :     CScript scriptRet;
     110        5059 :     ret.clear();
     111        5059 :     std::vector<unsigned char> sig;
     112             : 
     113        5059 :     std::vector<valtype> vSolutions;
     114        5059 :     whichTypeRet = Solver(scriptPubKey, vSolutions);
     115             : 
     116        5059 :     switch (whichTypeRet) {
     117             :     case TxoutType::NONSTANDARD:
     118             :     case TxoutType::NULL_DATA:
     119           0 :         return false;
     120             :     case TxoutType::PUBKEY:
     121         489 :         if (!CreateSig(creator, sigdata, provider, sig, CPubKey(vSolutions[0]), scriptPubKey, sigversion)) return false;
     122         469 :         ret.push_back(std::move(sig));
     123         469 :         return true;
     124             :     case TxoutType::PUBKEYHASH: {
     125        4240 :         CKeyID keyID = CKeyID(uint160(vSolutions[0]));
     126        4240 :         CPubKey pubkey;
     127        4240 :         if (!GetPubKey(provider, sigdata, keyID, pubkey)) {
     128             :             // Pubkey could not be found, add to missing
     129           1 :             sigdata.missing_pubkeys.push_back(keyID);
     130           1 :             return false;
     131             :         }
     132        4239 :         if (!CreateSig(creator, sigdata, provider, sig, pubkey, scriptPubKey, sigversion)) return false;
     133        4239 :         ret.push_back(std::move(sig));
     134        4239 :         ret.push_back(ToByteVector(pubkey));
     135        4239 :         return true;
     136             :     }
     137             :     case TxoutType::SCRIPTHASH: {
     138         170 :         uint160 h160{vSolutions[0]};
     139         170 :         if (GetCScript(provider, sigdata, CScriptID{h160}, scriptRet)) {
     140         169 :             ret.emplace_back(scriptRet.begin(), scriptRet.end());
     141         169 :             return true;
     142             :         }
     143             :         // Could not find redeemScript, add to missing
     144           1 :         sigdata.missing_redeem_script = h160;
     145           1 :         return false;
     146             :     }
     147             :     case TxoutType::MULTISIG: {
     148         160 :         size_t required = vSolutions.front()[0];
     149         160 :         ret.emplace_back(); // workaround CHECKMULTISIG bug
     150         492 :         for (size_t i = 1; i < vSolutions.size() - 1; ++i) {
     151         332 :             CPubKey pubkey = CPubKey(vSolutions[i]);
     152             :             // We need to always call CreateSig in order to fill sigdata with all
     153             :             // possible signatures that we can create. This will allow further PSBT
     154             :             // processing to work as it needs all possible signature and pubkey pairs
     155         332 :             if (CreateSig(creator, sigdata, provider, sig, pubkey, scriptPubKey, sigversion)) {
     156         314 :                 if (ret.size() < required + 1) {
     157         252 :                     ret.push_back(std::move(sig));
     158         252 :                 }
     159         314 :             }
     160         332 :         }
     161         160 :         bool ok = ret.size() == required + 1;
     162         166 :         for (size_t i = 0; i + ret.size() < required + 1; ++i) {
     163           6 :             ret.emplace_back();
     164           6 :         }
     165         160 :         return ok;
     166             :     }
     167             :     } // no default case, so the compiler can warn about missing cases
     168           0 :     assert(false);
     169        5059 : }
     170             : 
     171        4890 : static CScript PushAll(const std::vector<valtype>& values)
     172             : {
     173        4890 :     CScript result;
     174       14424 :     for(const valtype& v : values) {
     175        9534 :         if (v.size() == 0) {
     176         166 :             result << OP_0;
     177        9534 :         } else if (v.size() == 1 && v[0] >= 1 && v[0] <= 16) {
     178           0 :             result << CScript::EncodeOP_N(v[0]);
     179        9368 :         } else if (v.size() == 1 && v[0] == 0x81) {
     180           0 :             result << OP_1NEGATE;
     181           0 :         } else {
     182        9368 :             result << v;
     183             :         }
     184             :     }
     185        4890 :     return result;
     186        4890 : }
     187             : 
     188        4898 : bool ProduceSignature(const SigningProvider& provider, const BaseSignatureCreator& creator, const CScript& fromPubKey, SignatureData& sigdata)
     189             : {
     190        4898 :     if (sigdata.complete) return true;
     191             : 
     192        4890 :     std::vector<valtype> result;
     193             :     TxoutType whichType;
     194        4890 :     bool solved = SignStep(provider, creator, fromPubKey, result, whichType, SigVersion::BASE, sigdata);
     195        4890 :     bool P2SH = false;
     196        4890 :     CScript subscript;
     197             : 
     198        4890 :     if (solved && whichType == TxoutType::SCRIPTHASH)
     199             :     {
     200             :         // Solver returns the subscript that needs to be evaluated;
     201             :         // the final scriptSig is the signatures from that
     202             :         // and then the serialized subscript:
     203         169 :         subscript = CScript(result[0].begin(), result[0].end());
     204         169 :         sigdata.redeem_script = subscript;
     205         169 :         solved = solved && SignStep(provider, creator, subscript, result, whichType, SigVersion::BASE, sigdata) && whichType != TxoutType::SCRIPTHASH;
     206         169 :         P2SH = true;
     207         169 :     }
     208             : 
     209        4890 :     if (P2SH) {
     210         169 :         result.emplace_back(subscript.begin(), subscript.end());
     211         169 :     }
     212        4890 :     sigdata.scriptSig = PushAll(result);
     213             : 
     214             :     // Test solution
     215        9752 :     sigdata.complete = solved && VerifyScript(sigdata.scriptSig, fromPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, creator.Checker());
     216        4890 :     return sigdata.complete;
     217        4898 : }
     218             : 
     219             : namespace {
     220             : class SignatureExtractorChecker final : public DeferringSignatureChecker
     221             : {
     222             : private:
     223             :     SignatureData& sigdata;
     224             : 
     225             : public:
     226        1334 :     SignatureExtractorChecker(SignatureData& sigdata, BaseSignatureChecker& checker) : DeferringSignatureChecker(checker), sigdata(sigdata) {}
     227             : 
     228           7 :     bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const override
     229             :     {
     230           7 :         if (m_checker.CheckSig(scriptSig, vchPubKey, scriptCode, sigversion)) {
     231           6 :             CPubKey pubkey(vchPubKey);
     232           6 :             sigdata.signatures.emplace(pubkey.GetID(), SigPair(pubkey, scriptSig));
     233           6 :             return true;
     234             :         }
     235           1 :         return false;
     236           7 :     }
     237             : };
     238             : 
     239             : struct Stacks
     240             : {
     241             :     std::vector<valtype> script;
     242             : 
     243             :     Stacks() = delete;
     244             :     Stacks(const Stacks&) = delete;
     245        1334 :     explicit Stacks(const SignatureData& data) {
     246         667 :         EvalScript(script, data.scriptSig, SCRIPT_VERIFY_STRICTENC, BaseSignatureChecker(), SigVersion::BASE);
     247        1334 :     }
     248             : };
     249             : }
     250             : 
     251             : // Extracts signatures and scripts from incomplete scriptSigs. Please do not extend this, use PSBT instead
     252         667 : SignatureData DataFromTransaction(const CMutableTransaction& tx, unsigned int nIn, const CTxOut& txout)
     253             : {
     254         667 :     SignatureData data;
     255         667 :     assert(tx.vin.size() > nIn);
     256         667 :     data.scriptSig = tx.vin[nIn].scriptSig;
     257         667 :     Stacks stack(data);
     258             : 
     259             :     // Get signatures
     260         667 :     MutableTransactionSignatureChecker tx_checker(&tx, nIn, txout.nValue, MissingDataBehavior::FAIL);
     261         667 :     SignatureExtractorChecker extractor_checker(data, tx_checker);
     262         667 :     if (VerifyScript(data.scriptSig, txout.scriptPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, extractor_checker)) {
     263           5 :         data.complete = true;
     264           5 :         return data;
     265             :     }
     266             : 
     267             :     // Get scripts
     268         662 :     std::vector<std::vector<unsigned char>> solutions;
     269         662 :     TxoutType script_type = Solver(txout.scriptPubKey, solutions);
     270         662 :     SigVersion sigversion = SigVersion::BASE;
     271         662 :     CScript next_script = txout.scriptPubKey;
     272             : 
     273         662 :     if (script_type == TxoutType::SCRIPTHASH && !stack.script.empty() && !stack.script.back().empty()) {
     274             :         // Get the redeemScript
     275           0 :         CScript redeem_script(stack.script.back().begin(), stack.script.back().end());
     276           0 :         data.redeem_script = redeem_script;
     277           0 :         next_script = std::move(redeem_script);
     278             : 
     279             :         // Get redeemScript type
     280           0 :         script_type = Solver(next_script, solutions);
     281           0 :         stack.script.pop_back();
     282           0 :     }
     283             : 
     284         662 :     if (script_type == TxoutType::MULTISIG && !stack.script.empty()) {
     285             :         // Build a map of pubkey -> signature by matching sigs to pubkeys:
     286           0 :         assert(solutions.size() > 1);
     287           0 :         unsigned int num_pubkeys = solutions.size()-2;
     288           0 :         unsigned int last_success_key = 0;
     289           0 :         for (const valtype& sig : stack.script) {
     290           0 :             for (unsigned int i = last_success_key; i < num_pubkeys; ++i) {
     291           0 :                 const valtype& pubkey = solutions[i+1];
     292             :                 // We either have a signature for this pubkey, or we have found a signature and it is valid
     293           0 :                 if (data.signatures.count(CPubKey(pubkey).GetID()) || extractor_checker.CheckSig(sig, pubkey, next_script, sigversion)) {
     294           0 :                     last_success_key = i + 1;
     295           0 :                     break;
     296             :                 }
     297           0 :             }
     298             :         }
     299           0 :     }
     300             : 
     301         662 :     return data;
     302         667 : }
     303             : 
     304        4503 : void UpdateInput(CTxIn& input, const SignatureData& data)
     305             : {
     306        4503 :     input.scriptSig = data.scriptSig;
     307        4503 : }
     308             : 
     309          34 : void SignatureData::MergeSignatureData(SignatureData sigdata)
     310             : {
     311          34 :     if (complete) return;
     312          29 :     if (sigdata.complete) {
     313           8 :         *this = std::move(sigdata);
     314           8 :         return;
     315             :     }
     316          21 :     if (redeem_script.empty() && !sigdata.redeem_script.empty()) {
     317           0 :         redeem_script = sigdata.redeem_script;
     318           0 :     }
     319          21 :     signatures.insert(std::make_move_iterator(sigdata.signatures.begin()), std::make_move_iterator(sigdata.signatures.end()));
     320          34 : }
     321             : 
     322         319 : bool SignSignature(const SigningProvider &provider, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, const CAmount& amount, int nHashType)
     323             : {
     324         319 :     assert(nIn < txTo.vin.size());
     325             : 
     326         319 :     MutableTransactionSignatureCreator creator(txTo, nIn, amount, nHashType);
     327             : 
     328         319 :     SignatureData sigdata;
     329         319 :     bool ret = ProduceSignature(provider, creator, fromPubKey, sigdata);
     330         319 :     UpdateInput(txTo.vin.at(nIn), sigdata);
     331         319 :     return ret;
     332         319 : }
     333             : 
     334         217 : bool SignSignature(const SigningProvider &provider, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType)
     335             : {
     336         217 :     assert(nIn < txTo.vin.size());
     337         217 :     const CTxIn& txin = txTo.vin[nIn];
     338         217 :     assert(txin.prevout.n < txFrom.vout.size());
     339         217 :     const CTxOut& txout = txFrom.vout[txin.prevout.n];
     340             : 
     341         217 :     return SignSignature(provider, txout.scriptPubKey, txTo, nIn, txout.nValue, nHashType);
     342             : }
     343             : 
     344             : namespace {
     345             : /** Dummy signature checker which accepts all signatures. */
     346             : class DummySignatureChecker final : public BaseSignatureChecker
     347             : {
     348             : public:
     349         436 :     DummySignatureChecker() = default;
     350        4440 :     bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const override { return true; }
     351             : };
     352             : }
     353             : 
     354         218 : const BaseSignatureChecker& DUMMY_CHECKER = DummySignatureChecker();
     355             : 
     356             : namespace {
     357             : class DummySignatureCreator final : public BaseSignatureCreator {
     358             : private:
     359             :     char m_r_len = 32;
     360             :     char m_s_len = 32;
     361             : public:
     362         872 :     DummySignatureCreator(char r_len, char s_len) : m_r_len(r_len), m_s_len(s_len) {}
     363        3896 :     const BaseSignatureChecker& Checker() const override { return DUMMY_CHECKER; }
     364        4017 :     bool CreateSig(const SigningProvider& provider, std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode, SigVersion sigversion) const override
     365             :     {
     366             :         // Create a dummy signature that is a valid DER-encoding
     367        4017 :         vchSig.assign(m_r_len + m_s_len + 7, '\000');
     368        4017 :         vchSig[0] = 0x30;
     369        4017 :         vchSig[1] = m_r_len + m_s_len + 4;
     370        4017 :         vchSig[2] = 0x02;
     371        4017 :         vchSig[3] = m_r_len;
     372        4017 :         vchSig[4] = 0x01;
     373        4017 :         vchSig[4 + m_r_len] = 0x02;
     374        4017 :         vchSig[5 + m_r_len] = m_s_len;
     375        4017 :         vchSig[6 + m_r_len] = 0x01;
     376        4017 :         vchSig[6 + m_r_len + m_s_len] = SIGHASH_ALL;
     377        4017 :         return true;
     378             :     }
     379             : };
     380             : 
     381             : }
     382             : 
     383         218 : const BaseSignatureCreator& DUMMY_SIGNATURE_CREATOR = DummySignatureCreator(32, 32);
     384         218 : const BaseSignatureCreator& DUMMY_MAXIMUM_SIGNATURE_CREATOR = DummySignatureCreator(33, 32);
     385             : 
     386         374 : bool IsSolvable(const SigningProvider& provider, const CScript& script)
     387             : {
     388             :     // This check is to make sure that the script we created can actually be solved for and signed by us
     389             :     // if we were to have the private keys. This is just to make sure that the script is valid and that,
     390             :     // if found in a transaction, we would still accept and relay that transaction.
     391         374 :     SignatureData sigs;
     392         374 :     if (ProduceSignature(provider, DUMMY_SIGNATURE_CREATOR, script, sigs)) {
     393             :         // VerifyScript check is just defensive, and should never fail.
     394         374 :         bool verified = VerifyScript(sigs.scriptSig, script, STANDARD_SCRIPT_VERIFY_FLAGS, DUMMY_CHECKER);
     395         374 :         assert(verified);
     396         374 :         return true;
     397             :     }
     398           0 :     return false;
     399         374 : }
     400             : 
     401         232 : bool SignTransaction(CMutableTransaction& mtx, const SigningProvider* keystore, const std::map<COutPoint, Coin>& coins, int nHashType, std::map<int, bilingual_str>& input_errors)
     402             : {
     403         232 :     bool fHashSingle = ((nHashType & ~SIGHASH_ANYONECANPAY) == SIGHASH_SINGLE);
     404             : 
     405             :     // Use CTransaction for the constant parts of the
     406             :     // transaction to avoid rehashing.
     407         232 :     const CTransaction txConst(mtx);
     408             : 
     409         232 :     PrecomputedTransactionData txdata;
     410         232 :     std::vector<CTxOut> spent_outputs;
     411         232 :     spent_outputs.resize(mtx.vin.size());
     412         232 :     bool have_all_spent_outputs = true;
     413         891 :     for (unsigned int i = 0; i < mtx.vin.size(); i++) {
     414         659 :         CTxIn& txin = mtx.vin[i];
     415         659 :         auto coin = coins.find(txin.prevout);
     416         659 :         if (coin == coins.end() || coin->second.IsSpent()) {
     417           0 :             have_all_spent_outputs = false;
     418           0 :         } else {
     419         659 :             spent_outputs[i] = CTxOut(coin->second.out.nValue, coin->second.out.scriptPubKey);
     420             :         }
     421         659 :     }
     422         232 :     if (have_all_spent_outputs) {
     423         232 :         txdata.Init(txConst, std::move(spent_outputs), true);
     424         232 :     } else {
     425           0 :         txdata.Init(txConst, {}, true);
     426             :     }
     427             : 
     428             :     // Sign what we can:
     429         891 :     for (unsigned int i = 0; i < mtx.vin.size(); i++) {
     430         659 :         CTxIn& txin = mtx.vin[i];
     431         659 :         auto coin = coins.find(txin.prevout);
     432         659 :         if (coin == coins.end() || coin->second.IsSpent()) {
     433           0 :             input_errors[i] = _("Input not found or already spent");
     434           0 :             continue;
     435             :         }
     436         659 :         const CScript& prevPubKey = coin->second.out.scriptPubKey;
     437         659 :         const CAmount& amount = coin->second.out.nValue;
     438             : 
     439         659 :         SignatureData sigdata = DataFromTransaction(mtx, i, coin->second.out);
     440             :         // Only sign SIGHASH_SINGLE if there's a corresponding output:
     441         659 :         if (!fHashSingle || (i < mtx.vout.size())) {
     442         659 :             ProduceSignature(*keystore, MutableTransactionSignatureCreator(mtx, i, amount, &txdata, nHashType), prevPubKey, sigdata);
     443         659 :         }
     444             : 
     445         659 :         UpdateInput(txin, sigdata);
     446             : 
     447         659 :         ScriptError serror = SCRIPT_ERR_OK;
     448         659 :         if (!VerifyScript(txin.scriptSig, prevPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, TransactionSignatureChecker(&txConst, i, amount, txdata, MissingDataBehavior::FAIL), &serror)) {
     449          21 :             if (serror == SCRIPT_ERR_INVALID_STACK_OPERATION) {
     450             :                 // Unable to sign input and verification failed (possible attempt to partially sign).
     451          20 :                 input_errors[i] = Untranslated("Unable to sign input, invalid stack size (possibly missing key)");
     452          21 :             } else if (serror == SCRIPT_ERR_SIG_NULLFAIL) {
     453             :                 // Verification failed (possibly due to insufficient signatures).
     454           0 :                 input_errors[i] = Untranslated("CHECK(MULTI)SIG failing with non-zero signature (possibly need more signatures)");
     455           0 :             } else {
     456           1 :                 input_errors[i] = Untranslated(ScriptErrorString(serror));
     457             :             }
     458          21 :         } else {
     459             :             // If this input succeeds, make sure there is no error set for it
     460         638 :             input_errors.erase(i);
     461             :         }
     462         659 :     }
     463         232 :     return input_errors.empty();
     464         232 : }

Generated by: LCOV version 1.16