|
| 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.h" |
| 8 | +#include "primitives/transaction.h" |
| 9 | +#include "script/interpreter.h" |
| 10 | +#include "validation.h" |
| 11 | + |
| 12 | +// TODO remove the following dependencies |
| 13 | +#include "chain.h" |
| 14 | +#include "coins.h" |
| 15 | +#include "utilmoneystr.h" |
| 16 | + |
| 17 | +bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime) |
| 18 | +{ |
| 19 | + if (tx.nLockTime == 0) |
| 20 | + return true; |
| 21 | + if ((int64_t)tx.nLockTime < ((int64_t)tx.nLockTime < LOCKTIME_THRESHOLD ? (int64_t)nBlockHeight : nBlockTime)) |
| 22 | + return true; |
| 23 | + for (const auto& txin : tx.vin) { |
| 24 | + if (!(txin.nSequence == CTxIn::SEQUENCE_FINAL)) |
| 25 | + return false; |
| 26 | + } |
| 27 | + return true; |
| 28 | +} |
| 29 | + |
| 30 | +std::pair<int, int64_t> CalculateSequenceLocks(const CTransaction &tx, int flags, std::vector<int>* prevHeights, const CBlockIndex& block) |
| 31 | +{ |
| 32 | + assert(prevHeights->size() == tx.vin.size()); |
| 33 | + |
| 34 | + // Will be set to the equivalent height- and time-based nLockTime |
| 35 | + // values that would be necessary to satisfy all relative lock- |
| 36 | + // time constraints given our view of block chain history. |
| 37 | + // The semantics of nLockTime are the last invalid height/time, so |
| 38 | + // use -1 to have the effect of any height or time being valid. |
| 39 | + int nMinHeight = -1; |
| 40 | + int64_t nMinTime = -1; |
| 41 | + |
| 42 | + // tx.nVersion is signed integer so requires cast to unsigned otherwise |
| 43 | + // we would be doing a signed comparison and half the range of nVersion |
| 44 | + // wouldn't support BIP 68. |
| 45 | + bool fEnforceBIP68 = static_cast<uint32_t>(tx.nVersion) >= 2 |
| 46 | + && flags & LOCKTIME_VERIFY_SEQUENCE; |
| 47 | + |
| 48 | + // Do not enforce sequence numbers as a relative lock time |
| 49 | + // unless we have been instructed to |
| 50 | + if (!fEnforceBIP68) { |
| 51 | + return std::make_pair(nMinHeight, nMinTime); |
| 52 | + } |
| 53 | + |
| 54 | + for (size_t txinIndex = 0; txinIndex < tx.vin.size(); txinIndex++) { |
| 55 | + const CTxIn& txin = tx.vin[txinIndex]; |
| 56 | + |
| 57 | + // Sequence numbers with the most significant bit set are not |
| 58 | + // treated as relative lock-times, nor are they given any |
| 59 | + // consensus-enforced meaning at this point. |
| 60 | + if (txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_DISABLE_FLAG) { |
| 61 | + // The height of this input is not relevant for sequence locks |
| 62 | + (*prevHeights)[txinIndex] = 0; |
| 63 | + continue; |
| 64 | + } |
| 65 | + |
| 66 | + int nCoinHeight = (*prevHeights)[txinIndex]; |
| 67 | + |
| 68 | + if (txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG) { |
| 69 | + int64_t nCoinTime = block.GetAncestor(std::max(nCoinHeight-1, 0))->GetMedianTimePast(); |
| 70 | + // NOTE: Subtract 1 to maintain nLockTime semantics |
| 71 | + // BIP 68 relative lock times have the semantics of calculating |
| 72 | + // the first block or time at which the transaction would be |
| 73 | + // valid. When calculating the effective block time or height |
| 74 | + // for the entire transaction, we switch to using the |
| 75 | + // semantics of nLockTime which is the last invalid block |
| 76 | + // time or height. Thus we subtract 1 from the calculated |
| 77 | + // time or height. |
| 78 | + |
| 79 | + // Time-based relative lock-times are measured from the |
| 80 | + // smallest allowed timestamp of the block containing the |
| 81 | + // txout being spent, which is the median time past of the |
| 82 | + // block prior. |
| 83 | + nMinTime = std::max(nMinTime, nCoinTime + (int64_t)((txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_MASK) << CTxIn::SEQUENCE_LOCKTIME_GRANULARITY) - 1); |
| 84 | + } else { |
| 85 | + nMinHeight = std::max(nMinHeight, nCoinHeight + (int)(txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_MASK) - 1); |
| 86 | + } |
| 87 | + } |
| 88 | + |
| 89 | + return std::make_pair(nMinHeight, nMinTime); |
| 90 | +} |
| 91 | + |
| 92 | +bool EvaluateSequenceLocks(const CBlockIndex& block, std::pair<int, int64_t> lockPair) |
| 93 | +{ |
| 94 | + assert(block.pprev); |
| 95 | + int64_t nBlockTime = block.pprev->GetMedianTimePast(); |
| 96 | + if (lockPair.first >= block.nHeight || lockPair.second >= nBlockTime) |
| 97 | + return false; |
| 98 | + |
| 99 | + return true; |
| 100 | +} |
| 101 | + |
| 102 | +bool SequenceLocks(const CTransaction &tx, int flags, std::vector<int>* prevHeights, const CBlockIndex& block) |
| 103 | +{ |
| 104 | + return EvaluateSequenceLocks(block, CalculateSequenceLocks(tx, flags, prevHeights, block)); |
| 105 | +} |
| 106 | + |
| 107 | +unsigned int GetLegacySigOpCount(const CTransaction& tx) |
| 108 | +{ |
| 109 | + unsigned int nSigOps = 0; |
| 110 | + for (const auto& txin : tx.vin) |
| 111 | + { |
| 112 | + nSigOps += txin.scriptSig.GetSigOpCount(false); |
| 113 | + } |
| 114 | + for (const auto& txout : tx.vout) |
| 115 | + { |
| 116 | + nSigOps += txout.scriptPubKey.GetSigOpCount(false); |
| 117 | + } |
| 118 | + return nSigOps; |
| 119 | +} |
| 120 | + |
| 121 | +unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& inputs) |
| 122 | +{ |
| 123 | + if (tx.IsCoinBase()) |
| 124 | + return 0; |
| 125 | + |
| 126 | + unsigned int nSigOps = 0; |
| 127 | + for (unsigned int i = 0; i < tx.vin.size(); i++) |
| 128 | + { |
| 129 | + const CTxOut &prevout = inputs.GetOutputFor(tx.vin[i]); |
| 130 | + if (prevout.scriptPubKey.IsPayToScriptHash()) |
| 131 | + nSigOps += prevout.scriptPubKey.GetSigOpCount(tx.vin[i].scriptSig); |
| 132 | + } |
| 133 | + return nSigOps; |
| 134 | +} |
| 135 | + |
| 136 | +int64_t GetTransactionSigOpCost(const CTransaction& tx, const CCoinsViewCache& inputs, int flags) |
| 137 | +{ |
| 138 | + int64_t nSigOps = GetLegacySigOpCount(tx) * WITNESS_SCALE_FACTOR; |
| 139 | + |
| 140 | + if (tx.IsCoinBase()) |
| 141 | + return nSigOps; |
| 142 | + |
| 143 | + if (flags & SCRIPT_VERIFY_P2SH) { |
| 144 | + nSigOps += GetP2SHSigOpCount(tx, inputs) * WITNESS_SCALE_FACTOR; |
| 145 | + } |
| 146 | + |
| 147 | + for (unsigned int i = 0; i < tx.vin.size(); i++) |
| 148 | + { |
| 149 | + const CTxOut &prevout = inputs.GetOutputFor(tx.vin[i]); |
| 150 | + nSigOps += CountWitnessSigOps(tx.vin[i].scriptSig, prevout.scriptPubKey, &tx.vin[i].scriptWitness, flags); |
| 151 | + } |
| 152 | + return nSigOps; |
| 153 | +} |
| 154 | + |
| 155 | +bool CheckTransaction(const CTransaction& tx, CValidationState &state, bool fCheckDuplicateInputs) |
| 156 | +{ |
| 157 | + // Basic checks that don't depend on any context |
| 158 | + if (tx.vin.empty()) |
| 159 | + return state.DoS(10, false, REJECT_INVALID, "bad-txns-vin-empty"); |
| 160 | + if (tx.vout.empty()) |
| 161 | + return state.DoS(10, false, REJECT_INVALID, "bad-txns-vout-empty"); |
| 162 | + // Size limits (this doesn't take the witness into account, as that hasn't been checked for malleability) |
| 163 | + if (::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) > MAX_BLOCK_BASE_SIZE) |
| 164 | + return state.DoS(100, false, REJECT_INVALID, "bad-txns-oversize"); |
| 165 | + |
| 166 | + // Check for negative or overflow output values |
| 167 | + CAmount nValueOut = 0; |
| 168 | + for (const auto& txout : tx.vout) |
| 169 | + { |
| 170 | + if (txout.nValue < 0) |
| 171 | + return state.DoS(100, false, REJECT_INVALID, "bad-txns-vout-negative"); |
| 172 | + if (txout.nValue > MAX_MONEY) |
| 173 | + return state.DoS(100, false, REJECT_INVALID, "bad-txns-vout-toolarge"); |
| 174 | + nValueOut += txout.nValue; |
| 175 | + if (!MoneyRange(nValueOut)) |
| 176 | + return state.DoS(100, false, REJECT_INVALID, "bad-txns-txouttotal-toolarge"); |
| 177 | + } |
| 178 | + |
| 179 | + // Check for duplicate inputs - note that this check is slow so we skip it in CheckBlock |
| 180 | + if (fCheckDuplicateInputs) { |
| 181 | + std::set<COutPoint> vInOutPoints; |
| 182 | + for (const auto& txin : tx.vin) |
| 183 | + { |
| 184 | + if (!vInOutPoints.insert(txin.prevout).second) |
| 185 | + return state.DoS(100, false, REJECT_INVALID, "bad-txns-inputs-duplicate"); |
| 186 | + } |
| 187 | + } |
| 188 | + |
| 189 | + if (tx.IsCoinBase()) |
| 190 | + { |
| 191 | + if (tx.vin[0].scriptSig.size() < 2 || tx.vin[0].scriptSig.size() > 100) |
| 192 | + return state.DoS(100, false, REJECT_INVALID, "bad-cb-length"); |
| 193 | + } |
| 194 | + else |
| 195 | + { |
| 196 | + for (const auto& txin : tx.vin) |
| 197 | + if (txin.prevout.IsNull()) |
| 198 | + return state.DoS(10, false, REJECT_INVALID, "bad-txns-prevout-null"); |
| 199 | + } |
| 200 | + |
| 201 | + return true; |
| 202 | +} |
| 203 | + |
| 204 | +bool Consensus::CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight) |
| 205 | +{ |
| 206 | + // This doesn't trigger the DoS code on purpose; if it did, it would make it easier |
| 207 | + // for an attacker to attempt to split the network. |
| 208 | + if (!inputs.HaveInputs(tx)) |
| 209 | + return state.Invalid(false, 0, "", "Inputs unavailable"); |
| 210 | + |
| 211 | + CAmount nValueIn = 0; |
| 212 | + CAmount nFees = 0; |
| 213 | + for (unsigned int i = 0; i < tx.vin.size(); i++) |
| 214 | + { |
| 215 | + const COutPoint &prevout = tx.vin[i].prevout; |
| 216 | + const CCoins *coins = inputs.AccessCoins(prevout.hash); |
| 217 | + assert(coins); |
| 218 | + |
| 219 | + // If prev is coinbase, check that it's matured |
| 220 | + if (coins->IsCoinBase()) { |
| 221 | + if (nSpendHeight - coins->nHeight < COINBASE_MATURITY) |
| 222 | + return state.Invalid(false, |
| 223 | + REJECT_INVALID, "bad-txns-premature-spend-of-coinbase", |
| 224 | + strprintf("tried to spend coinbase at depth %d", nSpendHeight - coins->nHeight)); |
| 225 | + } |
| 226 | + |
| 227 | + // Check for negative or overflow input values |
| 228 | + nValueIn += coins->vout[prevout.n].nValue; |
| 229 | + if (!MoneyRange(coins->vout[prevout.n].nValue) || !MoneyRange(nValueIn)) |
| 230 | + return state.DoS(100, false, REJECT_INVALID, "bad-txns-inputvalues-outofrange"); |
| 231 | + |
| 232 | + } |
| 233 | + |
| 234 | + if (nValueIn < tx.GetValueOut()) |
| 235 | + return state.DoS(100, false, REJECT_INVALID, "bad-txns-in-belowout", false, |
| 236 | + strprintf("value in (%s) < value out (%s)", FormatMoney(nValueIn), FormatMoney(tx.GetValueOut()))); |
| 237 | + |
| 238 | + // Tally transaction fees |
| 239 | + CAmount nTxFee = nValueIn - tx.GetValueOut(); |
| 240 | + if (nTxFee < 0) |
| 241 | + return state.DoS(100, false, REJECT_INVALID, "bad-txns-fee-negative"); |
| 242 | + nFees += nTxFee; |
| 243 | + if (!MoneyRange(nFees)) |
| 244 | + return state.DoS(100, false, REJECT_INVALID, "bad-txns-fee-outofrange"); |
| 245 | + return true; |
| 246 | +} |
0 commit comments