LCOV - code coverage report
Current view: top level - src/consensus - tx_verify.cpp (source / functions) Coverage Total Hit
Test: fuzz_coverage.info Lines: 98.7 % 78 77
Test Date: 2026-08-11 06:08:24 Functions: 100.0 % 8 8
Branches: 73.7 % 114 84

             Branch data     Line data    Source code
       1                 :             : // Copyright (c) 2017-present 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/amount.h>
      10                 :             : #include <consensus/consensus.h>
      11                 :             : #include <consensus/validation.h>
      12                 :             : #include <primitives/transaction.h>
      13                 :             : #include <script/interpreter.h>
      14                 :             : #include <script/script.h>
      15                 :             : #include <tinyformat.h>
      16                 :             : #include <util/check.h>
      17                 :             : #include <util/moneystr.h>
      18                 :             : 
      19                 :             : #include <algorithm>
      20                 :             : #include <cstddef>
      21                 :             : #include <string>
      22                 :             : 
      23                 :     3800084 : bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime)
      24                 :             : {
      25         [ +  + ]:     3800084 :     if (tx.nLockTime == 0)
      26                 :             :         return true;
      27   [ +  +  +  + ]:     1625357 :     if ((int64_t)tx.nLockTime < ((int64_t)tx.nLockTime < LOCKTIME_THRESHOLD ? (int64_t)nBlockHeight : nBlockTime))
      28                 :             :         return true;
      29                 :             : 
      30                 :             :     // Even if tx.nLockTime isn't satisfied by nBlockHeight/nBlockTime, a
      31                 :             :     // transaction is still considered final if all inputs' nSequence ==
      32                 :             :     // SEQUENCE_FINAL (0xffffffff), in which case nLockTime is ignored.
      33                 :             :     //
      34                 :             :     // Because of this behavior OP_CHECKLOCKTIMEVERIFY/CheckLockTime() will
      35                 :             :     // also check that the spending input's nSequence != SEQUENCE_FINAL,
      36                 :             :     // ensuring that an unsatisfied nLockTime value will actually cause
      37                 :             :     // IsFinalTx() to return false here:
      38         [ +  + ]:     1390517 :     for (const auto& txin : tx.vin) {
      39         [ +  + ]:      803989 :         if (!(txin.nSequence == CTxIn::SEQUENCE_FINAL))
      40                 :             :             return false;
      41                 :             :     }
      42                 :             :     return true;
      43                 :             : }
      44                 :             : 
      45                 :     1790487 : std::pair<int, int64_t> CalculateSequenceLocks(const CTransaction &tx, int flags, std::vector<int>& prevHeights, const CBlockIndex& block)
      46                 :             : {
      47   [ -  +  -  +  :     1790487 :     assert(prevHeights.size() == tx.vin.size());
                   -  + ]
      48                 :             : 
      49                 :             :     // Will be set to the equivalent height- and time-based nLockTime
      50                 :             :     // values that would be necessary to satisfy all relative lock-
      51                 :             :     // time constraints given our view of block chain history.
      52                 :             :     // The semantics of nLockTime are the last invalid height/time, so
      53                 :             :     // use -1 to have the effect of any height or time being valid.
      54                 :     1790487 :     int nMinHeight = -1;
      55                 :     1790487 :     int64_t nMinTime = -1;
      56                 :             : 
      57   [ +  +  -  + ]:     1790487 :     bool fEnforceBIP68 = tx.version >= 2 && flags & LOCKTIME_VERIFY_SEQUENCE;
      58                 :             : 
      59                 :             :     // Do not enforce sequence numbers as a relative lock time
      60                 :             :     // unless we have been instructed to
      61                 :         555 :     if (!fEnforceBIP68) {
      62                 :         555 :         return std::make_pair(nMinHeight, nMinTime);
      63                 :             :     }
      64                 :             : 
      65   [ -  +  +  + ]:     8218115 :     for (size_t txinIndex = 0; txinIndex < tx.vin.size(); txinIndex++) {
      66         [ +  + ]:     6428183 :         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         [ +  + ]:     6428183 :         if (txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_DISABLE_FLAG) {
      72                 :             :             // The height of this input is not relevant for sequence locks
      73                 :     5444027 :             prevHeights[txinIndex] = 0;
      74                 :     5444027 :             continue;
      75                 :             :         }
      76                 :             : 
      77         [ +  + ]:      984156 :         int nCoinHeight = prevHeights[txinIndex];
      78                 :             : 
      79         [ +  + ]:      984156 :         if (txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG) {
      80   [ +  -  -  + ]:      185208 :             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         [ +  + ]:      141496 :             nMinTime = std::max(nMinTime, nCoinTime + (int64_t)((txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_MASK) << CTxIn::SEQUENCE_LOCKTIME_GRANULARITY) - 1);
      95                 :             :         } else {
      96         [ +  + ]:     1528231 :             nMinHeight = std::max(nMinHeight, nCoinHeight + (int)(txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_MASK) - 1);
      97                 :             :         }
      98                 :             :     }
      99                 :             : 
     100                 :     1789932 :     return std::make_pair(nMinHeight, nMinTime);
     101                 :             : }
     102                 :             : 
     103                 :     1790487 : bool EvaluateSequenceLocks(const CBlockIndex& block, std::pair<int, int64_t> lockPair)
     104                 :             : {
     105         [ -  + ]:     1790487 :     assert(block.pprev);
     106                 :     1790487 :     int64_t nBlockTime = block.pprev->GetMedianTimePast();
     107   [ +  +  +  + ]:     1790487 :     if (lockPair.first >= block.nHeight || lockPair.second >= nBlockTime)
     108                 :       71664 :         return false;
     109                 :             : 
     110                 :             :     return true;
     111                 :             : }
     112                 :             : 
     113                 :       63955 : bool SequenceLocks(const CTransaction &tx, int flags, std::vector<int>& prevHeights, const CBlockIndex& block)
     114                 :             : {
     115                 :       63955 :     return EvaluateSequenceLocks(block, CalculateSequenceLocks(tx, flags, prevHeights, block));
     116                 :             : }
     117                 :             : 
     118                 :     4123845 : unsigned int GetLegacySigOpCount(const CTransaction& tx)
     119                 :             : {
     120                 :     4123845 :     unsigned int nSigOps = 0;
     121         [ +  + ]:    11247860 :     for (const auto& txin : tx.vin)
     122                 :             :     {
     123                 :     7124015 :         nSigOps += txin.scriptSig.GetSigOpCount(false);
     124                 :             :     }
     125         [ +  + ]:    27409067 :     for (const auto& txout : tx.vout)
     126                 :             :     {
     127                 :    23285222 :         nSigOps += txout.scriptPubKey.GetSigOpCount(false);
     128                 :             :     }
     129                 :     4123845 :     return nSigOps;
     130                 :             : }
     131                 :             : 
     132                 :     1693170 : unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& inputs)
     133                 :             : {
     134         [ +  + ]:     1693170 :     if (tx.IsCoinBase())
     135                 :             :         return 0;
     136                 :             : 
     137                 :             :     unsigned int nSigOps = 0;
     138   [ -  +  +  + ]:     5976514 :     for (unsigned int i = 0; i < tx.vin.size(); i++)
     139                 :             :     {
     140                 :     4283349 :         const Coin& coin = inputs.AccessCoin(tx.vin[i].prevout);
     141         [ -  + ]:     4283349 :         assert(!coin.IsSpent());
     142                 :     4283349 :         const CTxOut &prevout = coin.out;
     143         [ +  + ]:     4283349 :         if (prevout.scriptPubKey.IsPayToScriptHash())
     144                 :         819 :             nSigOps += prevout.scriptPubKey.GetSigOpCount(tx.vin[i].scriptSig);
     145                 :             :     }
     146                 :             :     return nSigOps;
     147                 :             : }
     148                 :             : 
     149                 :     2562116 : int64_t GetTransactionSigOpCost(const CTransaction& tx, const CCoinsViewCache& inputs, script_verify_flags flags)
     150                 :             : {
     151                 :     2562116 :     int64_t nSigOps = GetLegacySigOpCount(tx) * WITNESS_SCALE_FACTOR;
     152                 :             : 
     153         [ +  + ]:     2562116 :     if (tx.IsCoinBase())
     154                 :             :         return nSigOps;
     155                 :             : 
     156         [ +  + ]:     1691676 :     if (flags & SCRIPT_VERIFY_P2SH) {
     157                 :     1691476 :         nSigOps += GetP2SHSigOpCount(tx, inputs) * WITNESS_SCALE_FACTOR;
     158                 :             :     }
     159                 :             : 
     160   [ -  +  +  + ]:     5974984 :     for (unsigned int i = 0; i < tx.vin.size(); i++)
     161                 :             :     {
     162                 :     4283308 :         const Coin& coin = inputs.AccessCoin(tx.vin[i].prevout);
     163         [ -  + ]:     4283308 :         assert(!coin.IsSpent());
     164                 :     4283308 :         const CTxOut &prevout = coin.out;
     165                 :     4283308 :         nSigOps += CountWitnessSigOps(tx.vin[i].scriptSig, prevout.scriptPubKey, tx.vin[i].scriptWitness, flags);
     166                 :             :     }
     167                 :             :     return nSigOps;
     168                 :             : }
     169                 :             : 
     170                 :     2168952 : bool Consensus::CheckTxInputs(const CTransaction& tx, TxValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, CAmount& txfee)
     171                 :             : {
     172                 :             :     // are the actual inputs available?
     173         [ +  + ]:     2168952 :     if (!inputs.HaveInputs(tx)) {
     174   [ +  -  +  - ]:        8081 :         return state.Invalid(TxValidationResult::TX_MISSING_INPUTS, "bad-txns-inputs-missingorspent",
     175                 :       16162 :                          strprintf("%s: inputs missing/spent", __func__));
     176                 :             :     }
     177                 :             : 
     178                 :             :     CAmount nValueIn = 0;
     179   [ -  +  +  + ]:     7247107 :     for (unsigned int i = 0; i < tx.vin.size(); ++i) {
     180                 :     5092596 :         const COutPoint &prevout = tx.vin[i].prevout;
     181                 :     5092596 :         const Coin& coin = inputs.AccessCoin(prevout);
     182         [ -  + ]:     5092596 :         assert(!coin.IsSpent());
     183                 :             : 
     184                 :             :         // If prev is coinbase, check that it's matured
     185   [ +  +  +  + ]:     5092596 :         if (coin.IsCoinBase() && nSpendHeight - coin.nHeight < COINBASE_MATURITY) {
     186   [ +  -  +  - ]:        6349 :             return state.Invalid(TxValidationResult::TX_PREMATURE_SPEND, "bad-txns-premature-spend-of-coinbase",
     187                 :       12698 :                 strprintf("tried to spend coinbase at depth %d", nSpendHeight - coin.nHeight));
     188                 :             :         }
     189                 :             : 
     190                 :             :         // Check for negative or overflow input values
     191                 :     5086247 :         nValueIn += coin.out.nValue;
     192   [ +  +  +  - ]:     5086247 :         if (!MoneyRange(coin.out.nValue) || !MoneyRange(nValueIn)) {
     193   [ +  -  +  - ]:          11 :             return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-inputvalues-outofrange");
     194                 :             :         }
     195                 :             :     }
     196                 :             : 
     197                 :             :     // `tx.GetValueOut()` won't throw in validation paths because output-range checks run first
     198                 :             :     // (`bad-txns-vout-negative`, `bad-txns-vout-toolarge`, `bad-txns-txouttotal-toolarge`):
     199                 :             :     // * `MemPoolAccept::PreChecks`: `CheckTransaction()` is called before this method;
     200                 :             :     // * `Chainstate::ConnectBlock`: `CheckTransaction()` is called via `CheckBlock()` before this method.
     201                 :     2154511 :     const CAmount value_out = tx.GetValueOut();
     202         [ +  + ]:     2154511 :     if (nValueIn < value_out) {
     203   [ +  -  +  - ]:       16841 :         return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-in-belowout",
     204   [ +  -  +  - ]:       33682 :             strprintf("value in (%s) < value out (%s)", FormatMoney(nValueIn), FormatMoney(value_out)));
     205                 :             :     }
     206                 :             : 
     207                 :             :     // Tally transaction fees
     208                 :     2137670 :     const CAmount txfee_aux = nValueIn - value_out;
     209         [ -  + ]:     2137670 :     if (!MoneyRange(txfee_aux)) {
     210                 :             :         // Unreachable, given the following preconditions:
     211                 :             :         // * `value_out` comes from `tx.GetValueOut()`, which throws unless `MoneyRange(value_out)` and asserts `MoneyRange(nValueOut)` on return.
     212                 :             :         // * `MoneyRange(nValueIn)` was enforced in the input loop.
     213                 :             :         // * `nValueIn < value_out` was handled above, so `nValueIn >= value_out` here (and `txfee_aux >= 0`).
     214                 :             :         // Therefore `0 <= txfee_aux = nValueIn - value_out <= nValueIn <= MAX_MONEY`.
     215   [ #  #  #  # ]:           0 :         return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-fee-outofrange");
     216                 :             :     }
     217                 :             : 
     218                 :     2137670 :     txfee = txfee_aux;
     219                 :     2137670 :     return true;
     220                 :             : }
        

Generated by: LCOV version 2.5.0-full