Changeset View
Changeset View
Standalone View
Standalone View
src/validation.cpp
Show First 20 Lines • Show All 679 Lines • ▼ Show 20 Lines | for (const CTxIn &txin : tx.vin) { | ||||
fSpendsCoinbase = true; | fSpendsCoinbase = true; | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
const uint32_t nextBlockScriptVerifyFlags = | const uint32_t nextBlockScriptVerifyFlags = | ||||
GetNextBlockScriptFlags(consensusParams, chainActive.Tip()); | GetNextBlockScriptFlags(consensusParams, chainActive.Tip()); | ||||
int64_t nSigOpsCount = | auto nSigOpsCount = | ||||
GetTransactionSigOpCount(tx, view, nextBlockScriptVerifyFlags); | GetTransactionSigOpCount(tx, view, nextBlockScriptVerifyFlags); | ||||
// Check that the transaction doesn't have an excessive number of | // Check that the transaction doesn't have an excessive number of | ||||
// sigops. This is more strict than the consensus limit of | // sigops. | ||||
// MAX_TX_SIGOPS_COUNT per transaction enforced in | static_assert(MAX_STANDARD_TX_SIGOPS <= MAX_TX_SIGOPS_COUNT, | ||||
// CheckRegularTransaction above. | "we don't want transactions we can't even mine"); | ||||
if (nSigOpsCount > MAX_STANDARD_TX_SIGOPS) { | if (nSigOpsCount > MAX_STANDARD_TX_SIGOPS) { | ||||
return state.DoS(0, false, REJECT_NONSTANDARD, | return state.DoS(0, false, REJECT_NONSTANDARD, | ||||
"bad-txns-too-many-sigops", false, | "bad-txns-too-many-sigops", false, | ||||
strprintf("%d", nSigOpsCount)); | strprintf("%d", nSigOpsCount)); | ||||
} | } | ||||
CTxMemPoolEntry entry(ptx, nFees, nAcceptTime, chainActive.Height(), | CTxMemPoolEntry entry(ptx, nFees, nAcceptTime, chainActive.Height(), | ||||
fSpendsCoinbase, nSigOpsCount, lp); | fSpendsCoinbase, nSigOpsCount, lp); | ||||
▲ Show 20 Lines • Show All 1,113 Lines • ▼ Show 20 Lines | bool CChainState::ConnectBlock(const CBlock &block, CValidationState &state, | ||||
blockundo.vtxundo.reserve(block.vtx.size() - 1); | blockundo.vtxundo.reserve(block.vtx.size() - 1); | ||||
for (const auto &ptx : block.vtx) { | for (const auto &ptx : block.vtx) { | ||||
const CTransaction &tx = *ptx; | const CTransaction &tx = *ptx; | ||||
nInputs += tx.vin.size(); | nInputs += tx.vin.size(); | ||||
if (tx.IsCoinBase()) { | if (tx.IsCoinBase()) { | ||||
// We've already checked for sigops count before P2SH in CheckBlock. | // Coinbase sigops count towards the block limit. | ||||
nSigOpsCount += GetSigOpCountWithoutP2SH(tx, flags); | auto txSigOpsCount = GetSigOpCountWithoutP2SH(tx, flags); | ||||
nSigOpsCount += txSigOpsCount; | |||||
// We should have already checked the coinbase sigops count limit in | |||||
// ContextualCheckBlock at some earlier time, however we don't | |||||
// currently re-invoke ContextualCheckBlock in this function. So, | |||||
// just in case of any upgrade/downgrade issues, re-check it here. | |||||
if (txSigOpsCount > MAX_TX_SIGOPS_COUNT) { | |||||
return state.DoS(100, false, REJECT_INVALID, "bad-txn-sigops"); | |||||
} | |||||
// Should be redundant since MAX_TX_SIGOPS_COUNT <= nMaxSigOpsCount | |||||
// and there is only one coinbase, but doesn't hurt to check. | |||||
if (nSigOpsCount > nMaxSigOpsCount) { | |||||
return state.DoS(100, error("ConnectBlock(): too many sigops"), | |||||
REJECT_INVALID, "bad-blk-sigops"); | |||||
} | |||||
} | } | ||||
// We do not need to throw when a transaction is duplicated. If they are | // We do not need to throw when a transaction is duplicated. If they are | ||||
// in the same block, CheckBlock will catch it, and if they are in a | // in the same block, CheckBlock will catch it, and if they are in a | ||||
// different block, it'll register as a double spend or BIP30 violation. | // different block, it'll register as a double spend or BIP30 violation. | ||||
// In both cases, we get a more meaningful feedback out of it. | // In both cases, we get a more meaningful feedback out of it. | ||||
AddCoins(view, tx, pindex->nHeight, true); | AddCoins(view, tx, pindex->nHeight, true); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 1,895 Lines • ▼ Show 20 Lines | static bool ContextualCheckBlock(const CBlock &block, CValidationState &state, | ||||
// Note that pindexPrev may be null if reindexing genesis block. | // Note that pindexPrev may be null if reindexing genesis block. | ||||
const auto scriptFlags = pindexPrev | const auto scriptFlags = pindexPrev | ||||
? GetNextBlockScriptFlags(params, pindexPrev) | ? GetNextBlockScriptFlags(params, pindexPrev) | ||||
: SCRIPT_VERIFY_NONE; | : SCRIPT_VERIFY_NONE; | ||||
// Check transactions: | // Check transactions: | ||||
// - canonical ordering | // - canonical ordering | ||||
// - ensure they are finalized | // - ensure they are finalized | ||||
// - perform a preliminary sigops count (they will be recounted more | // - perform a preliminary block-sigops count (they will be recounted more | ||||
// strictly during ConnectBlock) | // strictly during ConnectBlock). | ||||
// - perform a transaction-sigops check (again, a more strict check will | |||||
// happen in ConnectBlock). | |||||
const CTransaction *prevTx = nullptr; | const CTransaction *prevTx = nullptr; | ||||
for (const auto &ptx : block.vtx) { | for (const auto &ptx : block.vtx) { | ||||
const CTransaction &tx = *ptx; | const CTransaction &tx = *ptx; | ||||
if (fIsMagneticAnomalyEnabled) { | if (fIsMagneticAnomalyEnabled) { | ||||
if (prevTx && (tx.GetId() <= prevTx->GetId())) { | if (prevTx && (tx.GetId() <= prevTx->GetId())) { | ||||
if (tx.GetId() == prevTx->GetId()) { | if (tx.GetId() == prevTx->GetId()) { | ||||
return state.DoS(100, false, REJECT_INVALID, "tx-duplicate", | return state.DoS(100, false, REJECT_INVALID, "tx-duplicate", | ||||
false, | false, | ||||
strprintf("Duplicated transaction %s", | strprintf("Duplicated transaction %s", | ||||
tx.GetId().ToString())); | tx.GetId().ToString())); | ||||
} | } | ||||
return state.DoS( | return state.DoS( | ||||
100, false, REJECT_INVALID, "tx-ordering", false, | 100, false, REJECT_INVALID, "tx-ordering", false, | ||||
strprintf("Transaction order is invalid (%s < %s)", | strprintf("Transaction order is invalid (%s < %s)", | ||||
tx.GetId().ToString(), | tx.GetId().ToString(), | ||||
prevTx->GetId().ToString())); | prevTx->GetId().ToString())); | ||||
} | } | ||||
if (prevTx || !tx.IsCoinBase()) { | if (prevTx || !tx.IsCoinBase()) { | ||||
prevTx = &tx; | prevTx = &tx; | ||||
} | } | ||||
} | } | ||||
// Count the sigops for the current transaction. If the total sigops | // Count the sigops for the current transaction. If the tx or total | ||||
// count is too high, the the block is invalid. | // sigops counts are too high, then the block is invalid. | ||||
nSigOps += GetSigOpCountWithoutP2SH(tx, scriptFlags); | const auto txSigOps = GetSigOpCountWithoutP2SH(tx, scriptFlags); | ||||
if (txSigOps > MAX_TX_SIGOPS_COUNT) { | |||||
return state.DoS(100, false, REJECT_INVALID, "bad-txn-sigops", | |||||
false, "out-of-bounds SigOpCount"); | |||||
} | |||||
nSigOps += txSigOps; | |||||
if (nSigOps > nMaxSigOpsCount) { | if (nSigOps > nMaxSigOpsCount) { | ||||
return state.DoS(100, false, REJECT_INVALID, "bad-blk-sigops", | return state.DoS(100, false, REJECT_INVALID, "bad-blk-sigops", | ||||
false, "out-of-bounds SigOpCount"); | false, "out-of-bounds SigOpCount"); | ||||
} | } | ||||
if (!ContextualCheckTransaction(params, tx, state, nHeight, | if (!ContextualCheckTransaction(params, tx, state, nHeight, | ||||
nLockTimeCutoff, nMedianTimePast)) { | nLockTimeCutoff, nMedianTimePast)) { | ||||
// state set by ContextualCheckTransaction. | // state set by ContextualCheckTransaction. | ||||
▲ Show 20 Lines • Show All 1,926 Lines • Show Last 20 Lines |