LCOV - code coverage report
Current view: top level - src/consensus - tx_check.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 43 44 97.7 %
Date: 2026-06-25 07:23:43 Functions: 1 1 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 <version.h>
       6             : 
       7             : #include <consensus/consensus.h>
       8             : #include <consensus/tx_check.h>
       9             : 
      10             : #include <consensus/amount.h>
      11             : #include <primitives/transaction.h>
      12             : #include <consensus/validation.h>
      13             : 
      14     1003366 : bool CheckTransaction(const CTransaction& tx, TxValidationState& state)
      15             : {
      16     1003366 :     bool allowEmptyTxIn = false;
      17     1003366 :     bool allowEmptyTxOut = false;
      18     1003366 :     if (tx.nType == TRANSACTION_QUORUM_COMMITMENT || tx.nType == TRANSACTION_MNHF_SIGNAL) {
      19      308795 :         allowEmptyTxIn = true;
      20      308795 :         allowEmptyTxOut = true;
      21      308795 :     }
      22     1003366 :     if (tx.nType == TRANSACTION_ASSET_UNLOCK) {
      23         554 :         allowEmptyTxIn = true;
      24         554 :     }
      25             : 
      26             :     // Basic checks that don't depend on any context
      27     1003366 :     if (!allowEmptyTxIn && tx.vin.empty())
      28           8 :         return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-vin-empty");
      29     1003358 :     if (!allowEmptyTxOut && tx.vout.empty())
      30          10 :         return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-vout-empty");
      31             :     // Size limits
      32     1003348 :     if (::GetSerializeSize(tx, PROTOCOL_VERSION) > MAX_LEGACY_BLOCK_SIZE)
      33           2 :         return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-oversize");
      34     1003346 :     if (tx.vExtraPayload.size() > MAX_TX_EXTRA_PAYLOAD)
      35           0 :         return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-payload-oversize");
      36             : 
      37             :     // Check for negative or overflow output values (see CVE-2010-5139)
      38     1003346 :     CAmount nValueOut = 0;
      39     2915711 :     for (const auto& txout : tx.vout) {
      40     1912395 :         if (txout.nValue < 0)
      41          10 :             return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-vout-negative");
      42     1912385 :         if (txout.nValue > MAX_MONEY)
      43          10 :             return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-vout-toolarge");
      44     1912375 :         nValueOut += txout.nValue;
      45     1912375 :         if (!MoneyRange(nValueOut))
      46          10 :             return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-txouttotal-toolarge");
      47             :     }
      48             : 
      49             :     // Check for duplicate inputs (see CVE-2018-17144)
      50             :     // While Consensus::CheckTxInputs does check if all inputs of a tx are available, and UpdateCoins marks all inputs
      51             :     // of a tx as spent, it does not check if the tx has duplicate inputs.
      52             :     // Failure to run this check will result in either a crash or an inflation bug, depending on the implementation of
      53             :     // the underlying coins database.
      54     1003316 :     std::set<COutPoint> vInOutPoints;
      55     1871852 :     for (const auto& txin : tx.vin) {
      56      870753 :         if (!vInOutPoints.insert(txin.prevout).second)
      57        2217 :             return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-inputs-duplicate");
      58             :     }
      59             : 
      60     1001099 :     if (tx.IsCoinBase()) {
      61      471462 :         size_t minCbSize = 2;
      62      471462 :         if (tx.nType == TRANSACTION_COINBASE) {
      63             :             // With the introduction of CbTx, coinbase scripts are not required anymore to hold a valid block height
      64      219019 :             minCbSize = 1;
      65      219019 :         }
      66      471462 :         if (tx.vin[0].scriptSig.size() < minCbSize || tx.vin[0].scriptSig.size() > 100)
      67           8 :             return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-cb-length");
      68      471454 :     } else {
      69      924482 :         for (const auto& txin : tx.vin)
      70      394856 :             if (txin.prevout.IsNull())
      71          11 :                 return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-prevout-null");
      72             :     }
      73             : 
      74     1001080 :     return true;
      75     1003366 : }

Generated by: LCOV version 1.16