Changeset View
Changeset View
Standalone View
Standalone View
src/validation.cpp
Show First 20 Lines • Show All 3,551 Lines • ▼ Show 20 Lines | bool CheckBlock(const CBlock &block, CValidationState &state, | ||||
if (!CheckCoinbase(*block.vtx[0], state)) { | if (!CheckCoinbase(*block.vtx[0], state)) { | ||||
return state.Invalid(false, state.GetRejectCode(), | return state.Invalid(false, state.GetRejectCode(), | ||||
state.GetRejectReason(), | state.GetRejectReason(), | ||||
strprintf("Coinbase check failed (txid %s) %s", | strprintf("Coinbase check failed (txid %s) %s", | ||||
block.vtx[0]->GetId().ToString(), | block.vtx[0]->GetId().ToString(), | ||||
state.GetDebugMessage())); | state.GetDebugMessage())); | ||||
} | } | ||||
// Keep track of the sigops count. | // Check transactions for regularity, skipping the first. Note that this | ||||
uint64_t nSigOps = 0; | // is the first time we check that all after the first are !IsCoinBase. | ||||
auto nMaxSigOpsCount = GetMaxBlockSigOpsCount(currentBlockSize); | for (size_t i = 1; i < block.vtx.size(); i++) { | ||||
auto *tx = block.vtx[i].get(); | |||||
// Check transactions | |||||
auto txCount = block.vtx.size(); | |||||
auto *tx = block.vtx[0].get(); | |||||
size_t i = 0; | |||||
while (true) { | |||||
// Count the sigops for the current transaction. If the total sigops | |||||
// count is too high, the the block is invalid. | |||||
nSigOps += GetSigOpCountWithoutP2SH(*tx, STANDARD_SCRIPT_VERIFY_FLAGS); | |||||
if (nSigOps > nMaxSigOpsCount) { | |||||
return state.DoS(100, false, REJECT_INVALID, "bad-blk-sigops", | |||||
false, "out-of-bounds SigOpCount"); | |||||
} | |||||
// Go to the next transaction. | |||||
i++; | |||||
// We reached the end of the block, success. | |||||
if (i >= txCount) { | |||||
break; | |||||
} | |||||
// Check that the transaction is valid. Because this check differs for | |||||
// the coinbase, the loop is arranged such as this only runs after at | |||||
// least one increment. | |||||
tx = block.vtx[i].get(); | |||||
if (!CheckRegularTransaction(*tx, state)) { | if (!CheckRegularTransaction(*tx, state)) { | ||||
return state.Invalid( | return state.Invalid( | ||||
false, state.GetRejectCode(), state.GetRejectReason(), | false, state.GetRejectCode(), state.GetRejectReason(), | ||||
strprintf("Transaction check failed (txid %s) %s", | strprintf("Transaction check failed (txid %s) %s", | ||||
tx->GetId().ToString(), state.GetDebugMessage())); | tx->GetId().ToString(), state.GetDebugMessage())); | ||||
} | } | ||||
} | } | ||||
▲ Show 20 Lines • Show All 146 Lines • ▼ Show 20 Lines | static bool ContextualCheckBlock(const CBlock &block, CValidationState &state, | ||||
const int64_t nLockTimeCutoff = (nLockTimeFlags & LOCKTIME_MEDIAN_TIME_PAST) | const int64_t nLockTimeCutoff = (nLockTimeFlags & LOCKTIME_MEDIAN_TIME_PAST) | ||||
? nMedianTimePast | ? nMedianTimePast | ||||
: block.GetBlockTime(); | : block.GetBlockTime(); | ||||
const bool fIsMagneticAnomalyEnabled = | const bool fIsMagneticAnomalyEnabled = | ||||
IsMagneticAnomalyEnabled(params, pindexPrev); | IsMagneticAnomalyEnabled(params, pindexPrev); | ||||
// Check that all transactions are finalized | // Keep track of the sigops count. | ||||
uint64_t nSigOps = 0; | |||||
const auto currentBlockSize = ::GetSerializeSize(block, PROTOCOL_VERSION); | |||||
auto nMaxSigOpsCount = GetMaxBlockSigOpsCount(currentBlockSize); | |||||
// Note that pindexPrev may be null if reindexing genesis block. | |||||
const auto scriptFlags = pindexPrev | |||||
? GetNextBlockScriptFlags(params, pindexPrev) | |||||
: SCRIPT_VERIFY_NONE; | |||||
// Check transactions: | |||||
// - canonical ordering | |||||
// - ensure they are finalized | |||||
// - perform a preliminary sigops count (they will be recounted more | |||||
// strictly during 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 is too high, the the block is invalid. | |||||
nSigOps += GetSigOpCountWithoutP2SH(tx, scriptFlags); | |||||
if (nSigOps > nMaxSigOpsCount) { | |||||
return state.DoS(100, false, REJECT_INVALID, "bad-blk-sigops", | |||||
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. | ||||
return false; | return false; | ||||
} | } | ||||
} | } | ||||
// Enforce rule that the coinbase starts with serialized block height | // Enforce rule that the coinbase starts with serialized block height | ||||
▲ Show 20 Lines • Show All 1,921 Lines • Show Last 20 Lines |