Merge #10537: Few Minor per-utxo assert-semantics re-adds and tweak

9417d7a33 Be much more agressive in AccessCoin docs. (Matt Corallo)
f58349ca8 Restore some assert semantics in sigop cost calculations (Matt Corallo)
3533fb4d3 Return a bool in SpendCoin to restore pre-per-utxo assert semantics (Matt Corallo)
ec1271f2b Remove useless mapNextTx lookup in CTxMemPool::TrimToSize. (Matt Corallo)

Tree-SHA512: 158a4bce063eac93e1d50709500a10a7cb1fb3271f10ed445d701852fce713e2bf0da3456088e530ab005f194ef4a2adf0c7cb23226b160cecb37a79561f29ca
This commit is contained in:
Pieter Wuille 2017-06-20 18:18:09 -07:00 committed by Alexander Block
parent 4f807422fa
commit 151c552c71
4 changed files with 19 additions and 12 deletions

View File

@ -91,9 +91,9 @@ void AddCoins(CCoinsViewCache& cache, const CTransaction &tx, int nHeight) {
} }
} }
void CCoinsViewCache::SpendCoin(const COutPoint &outpoint, Coin* moveout) { bool CCoinsViewCache::SpendCoin(const COutPoint &outpoint, Coin* moveout) {
CCoinsMap::iterator it = FetchCoin(outpoint); CCoinsMap::iterator it = FetchCoin(outpoint);
if (it == cacheCoins.end()) return; if (it == cacheCoins.end()) return false;
cachedCoinsUsage -= it->second.coin.DynamicMemoryUsage(); cachedCoinsUsage -= it->second.coin.DynamicMemoryUsage();
if (moveout) { if (moveout) {
*moveout = std::move(it->second.coin); *moveout = std::move(it->second.coin);
@ -104,6 +104,7 @@ void CCoinsViewCache::SpendCoin(const COutPoint &outpoint, Coin* moveout) {
it->second.flags |= CCoinsCacheEntry::DIRTY; it->second.flags |= CCoinsCacheEntry::DIRTY;
it->second.coin.Clear(); it->second.coin.Clear();
} }
return true;
} }
static const Coin coinEmpty; static const Coin coinEmpty;

View File

@ -225,8 +225,13 @@ public:
/** /**
* Return a reference to Coin in the cache, or a pruned one if not found. This is * Return a reference to Coin in the cache, or a pruned one if not found. This is
* more efficient than GetCoin. Modifications to other cache entries are * more efficient than GetCoin.
* allowed while accessing the returned pointer. *
* Generally, do not hold the reference returned for more than a short scope.
* While the current implementation allows for modifications to the contents
* of the cache while holding the reference, this behavior should not be relied
* on! To be safe, best to not hold the returned reference through any other
* calls to this cache.
*/ */
const Coin& AccessCoin(const COutPoint &output) const; const Coin& AccessCoin(const COutPoint &output) const;
@ -241,7 +246,7 @@ public:
* If no unspent output exists for the passed outpoint, this call * If no unspent output exists for the passed outpoint, this call
* has no effect. * has no effect.
*/ */
void SpendCoin(const COutPoint &outpoint, Coin* moveto = nullptr); bool SpendCoin(const COutPoint &outpoint, Coin* moveto = nullptr);
/** /**
* Push the modifications applied to this cache to its base. * Push the modifications applied to this cache to its base.

View File

@ -1143,13 +1143,11 @@ void CTxMemPool::TrimToSize(size_t sizelimit, std::vector<COutPoint>* pvNoSpends
BOOST_FOREACH(const CTransaction& tx, txn) { BOOST_FOREACH(const CTransaction& tx, txn) {
BOOST_FOREACH(const CTxIn& txin, tx.vin) { BOOST_FOREACH(const CTxIn& txin, tx.vin) {
if (exists(txin.prevout.hash)) continue; if (exists(txin.prevout.hash)) continue;
if (!mapNextTx.count(txin.prevout)) {
pvNoSpendsRemaining->push_back(txin.prevout); pvNoSpendsRemaining->push_back(txin.prevout);
} }
} }
} }
} }
}
if (maxFeeRateRemoved > CFeeRate(0)) if (maxFeeRateRemoved > CFeeRate(0))
LogPrint("mempool", "Removed %u txn, rolling minimum fee bumped to %s\n", nTxnRemoved, maxFeeRateRemoved.ToString()); LogPrint("mempool", "Removed %u txn, rolling minimum fee bumped to %s\n", nTxnRemoved, maxFeeRateRemoved.ToString());

View File

@ -437,7 +437,9 @@ unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& in
unsigned int nSigOps = 0; unsigned int nSigOps = 0;
for (unsigned int i = 0; i < tx.vin.size(); i++) for (unsigned int i = 0; i < tx.vin.size(); i++)
{ {
const CTxOut &prevout = inputs.AccessCoin(tx.vin[i].prevout).out; const Coin& coin = inputs.AccessCoin(tx.vin[i].prevout);
assert(!coin.IsSpent());
const CTxOut &prevout = coin.out;
if (prevout.scriptPubKey.IsPayToScriptHash()) if (prevout.scriptPubKey.IsPayToScriptHash())
nSigOps += prevout.scriptPubKey.GetSigOpCount(tx.vin[i].scriptSig); nSigOps += prevout.scriptPubKey.GetSigOpCount(tx.vin[i].scriptSig);
} }
@ -1427,7 +1429,8 @@ void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCach
txundo.vprevout.reserve(tx.vin.size()); txundo.vprevout.reserve(tx.vin.size());
BOOST_FOREACH(const CTxIn &txin, tx.vin) { BOOST_FOREACH(const CTxIn &txin, tx.vin) {
txundo.vprevout.emplace_back(); txundo.vprevout.emplace_back();
inputs.SpendCoin(txin.prevout, &txundo.vprevout.back()); bool is_spent = inputs.SpendCoin(txin.prevout, &txundo.vprevout.back());
assert(is_spent);
} }
} }
// add outputs // add outputs
@ -1750,8 +1753,8 @@ static DisconnectResult DisconnectBlock(const CBlock& block, CValidationState& s
if (!tx.vout[o].scriptPubKey.IsUnspendable()) { if (!tx.vout[o].scriptPubKey.IsUnspendable()) {
COutPoint out(hash, o); COutPoint out(hash, o);
Coin coin; Coin coin;
view.SpendCoin(out, &coin); bool is_spent = view.SpendCoin(out, &coin);
if (tx.vout[o] != coin.out) { if (!is_spent || tx.vout[o] != coin.out) {
fClean = false; // transaction output mismatch fClean = false; // transaction output mismatch
} }
} }