Changeset View
Changeset View
Standalone View
Standalone View
src/validation.cpp
Show First 20 Lines • Show All 1,709 Lines • ▼ Show 20 Lines | for (const auto &ptx : block.vtx) { | ||||
pos.nTxOffset += ::GetSerializeSize(tx, SER_DISK, CLIENT_VERSION); | pos.nTxOffset += ::GetSerializeSize(tx, SER_DISK, CLIENT_VERSION); | ||||
if (tx.IsCoinBase()) { | if (tx.IsCoinBase()) { | ||||
// We've already checked for sigops count before P2SH in CheckBlock. | // We've already checked for sigops count before P2SH in CheckBlock. | ||||
nSigOpsCount += GetSigOpCountWithoutP2SH(tx, flags); | nSigOpsCount += GetSigOpCountWithoutP2SH(tx, flags); | ||||
} | } | ||||
if (fIsMagneticAnomalyEnabled || tx.IsCoinBase()) { | if (fIsMagneticAnomalyEnabled || tx.IsCoinBase()) { | ||||
AddCoins(view, tx, pindex->nHeight); | // 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 different block, it'll register as a double spend or BIP30 | |||||
// violation. In both cases, we get a more meaningful feedback out | |||||
// of it. | |||||
AddCoins(view, tx, pindex->nHeight, true); | |||||
} | } | ||||
} | } | ||||
for (const auto &ptx : block.vtx) { | for (const auto &ptx : block.vtx) { | ||||
const CTransaction &tx = *ptx; | const CTransaction &tx = *ptx; | ||||
if (tx.IsCoinBase()) { | if (tx.IsCoinBase()) { | ||||
continue; | continue; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 1,612 Lines • ▼ Show 20 Lines | static bool ContextualCheckBlock(const Config &config, const CBlock &block, | ||||
const bool fIsMagneticAnomalyEnabled = | const bool fIsMagneticAnomalyEnabled = | ||||
IsMagneticAnomalyEnabled(config, pindexPrev); | IsMagneticAnomalyEnabled(config, pindexPrev); | ||||
// Check that all transactions are finalized | // Check that all transactions are finalized | ||||
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()) { | |||||
return state.DoS(100, false, REJECT_INVALID, "tx-duplicate", | |||||
false, | |||||
strprintf("Duplicated transaction %s", | |||||
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()) { | ||||
▲ Show 20 Lines • Show All 1,896 Lines • Show Last 20 Lines |