PIVX Core  5.6.99
P2P Digital Currency
tx_verify.cpp
Go to the documentation of this file.
1 // Copyright (c) 2017-2017 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 "tx_verify.h"
6 
7 #include "consensus/consensus.h"
10 #include "../validation.h"
11 
12 bool IsFinalTx(const CTransactionRef& tx, int nBlockHeight, int64_t nBlockTime)
13 {
14  // Time based nLockTime implemented in 0.1.6
15  if (tx->nLockTime == 0)
16  return true;
17  if (nBlockTime == 0)
18  nBlockTime = GetAdjustedTime();
19  if ((int64_t)tx->nLockTime < ((int64_t)tx->nLockTime < LOCKTIME_THRESHOLD ? (int64_t)nBlockHeight : nBlockTime))
20  return true;
21  for (const CTxIn& txin : tx->vin)
22  if (!txin.IsFinal())
23  return false;
24  return true;
25 }
26 
27 unsigned int GetLegacySigOpCount(const CTransaction& tx)
28 {
29  unsigned int nSigOps = 0;
30  for (const CTxIn& txin : tx.vin) {
31  nSigOps += txin.scriptSig.GetSigOpCount(false);
32  }
33  for (const CTxOut& txout : tx.vout) {
34  nSigOps += txout.scriptPubKey.GetSigOpCount(false);
35  }
36  return nSigOps;
37 }
38 
39 unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& inputs)
40 {
41  if (tx.IsCoinBase() || tx.HasZerocoinSpendInputs())
42  // a tx containing a zc spend can have only zc inputs
43  return 0;
44 
45  unsigned int nSigOps = 0;
46  for (unsigned int i = 0; i < tx.vin.size(); i++) {
47  const CTxOut& prevout = inputs.AccessCoin(tx.vin[i].prevout).out;
48  if (prevout.scriptPubKey.IsPayToScriptHash())
49  nSigOps += prevout.scriptPubKey.GetSigOpCount(tx.vin[i].scriptSig);
50  }
51  return nSigOps;
52 }
53 
54 bool CheckTransaction(const CTransaction& tx, CValidationState& state, bool fColdStakingActive)
55 {
56  // Basic checks that don't depend on any context
57  // Transactions containing empty `vin` must have non-empty `vShieldedSpend`,
58  // or they must be quorum commitments (only one per-type allowed in a block)
59  if (tx.vin.empty() && (tx.sapData && tx.sapData->vShieldedSpend.empty()) && !tx.IsQuorumCommitmentTx())
60  return state.DoS(10, false, REJECT_INVALID, "bad-txns-vin-empty");
61  // Transactions containing empty `vout` must have non-empty `vShieldedOutput`,
62  // or they must be quorum commitments (only one per-type allowed in a block)
63  if (tx.vout.empty() && (tx.sapData && tx.sapData->vShieldedOutput.empty()) && !tx.IsQuorumCommitmentTx())
64  return state.DoS(10, false, REJECT_INVALID, "bad-txns-vout-empty");
65 
66  // Version check
67  if (tx.nVersion < 1 || tx.nVersion >= CTransaction::TxVersion::TOOHIGH) {
68  return state.DoS(10,
69  error("%s: Transaction version (%d) too high. Max: %d", __func__, tx.nVersion, int(CTransaction::TxVersion::TOOHIGH) - 1),
70  REJECT_INVALID, "bad-tx-version-too-high");
71  }
72 
73  // Size limits
74  static_assert(MAX_BLOCK_SIZE_CURRENT >= MAX_TX_SIZE_AFTER_SAPLING, "Max block size must be bigger than max TX size"); // sanity
75  static_assert(MAX_TX_SIZE_AFTER_SAPLING > MAX_ZEROCOIN_TX_SIZE, "New max TX size must be bigger than old max TX size"); // sanity
76  const unsigned int nMaxSize = tx.IsShieldedTx() ? MAX_TX_SIZE_AFTER_SAPLING : MAX_ZEROCOIN_TX_SIZE;
77  if (tx.GetTotalSize() > nMaxSize) {
78  return state.DoS(10, error("tx oversize: %d > %d", tx.GetTotalSize(), nMaxSize), REJECT_INVALID, "bad-txns-oversize");
79  }
80 
81  // Dispatch to Sapling validator
82  CAmount nValueOut = 0;
83  if (!SaplingValidation::CheckTransaction(tx, state, nValueOut)) {
84  return false;
85  }
86 
87  // Check for negative or overflow output values
88  const Consensus::Params& consensus = Params().GetConsensus();
89  for (const CTxOut& txout : tx.vout) {
90  if (txout.IsEmpty() && !tx.IsCoinBase() && !tx.IsCoinStake())
91  return state.DoS(100, false, REJECT_INVALID, "bad-txns-vout-empty");
92  if (txout.nValue < 0)
93  return state.DoS(100, false, REJECT_INVALID, "bad-txns-vout-negative");
94  if (txout.nValue > consensus.nMaxMoneyOut)
95  return state.DoS(100, false, REJECT_INVALID, "bad-txns-vout-toolarge");
96  nValueOut += txout.nValue;
97  if (!consensus.MoneyRange(nValueOut))
98  return state.DoS(100, false, REJECT_INVALID, "bad-txns-txouttotal-toolarge");
99  // check cold staking enforcement (for delegations) and value out
100  if (txout.scriptPubKey.IsPayToColdStaking()) {
101  if (!fColdStakingActive)
102  return state.DoS(10, false, REJECT_INVALID, "cold-stake-inactive");
103  if (txout.nValue < MIN_COLDSTAKING_AMOUNT)
104  return state.DoS(100, false, REJECT_INVALID, "cold-stake-vout-toosmall");
105  }
106  }
107 
108  std::set<COutPoint> vInOutPoints;
109  for (const CTxIn& txin : tx.vin) {
110  // Check for duplicate inputs
111  if (vInOutPoints.count(txin.prevout))
112  return state.DoS(100, false, REJECT_INVALID, "bad-txns-inputs-duplicate");
113  if (!txin.IsZerocoinSpend()) {
114  vInOutPoints.insert(txin.prevout);
115  }
116  }
117 
118  bool hasExchangeUTXOs = tx.HasExchangeAddr();
119 
120  if (tx.IsCoinBase()) {
121  if (tx.vin[0].scriptSig.size() < 2 || tx.vin[0].scriptSig.size() > 150)
122  return state.DoS(100, false, REJECT_INVALID, "bad-cb-length");
123  if (hasExchangeUTXOs)
124  return state.DoS(100, false, REJECT_INVALID, "bad-exchange-address-in-cb");
125  } else {
126  for (const CTxIn& txin : tx.vin)
127  if (txin.prevout.IsNull() && !txin.IsZerocoinSpend())
128  return state.DoS(10, false, REJECT_INVALID, "bad-txns-prevout-null");
129  }
130 
131  return true;
132 }
133 
134 bool ContextualCheckTransaction(const CTransactionRef& tx, CValidationState& state, const CChainParams& chainparams, int nHeight, bool isMined, bool fIBD)
135 {
136  // Dispatch to Sapling validator
137  if (!SaplingValidation::ContextualCheckTransaction(*tx, state, chainparams, nHeight, isMined, fIBD)) {
138  return false; // Failure reason has been set in validation state object
139  }
140 
141  // Dispatch to ZerocoinTx validator
142  if (!ContextualCheckZerocoinTx(tx, state, chainparams.GetConsensus(), nHeight, isMined)) {
143  return false; // Failure reason has been set in validation state object
144  }
145 
146  return true;
147 }
int64_t CAmount
Amount in PIV (Can be negative)
Definition: amount.h:13
const CChainParams & Params()
Return the currently selected parameters.
bool IsNull() const
Definition: transaction.h:46
CChainParams defines various tweakable parameters of a given instance of the PIVX system.
Definition: chainparams.h:43
const Consensus::Params & GetConsensus() const
Definition: chainparams.h:72
CCoinsView that adds a memory cache for transactions to another CCoinsView.
Definition: coins.h:283
const Coin & AccessCoin(const COutPoint &output) const
Return a reference to a Coin in the cache, or a pruned one if not found.
Definition: coins.cpp:151
bool IsPayToScriptHash() const
Definition: script.cpp:223
unsigned int GetSigOpCount(bool fAccurate) const
Pre-version-0.6, Bitcoin always counted CHECKMULTISIGs as 20 sigops.
Definition: script.cpp:164
bool IsPayToColdStaking() const
Definition: script.cpp:233
The basic transaction that is broadcasted on the network and contained in blocks.
Definition: transaction.h:244
bool HasZerocoinSpendInputs() const
bool HasExchangeAddr() const
bool IsQuorumCommitmentTx() const
Definition: transaction.h:341
std::vector< CTxIn > vin
Definition: transaction.h:270
const int16_t nVersion
Definition: transaction.h:272
bool IsShieldedTx() const
Definition: transaction.h:319
unsigned int GetTotalSize() const
bool IsCoinBase() const
Definition: transaction.h:376
Optional< SaplingTxData > sapData
Definition: transaction.h:275
bool IsCoinStake() const
std::vector< CTxOut > vout
Definition: transaction.h:271
An input of a transaction.
Definition: transaction.h:94
bool IsZerocoinSpend() const
Definition: transaction.cpp:43
CScript scriptSig
Definition: transaction.h:97
bool IsFinal() const
Definition: transaction.h:110
COutPoint prevout
Definition: transaction.h:96
An output of a transaction.
Definition: transaction.h:137
CScript scriptPubKey
Definition: transaction.h:140
CAmount nValue
Definition: transaction.h:139
bool IsEmpty() const
Definition: transaction.h:170
Capture information about block/transaction validation.
Definition: validation.h:24
bool DoS(int level, bool ret=false, unsigned int chRejectCodeIn=0, std::string strRejectReasonIn="", bool corruptionIn=false, const std::string &strDebugMessageIn="")
Definition: validation.h:39
CTxOut out
unspent transaction output
Definition: coins.h:41
bool CheckTransaction(const CTransaction &tx, CValidationState &state, CAmount &nValueOut)
Context-independent validity checks.
bool ContextualCheckTransaction(const CTransaction &tx, CValidationState &state, const CChainParams &chainparams, const int nHeight, const bool isMined, bool isInitBlockDownload)
Check a transaction contextually against a set of consensus rules valid at a given block height.
Parameters that influence chain consensus.
Definition: params.h:171
CAmount nMaxMoneyOut
Definition: params.h:183
bool MoneyRange(const CAmount &nValue) const
Definition: params.h:217
bool error(const char *fmt, const Args &... args)
Definition: system.h:77
int64_t GetAdjustedTime()
Definition: timedata.cpp:36
std::shared_ptr< const CTransaction > CTransactionRef
Definition: transaction.h:456
bool IsFinalTx(const CTransactionRef &tx, int nBlockHeight, int64_t nBlockTime)
Check if transaction is final and can be included in a block with the specified height and time.
Definition: tx_verify.cpp:12
bool CheckTransaction(const CTransaction &tx, CValidationState &state, bool fColdStakingActive)
Transaction validation functions.
Definition: tx_verify.cpp:54
bool ContextualCheckTransaction(const CTransactionRef &tx, CValidationState &state, const CChainParams &chainparams, int nHeight, bool isMined, bool fIBD)
Context-dependent validity checks.
Definition: tx_verify.cpp:134
unsigned int GetLegacySigOpCount(const CTransaction &tx)
Count ECDSA signature operations the old-fashioned (pre-0.6) way.
Definition: tx_verify.cpp:27
unsigned int GetP2SHSigOpCount(const CTransaction &tx, const CCoinsViewCache &inputs)
Count ECDSA signature operations in pay-to-script-hash inputs.
Definition: tx_verify.cpp:39
bool ContextualCheckZerocoinTx(const CTransactionRef &tx, CValidationState &state, const Consensus::Params &consensus, int nHeight, bool isMined)