* Check whether all of this transaction's input scripts succeed. * * This involves ECDSA signature checks so can be computationally intensive. This function should * only be called after the cheap sanity checks in CheckTxInputs passed. * * If pvChecks is not nullptr, script checks are pushed onto it instead of being performed inline. Any * script checks which are not necessary (eg due to scr
| 1737 | * Non-static (and re-declared) in src/test/txvalidationcache_tests.cpp |
| 1738 | */ |
| 1739 | bool CheckInputScripts(const CTransaction& tx, TxValidationState& state, |
| 1740 | const CCoinsViewCache& inputs, unsigned int flags, bool cacheSigStore, |
| 1741 | bool cacheFullScriptStore, PrecomputedTransactionData& txdata, |
| 1742 | std::vector<CCheck*>* pvChecks) |
| 1743 | { |
| 1744 | if (tx.IsCoinBase()) return true; |
| 1745 | |
| 1746 | if (pvChecks) { |
| 1747 | pvChecks->reserve(tx.vin.size()); |
| 1748 | } |
| 1749 | |
| 1750 | // First check if script executions have been cached with the same |
| 1751 | // flags. Note that this assumes that the inputs provided are |
| 1752 | // correct (ie that the transaction hash which is in tx's prevouts |
| 1753 | // properly commits to the scriptPubKey in the inputs view of that |
| 1754 | // transaction). |
| 1755 | uint256 hashCacheEntry; |
| 1756 | CSHA256 hasher = g_scriptExecutionCacheHasher; |
| 1757 | hasher.Write(tx.GetWitnessHash().begin(), 32).Write((unsigned char*)&flags, sizeof(flags)).Finalize(hashCacheEntry.begin()); |
| 1758 | AssertLockHeld(cs_main); //TODO: Remove this requirement by making CuckooCache not require external locks |
| 1759 | if (g_scriptExecutionCache.contains(hashCacheEntry, !cacheFullScriptStore)) { |
| 1760 | return true; |
| 1761 | } |
| 1762 | |
| 1763 | if (!txdata.m_spent_outputs_ready) { |
| 1764 | std::vector<CTxOut> spent_outputs; |
| 1765 | spent_outputs.reserve(tx.vin.size()); |
| 1766 | |
| 1767 | for (unsigned int i = 0; i < tx.vin.size(); i++) { |
| 1768 | const COutPoint& prevout = tx.vin[i].prevout; |
| 1769 | // ELEMENTS: |
| 1770 | // If input is peg-in, create "coin" to evaluate against |
| 1771 | Coin pegin_coin; |
| 1772 | if (tx.vin[i].m_is_pegin) { |
| 1773 | // Height of "output" in script evaluation will be 0 |
| 1774 | pegin_coin = Coin(GetPeginOutputFromWitness(tx.witness.vtxinwit[i].m_pegin_witness), 0, false); |
| 1775 | } |
| 1776 | const Coin& coin = tx.vin[i].m_is_pegin ? pegin_coin : inputs.AccessCoin(prevout); |
| 1777 | // end ELEMENTS |
| 1778 | assert(!coin.IsSpent()); |
| 1779 | spent_outputs.emplace_back(coin.out); |
| 1780 | } |
| 1781 | txdata.Init(tx, std::move(spent_outputs)); |
| 1782 | } |
| 1783 | assert(txdata.m_spent_outputs.size() == tx.vin.size()); |
| 1784 | |
| 1785 | for (unsigned int i = 0; i < tx.vin.size(); i++) { |
| 1786 | // We very carefully only pass in things to CScriptCheck which |
| 1787 | // are clearly committed to by tx' witness hash. This provides |
| 1788 | // a sanity check that our caching is not introducing consensus |
| 1789 | // failures through additional data in, eg, the coins being |
| 1790 | // spent being checked as a part of CScriptCheck. |
| 1791 | |
| 1792 | // Verify signature |
| 1793 | CCheck* check = new CScriptCheck(txdata.m_spent_outputs[i], tx, i, flags, cacheSigStore, &txdata); |
| 1794 | ScriptError serror = QueueCheck(pvChecks, check); |
| 1795 | if (serror != SCRIPT_ERR_OK) { |
| 1796 | // Tx failures never trigger disconnections/bans. |