Line data Source code
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"
8 : #include "consensus/zerocoin_verify.h"
9 : #include "sapling/sapling_validation.h"
10 : #include "../validation.h"
11 :
12 9756738 : bool IsFinalTx(const CTransactionRef& tx, int nBlockHeight, int64_t nBlockTime)
13 : {
14 : // Time based nLockTime implemented in 0.1.6
15 9756738 : if (tx->nLockTime == 0)
16 : return true;
17 12 : if (nBlockTime == 0)
18 4 : nBlockTime = GetAdjustedTime();
19 12 : if ((int64_t)tx->nLockTime < ((int64_t)tx->nLockTime < LOCKTIME_THRESHOLD ? (int64_t)nBlockHeight : nBlockTime))
20 : return true;
21 8 : for (const CTxIn& txin : tx->vin)
22 8 : if (!txin.IsFinal())
23 8 : return false;
24 0 : return true;
25 : }
26 :
27 1168707 : unsigned int GetLegacySigOpCount(const CTransaction& tx)
28 : {
29 1168707 : unsigned int nSigOps = 0;
30 3210856 : for (const CTxIn& txin : tx.vin) {
31 2042149 : nSigOps += txin.scriptSig.GetSigOpCount(false);
32 : }
33 4163769 : for (const CTxOut& txout : tx.vout) {
34 2995062 : nSigOps += txout.scriptPubKey.GetSigOpCount(false);
35 : }
36 1168707 : return nSigOps;
37 : }
38 :
39 490447 : unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& inputs)
40 : {
41 490447 : if (tx.IsCoinBase() || tx.HasZerocoinSpendInputs())
42 : // a tx containing a zc spend can have only zc inputs
43 0 : return 0;
44 :
45 : unsigned int nSigOps = 0;
46 1395166 : for (unsigned int i = 0; i < tx.vin.size(); i++) {
47 904721 : const CTxOut& prevout = inputs.AccessCoin(tx.vin[i].prevout).out;
48 904721 : if (prevout.scriptPubKey.IsPayToScriptHash())
49 61904 : nSigOps += prevout.scriptPubKey.GetSigOpCount(tx.vin[i].scriptSig);
50 : }
51 : return nSigOps;
52 : }
53 :
54 766980 : 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 766980 : if (tx.vin.empty() && (tx.sapData && tx.sapData->vShieldedSpend.empty()) && !tx.IsQuorumCommitmentTx())
60 6 : 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 766978 : if (tx.vout.empty() && (tx.sapData && tx.sapData->vShieldedOutput.empty()) && !tx.IsQuorumCommitmentTx())
64 6 : return state.DoS(10, false, REJECT_INVALID, "bad-txns-vout-empty");
65 :
66 : // Version check
67 766976 : if (tx.nVersion < 1 || tx.nVersion >= CTransaction::TxVersion::TOOHIGH) {
68 0 : return state.DoS(10,
69 0 : 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 766976 : static_assert(MAX_BLOCK_SIZE_CURRENT >= MAX_TX_SIZE_AFTER_SAPLING, "Max block size must be bigger than max TX size"); // sanity
75 766976 : 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 766976 : const unsigned int nMaxSize = tx.IsShieldedTx() ? MAX_TX_SIZE_AFTER_SAPLING : MAX_ZEROCOIN_TX_SIZE;
77 766976 : if (tx.GetTotalSize() > nMaxSize) {
78 0 : 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 766976 : CAmount nValueOut = 0;
83 766976 : if (!SaplingValidation::CheckTransaction(tx, state, nValueOut)) {
84 : return false;
85 : }
86 :
87 : // Check for negative or overflow output values
88 766974 : const Consensus::Params& consensus = Params().GetConsensus();
89 2777477 : for (const CTxOut& txout : tx.vout) {
90 2027482 : if (txout.IsEmpty() && !tx.IsCoinBase() && !tx.IsCoinStake())
91 54 : return state.DoS(100, false, REJECT_INVALID, "bad-txns-vout-empty");
92 2010509 : if (txout.nValue < 0)
93 3 : return state.DoS(100, false, REJECT_INVALID, "bad-txns-vout-negative");
94 2010508 : if (txout.nValue > consensus.nMaxMoneyOut)
95 3 : return state.DoS(100, false, REJECT_INVALID, "bad-txns-vout-toolarge");
96 2010507 : nValueOut += txout.nValue;
97 2010507 : if (!consensus.MoneyRange(nValueOut))
98 3 : return state.DoS(100, false, REJECT_INVALID, "bad-txns-txouttotal-toolarge");
99 : // check cold staking enforcement (for delegations) and value out
100 2010506 : if (txout.scriptPubKey.IsPayToColdStaking()) {
101 209 : if (!fColdStakingActive)
102 3 : return state.DoS(10, false, REJECT_INVALID, "cold-stake-inactive");
103 208 : if (txout.nValue < MIN_COLDSTAKING_AMOUNT)
104 0 : return state.DoS(100, false, REJECT_INVALID, "cold-stake-vout-toosmall");
105 : }
106 : }
107 :
108 1533927 : std::set<COutPoint> vInOutPoints;
109 2138630 : for (const CTxIn& txin : tx.vin) {
110 : // Check for duplicate inputs
111 1371682 : if (vInOutPoints.count(txin.prevout))
112 12 : return state.DoS(100, false, REJECT_INVALID, "bad-txns-inputs-duplicate");
113 1371680 : if (!txin.IsZerocoinSpend()) {
114 2743358 : vInOutPoints.insert(txin.prevout);
115 : }
116 : }
117 :
118 766948 : bool hasExchangeUTXOs = tx.HasExchangeAddr();
119 :
120 766948 : if (tx.IsCoinBase()) {
121 72712 : if (tx.vin[0].scriptSig.size() < 2 || tx.vin[0].scriptSig.size() > 150)
122 4 : return state.DoS(100, false, REJECT_INVALID, "bad-cb-length");
123 72389 : if (hasExchangeUTXOs)
124 0 : return state.DoS(100, false, REJECT_INVALID, "bad-exchange-address-in-cb");
125 : } else {
126 1993836 : for (const CTxIn& txin : tx.vin)
127 2604209 : if (txin.prevout.IsNull() && !txin.IsZerocoinSpend())
128 0 : return state.DoS(10, false, REJECT_INVALID, "bad-txns-prevout-null");
129 : }
130 :
131 : return true;
132 : }
133 :
134 555806 : bool ContextualCheckTransaction(const CTransactionRef& tx, CValidationState& state, const CChainParams& chainparams, int nHeight, bool isMined, bool fIBD)
135 : {
136 : // Dispatch to Sapling validator
137 555806 : 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 555805 : if (!ContextualCheckZerocoinTx(tx, state, chainparams.GetConsensus(), nHeight, isMined)) {
143 6 : return false; // Failure reason has been set in validation state object
144 : }
145 :
146 : return true;
147 : }
|