diff --git a/src/validation.h b/src/validation.h --- a/src/validation.h +++ b/src/validation.h @@ -513,7 +513,15 @@ const PrecomputedTransactionData &txdata, std::vector *pvChecks = nullptr); -/** Apply the effects of this transaction on the UTXO set represented by view */ +/** + * Mark all the coins corresponding to a given transaction inputs as spent. + */ +void SpendCoins(CCoinsViewCache &view, const CTransaction &tx, CTxUndo &txundo, + int nHeight); + +/** + * Apply the effects of this transaction on the UTXO set represented by view. + */ void UpdateCoins(CCoinsViewCache &view, const CTransaction &tx, int nHeight); void UpdateCoins(CCoinsViewCache &view, const CTransaction &tx, CTxUndo &txundo, int nHeight); diff --git a/src/validation.cpp b/src/validation.cpp --- a/src/validation.cpp +++ b/src/validation.cpp @@ -1432,15 +1432,32 @@ } } +void SpendCoins(CCoinsViewCache &view, const CTransaction &tx, CTxUndo &txundo, + int nHeight) { + // Mark inputs spent. + if (tx.IsCoinBase()) { + return; + } + + txundo.vprevout.reserve(tx.vin.size()); + for (const CTxIn &txin : tx.vin) { + txundo.vprevout.emplace_back(); + bool is_spent = view.SpendCoin(txin.prevout, &txundo.vprevout.back()); + assert(is_spent); + } +} + void UpdateCoins(CCoinsViewCache &view, const CTransaction &tx, CTxUndo &txundo, int nHeight) { + SpendCoins(view, tx, txundo, nHeight); + AddCoins(view, tx, nHeight); +} + +void UpdateCoins(CCoinsViewCache &view, const CTransaction &tx, int nHeight) { // Mark inputs spent. if (!tx.IsCoinBase()) { - txundo.vprevout.reserve(tx.vin.size()); for (const CTxIn &txin : tx.vin) { - txundo.vprevout.emplace_back(); - bool is_spent = - view.SpendCoin(txin.prevout, &txundo.vprevout.back()); + bool is_spent = view.SpendCoin(txin.prevout); assert(is_spent); } } @@ -1449,11 +1466,6 @@ AddCoins(view, tx, nHeight); } -void UpdateCoins(CCoinsViewCache &view, const CTransaction &tx, int nHeight) { - CTxUndo txundo; - UpdateCoins(view, tx, txundo, nHeight); -} - bool CScriptCheck::operator()() { const CScript &scriptSig = ptxTo->vin[nIn].scriptSig; return VerifyScript(scriptSig, scriptPubKey, nFlags, @@ -2216,8 +2228,9 @@ if (i > 0) { blockundo.vtxundo.push_back(CTxUndo()); } - UpdateCoins(view, tx, i == 0 ? undoDummy : blockundo.vtxundo.back(), - pindex->nHeight); + SpendCoins(view, tx, i == 0 ? undoDummy : blockundo.vtxundo.back(), + pindex->nHeight); + AddCoins(view, tx, pindex->nHeight); vPos.push_back(std::make_pair(tx.GetId(), pos)); pos.nTxOffset += ::GetSerializeSize(tx, SER_DISK, CLIENT_VERSION); @@ -4607,16 +4620,20 @@ } for (const CTransactionRef &tx : block.vtx) { - if (!tx->IsCoinBase()) { - for (const CTxIn &txin : tx->vin) { - view.SpendCoin(txin.prevout); - } - } - // Pass check = true as every addition may be an overwrite. AddCoins(view, *tx, pindex->nHeight, true); } + for (const CTransactionRef &tx : block.vtx) { + if (tx->IsCoinBase()) { + continue; + } + + for (const CTxIn &txin : tx->vin) { + view.SpendCoin(txin.prevout); + } + } + return true; }