/ src / consensus / tx_check.cpp
tx_check.cpp
 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_check.h>
 6  
 7  #include <consensus/amount.h>
 8  #include <primitives/transaction.h>
 9  #include <consensus/validation.h>
10  
11  bool CheckTransaction(const CTransaction& tx, TxValidationState& state)
12  {
13      // Basic checks that don't depend on any context
14      if (tx.vin.empty())
15          return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-vin-empty");
16      if (tx.vout.empty())
17          return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-vout-empty");
18      // Size limits (this doesn't take the witness into account, as that hasn't been checked for malleability)
19      if (::GetSerializeSize(TX_NO_WITNESS(tx)) * WITNESS_SCALE_FACTOR > MAX_BLOCK_WEIGHT) {
20          return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-oversize");
21      }
22  
23      // Check for negative or overflow output values (see CVE-2010-5139)
24      CAmount nValueOut = 0;
25      for (const auto& txout : tx.vout)
26      {
27          if (txout.nValue < 0)
28              return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-vout-negative");
29          if (txout.nValue > MAX_MONEY)
30              return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-vout-toolarge");
31          nValueOut += txout.nValue;
32          if (!MoneyRange(nValueOut))
33              return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-txouttotal-toolarge");
34      }
35  
36      // Check for duplicate inputs (see CVE-2018-17144)
37      // While Consensus::CheckTxInputs does check if all inputs of a tx are available, and UpdateCoins marks all inputs
38      // of a tx as spent, it does not check if the tx has duplicate inputs.
39      // Failure to run this check will result in either a crash or an inflation bug, depending on the implementation of
40      // the underlying coins database.
41      std::set<COutPoint> vInOutPoints;
42      for (const auto& txin : tx.vin) {
43          if (!vInOutPoints.insert(txin.prevout).second)
44              return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-inputs-duplicate");
45      }
46  
47      if (tx.IsCoinBase())
48      {
49          if (tx.vin[0].scriptSig.size() < 2 || tx.vin[0].scriptSig.size() > 100)
50              return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-cb-length");
51      }
52      else
53      {
54          for (const auto& txin : tx.vin)
55              if (txin.prevout.IsNull())
56                  return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-prevout-null");
57      }
58  
59      return true;
60  }