LCOV - code coverage report
Current view: top level - src/consensus - tx_verify.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 95 98 96.9 %
Date: 2026-06-25 07:23:43 Functions: 8 8 100.0 %

          Line data    Source code
       1             : // Copyright (c) 2017-2021 The Bitcoin Core developers
       2             : // Distributed under the MIT software license, see the accompanying
       3             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       4             : 
       5             : #include <consensus/tx_verify.h>
       6             : 
       7             : #include <chain.h>
       8             : #include <coins.h>
       9             : #include <consensus/consensus.h>
      10             : #include <consensus/validation.h>
      11             : #include <evo/assetlocktx.h>
      12             : #include <primitives/transaction.h>
      13             : #include <script/interpreter.h>
      14             : #include <tinyformat.h>
      15             : #include <util/check.h>
      16             : #include <util/moneystr.h>
      17             : 
      18             : 
      19      772630 : bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime)
      20             : {
      21      772630 :     if (tx.nLockTime == 0)
      22      735021 :         return true;
      23       37609 :     if ((int64_t)tx.nLockTime < ((int64_t)tx.nLockTime < LOCKTIME_THRESHOLD ? (int64_t)nBlockHeight : nBlockTime))
      24       37319 :         return true;
      25             : 
      26             :     // Even if tx.nLockTime isn't satisfied by nBlockHeight/nBlockTime, a
      27             :     // transaction is still considered final if all inputs' nSequence ==
      28             :     // SEQUENCE_FINAL (0xffffffff), in which case nLockTime is ignored.
      29             :     //
      30             :     // Because of this behavior OP_CHECKLOCKTIMEVERIFY/CheckLockTime() will
      31             :     // also check that the spending input's nSequence != SEQUENCE_FINAL,
      32             :     // ensuring that an unsatisfied nLockTime value will actually cause
      33             :     // IsFinalTx() to return false here:
      34         300 :     for (const auto& txin : tx.vin) {
      35         290 :         if (!(txin.nSequence == CTxIn::SEQUENCE_FINAL))
      36         280 :             return false;
      37             :     }
      38          10 :     return true;
      39      772630 : }
      40             : 
      41      411415 : std::pair<int, int64_t> CalculateSequenceLocks(const CTransaction &tx, int flags, std::vector<int>& prevHeights, const CBlockIndex& block)
      42             : {
      43      411415 :     assert(prevHeights.size() == tx.vin.size());
      44             : 
      45             :     // Will be set to the equivalent height- and time-based nLockTime
      46             :     // values that would be necessary to satisfy all relative lock-
      47             :     // time constraints given our view of block chain history.
      48             :     // The semantics of nLockTime are the last invalid height/time, so
      49             :     // use -1 to have the effect of any height or time being valid.
      50      411415 :     int nMinHeight = -1;
      51      411415 :     int64_t nMinTime = -1;
      52             : 
      53             :     // tx.nVersion is signed integer so requires cast to unsigned otherwise
      54             :     // we would be doing a signed comparison and half the range of nVersion
      55             :     // wouldn't support BIP 68.
      56      822402 :     bool fEnforceBIP68 = static_cast<uint32_t>(tx.nVersion) >= 2
      57      411415 :                          && flags & LOCKTIME_VERIFY_SEQUENCE;
      58             : 
      59             :     // Do not enforce sequence numbers as a relative lock time
      60             :     // unless we have been instructed to
      61      411415 :     if (!fEnforceBIP68) {
      62        2554 :         return std::make_pair(nMinHeight, nMinTime);
      63             :     }
      64             : 
      65      720757 :     for (size_t txinIndex = 0; txinIndex < tx.vin.size(); txinIndex++) {
      66      311896 :         const CTxIn& txin = tx.vin[txinIndex];
      67             : 
      68             :         // Sequence numbers with the most significant bit set are not
      69             :         // treated as relative lock-times, nor are they given any
      70             :         // consensus-enforced meaning at this point.
      71      311896 :         if (txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_DISABLE_FLAG) {
      72             :             // The height of this input is not relevant for sequence locks
      73      177431 :             prevHeights[txinIndex] = 0;
      74      177431 :             continue;
      75             :         }
      76             : 
      77      134465 :         int nCoinHeight = prevHeights[txinIndex];
      78             : 
      79      134465 :         if (txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG) {
      80        1719 :             const int64_t nCoinTime{Assert(block.GetAncestor(std::max(nCoinHeight - 1, 0)))->GetMedianTimePast()};
      81             :             // NOTE: Subtract 1 to maintain nLockTime semantics
      82             :             // BIP 68 relative lock times have the semantics of calculating
      83             :             // the first block or time at which the transaction would be
      84             :             // valid. When calculating the effective block time or height
      85             :             // for the entire transaction, we switch to using the
      86             :             // semantics of nLockTime which is the last invalid block
      87             :             // time or height.  Thus we subtract 1 from the calculated
      88             :             // time or height.
      89             : 
      90             :             // Time-based relative lock-times are measured from the
      91             :             // smallest allowed timestamp of the block containing the
      92             :             // txout being spent, which is the median time past of the
      93             :             // block prior.
      94        1719 :             nMinTime = std::max(nMinTime, nCoinTime + (int64_t)((txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_MASK) << CTxIn::SEQUENCE_LOCKTIME_GRANULARITY) - 1);
      95        1719 :         } else {
      96      132746 :             nMinHeight = std::max(nMinHeight, nCoinHeight + (int)(txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_MASK) - 1);
      97             :         }
      98      134465 :     }
      99             : 
     100      408861 :     return std::make_pair(nMinHeight, nMinTime);
     101      411415 : }
     102             : 
     103      413571 : bool EvaluateSequenceLocks(const CBlockIndex& block, std::pair<int, int64_t> lockPair)
     104             : {
     105      413571 :     assert(block.pprev);
     106      413571 :     int64_t nBlockTime = block.pprev->GetMedianTimePast();
     107      413571 :     if (lockPair.first >= block.nHeight || lockPair.second >= nBlockTime)
     108        1131 :         return false;
     109             : 
     110      412440 :     return true;
     111      413571 : }
     112             : 
     113      364003 : bool SequenceLocks(const CTransaction &tx, int flags, std::vector<int>& prevHeights, const CBlockIndex& block)
     114             : {
     115      364003 :     return EvaluateSequenceLocks(block, CalculateSequenceLocks(tx, flags, prevHeights, block));
     116             : }
     117             : 
     118     3075860 : unsigned int GetLegacySigOpCount(const CTransaction& tx)
     119             : {
     120     3075860 :     unsigned int nSigOps = 0;
     121     5592050 :     for (const auto& txin : tx.vin)
     122             :     {
     123     2516190 :         nSigOps += txin.scriptSig.GetSigOpCount(false);
     124             :     }
     125     8275221 :     for (const auto& txout : tx.vout)
     126             :     {
     127     5199361 :         nSigOps += txout.scriptPubKey.GetSigOpCount(false);
     128             :     }
     129     3075860 :     return nSigOps;
     130             : }
     131             : 
     132      447153 : unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& inputs)
     133             : {
     134      447153 :     if (tx.IsCoinBase())
     135           0 :         return 0;
     136             : 
     137      447153 :     unsigned int nSigOps = 0;
     138      834986 :     for (unsigned int i = 0; i < tx.vin.size(); i++)
     139             :     {
     140      387833 :         const Coin& coin = inputs.AccessCoin(tx.vin[i].prevout);
     141      387833 :         assert(!coin.IsSpent());
     142      387833 :         const CTxOut &prevout = coin.out;
     143      387833 :         if (prevout.scriptPubKey.IsPayToScriptHash())
     144      133573 :             nSigOps += prevout.scriptPubKey.GetSigOpCount(tx.vin[i].scriptSig);
     145      387833 :     }
     146      447153 :     return nSigOps;
     147      447153 : }
     148             : 
     149      788365 : unsigned int GetTransactionSigOpCount(const CTransaction& tx, const CCoinsViewCache& inputs, uint32_t flags)
     150             : {
     151      788365 :     unsigned int nSigOps = GetLegacySigOpCount(tx);
     152             : 
     153      788365 :     if (tx.IsCoinBase())
     154      341215 :         return nSigOps;
     155             : 
     156      447150 :     if (flags & SCRIPT_VERIFY_P2SH) {
     157      447150 :         nSigOps += GetP2SHSigOpCount(tx, inputs);
     158      447150 :     }
     159             : 
     160      447150 :     return nSigOps;
     161      788365 : }
     162             : 
     163     8432641 : bool Consensus::CheckTxInputs(const CTransaction& tx, TxValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, CAmount& txfee)
     164             : {
     165     8432641 :     if (bool isAssetUnlockTx = (tx.IsSpecialTxVersion() && tx.nType == TRANSACTION_ASSET_UNLOCK); isAssetUnlockTx) {
     166        3407 :         return GetAssetUnlockFee(tx, txfee, state);
     167             :     }
     168             : 
     169             :     // are the actual inputs available?
     170     8429234 :     if (!inputs.HaveInputs(tx)) {
     171          49 :         return state.Invalid(TxValidationResult::TX_MISSING_INPUTS, "bad-txns-inputs-missingorspent",
     172          49 :                          strprintf("%s: inputs missing/spent", __func__));
     173             :     }
     174             : 
     175     8429185 :     CAmount nValueIn = 0;
     176    19897680 :     for (unsigned int i = 0; i < tx.vin.size(); ++i) {
     177    11468506 :         const COutPoint &prevout = tx.vin[i].prevout;
     178    11468506 :         const Coin& coin = inputs.AccessCoin(prevout);
     179    11468506 :         assert(!coin.IsSpent());
     180             : 
     181             :         // If prev is coinbase, check that it's matured
     182    11468506 :         if (coin.IsCoinBase() && nSpendHeight - coin.nHeight < COINBASE_MATURITY) {
     183          11 :             return state.Invalid(TxValidationResult::TX_PREMATURE_SPEND, "bad-txns-premature-spend-of-coinbase",
     184          11 :                 strprintf("tried to spend coinbase at depth %d", nSpendHeight - coin.nHeight));
     185             :         }
     186             : 
     187             :         // Check for negative or overflow input values
     188    11468495 :         nValueIn += coin.out.nValue;
     189    11468495 :         if (!MoneyRange(coin.out.nValue) || !MoneyRange(nValueIn)) {
     190           0 :             return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-inputvalues-outofrange");
     191             :         }
     192    11468495 :     }
     193             : 
     194     8429174 :     const CAmount value_out = tx.GetValueOut();
     195     8429174 :     if (nValueIn < value_out) {
     196          36 :         return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-in-belowout",
     197          18 :             strprintf("value in (%s) < value out (%s)", FormatMoney(nValueIn), FormatMoney(value_out)));
     198             :     }
     199             : 
     200             :     // Tally transaction fees
     201     8429156 :     const CAmount txfee_aux = nValueIn - value_out;
     202     8429156 :     if (!MoneyRange(txfee_aux)) {
     203           0 :         return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-fee-outofrange");
     204             :     }
     205             : 
     206     8429156 :     txfee = txfee_aux;
     207     8429156 :     return true;
     208     8432641 : }

Generated by: LCOV version 1.16