Changeset View
Changeset View
Standalone View
Standalone View
src/consensus/tx_verify.cpp
Show First 20 Lines • Show All 180 Lines • ▼ Show 20 Lines | |||||
uint64_t GetTransactionSigOpCount(const CTransaction &tx, | uint64_t GetTransactionSigOpCount(const CTransaction &tx, | ||||
const CCoinsViewCache &view, uint32_t flags) { | const CCoinsViewCache &view, uint32_t flags) { | ||||
return GetSigOpCountWithoutP2SH(tx, flags) + | return GetSigOpCountWithoutP2SH(tx, flags) + | ||||
GetP2SHSigOpCount(tx, view, flags); | GetP2SHSigOpCount(tx, view, flags); | ||||
} | } | ||||
static bool CheckTransactionCommon(const CTransaction &tx, | static bool CheckTransactionCommon(const CTransaction &tx, | ||||
CValidationState &state, | CValidationState &state) { | ||||
bool fCheckDuplicateInputs) { | |||||
// Basic checks that don't depend on any context | // Basic checks that don't depend on any context | ||||
if (tx.vin.empty()) { | if (tx.vin.empty()) { | ||||
return state.DoS(10, false, REJECT_INVALID, "bad-txns-vin-empty"); | return state.DoS(10, false, REJECT_INVALID, "bad-txns-vin-empty"); | ||||
} | } | ||||
if (tx.vout.empty()) { | if (tx.vout.empty()) { | ||||
return state.DoS(10, false, REJECT_INVALID, "bad-txns-vout-empty"); | return state.DoS(10, false, REJECT_INVALID, "bad-txns-vout-empty"); | ||||
} | } | ||||
Show All 23 Lines | for (const auto &txout : tx.vout) { | ||||
} | } | ||||
} | } | ||||
if (GetSigOpCountWithoutP2SH(tx, SCRIPT_ENABLE_CHECKDATASIG) > | if (GetSigOpCountWithoutP2SH(tx, SCRIPT_ENABLE_CHECKDATASIG) > | ||||
MAX_TX_SIGOPS_COUNT) { | MAX_TX_SIGOPS_COUNT) { | ||||
return state.DoS(100, false, REJECT_INVALID, "bad-txn-sigops"); | return state.DoS(100, false, REJECT_INVALID, "bad-txn-sigops"); | ||||
} | } | ||||
// Check for duplicate inputs - note that this check is slow so we skip it | |||||
// in CheckBlock | |||||
if (fCheckDuplicateInputs) { | |||||
std::set<COutPoint> vInOutPoints; | |||||
for (const auto &txin : tx.vin) { | |||||
if (!vInOutPoints.insert(txin.prevout).second) { | |||||
return state.DoS(100, false, REJECT_INVALID, | |||||
"bad-txns-inputs-duplicate"); | |||||
} | |||||
} | |||||
} | |||||
return true; | return true; | ||||
} | } | ||||
bool CheckCoinbase(const CTransaction &tx, CValidationState &state, | bool CheckCoinbase(const CTransaction &tx, CValidationState &state) { | ||||
bool fCheckDuplicateInputs) { | |||||
if (!tx.IsCoinBase()) { | if (!tx.IsCoinBase()) { | ||||
return state.DoS(100, false, REJECT_INVALID, "bad-cb-missing", false, | return state.DoS(100, false, REJECT_INVALID, "bad-cb-missing", false, | ||||
"first tx is not coinbase"); | "first tx is not coinbase"); | ||||
} | } | ||||
if (!CheckTransactionCommon(tx, state, fCheckDuplicateInputs)) { | if (!CheckTransactionCommon(tx, state)) { | ||||
// CheckTransactionCommon fill in the state. | // CheckTransactionCommon fill in the state. | ||||
return false; | return false; | ||||
} | } | ||||
if (tx.vin[0].scriptSig.size() < 2 || | if (tx.vin[0].scriptSig.size() < 2 || | ||||
tx.vin[0].scriptSig.size() > MAX_COINBASE_SCRIPTSIG_SIZE) { | tx.vin[0].scriptSig.size() > MAX_COINBASE_SCRIPTSIG_SIZE) { | ||||
return state.DoS(100, false, REJECT_INVALID, "bad-cb-length"); | return state.DoS(100, false, REJECT_INVALID, "bad-cb-length"); | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
bool CheckRegularTransaction(const CTransaction &tx, CValidationState &state, | bool CheckRegularTransaction(const CTransaction &tx, CValidationState &state) { | ||||
bool fCheckDuplicateInputs) { | |||||
if (tx.IsCoinBase()) { | if (tx.IsCoinBase()) { | ||||
return state.DoS(100, false, REJECT_INVALID, "bad-tx-coinbase"); | return state.DoS(100, false, REJECT_INVALID, "bad-tx-coinbase"); | ||||
} | } | ||||
if (!CheckTransactionCommon(tx, state, fCheckDuplicateInputs)) { | if (!CheckTransactionCommon(tx, state)) { | ||||
// CheckTransactionCommon fill in the state. | // CheckTransactionCommon fill in the state. | ||||
return false; | return false; | ||||
} | } | ||||
std::unordered_set<COutPoint, SaltedOutpointHasher> vInOutPoints; | |||||
for (const auto &txin : tx.vin) { | for (const auto &txin : tx.vin) { | ||||
if (txin.prevout.IsNull()) { | if (txin.prevout.IsNull()) { | ||||
return state.DoS(10, false, REJECT_INVALID, | return state.DoS(10, false, REJECT_INVALID, | ||||
"bad-txns-prevout-null"); | "bad-txns-prevout-null"); | ||||
} | } | ||||
if (!vInOutPoints.insert(txin.prevout).second) { | |||||
return state.DoS(100, false, REJECT_INVALID, | |||||
"bad-txns-inputs-duplicate"); | |||||
} | |||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
namespace Consensus { | namespace Consensus { | ||||
bool CheckTxInputs(const CTransaction &tx, CValidationState &state, | bool CheckTxInputs(const CTransaction &tx, CValidationState &state, | ||||
const CCoinsViewCache &inputs, int nSpendHeight) { | const CCoinsViewCache &inputs, int nSpendHeight) { | ||||
▲ Show 20 Lines • Show All 53 Lines • Show Last 20 Lines |