Browse Source

ModifyNewCoins saves database lookups

When processing a new transaction, in addition to spending the Coins of its txin's it creates a new Coins for its outputs.  The existing ModifyCoins function will first make sure this Coins does not already exist.  It can not exist due to BIP 30, but because of that the lookup can't be cached and always has to go to the database.  Since we are creating the coins to match the new tx anyway, there is no point in checking if they exist first anyway.  However this should not be used for coinbase tx's in order to preserve the historical behavior of overwriting the two existing duplicate tx pairs.
0.13
Alex Morcos 9 years ago
parent
commit
14470f9aa6
  1. 9
      src/coins.cpp
  2. 11
      src/coins.h
  3. 11
      src/main.cpp

9
src/coins.cpp

@ -117,6 +117,15 @@ CCoinsModifier CCoinsViewCache::ModifyCoins(const uint256 &txid) {
return CCoinsModifier(*this, ret.first, cachedCoinUsage); return CCoinsModifier(*this, ret.first, cachedCoinUsage);
} }
CCoinsModifier CCoinsViewCache::ModifyNewCoins(const uint256 &txid) {
assert(!hasModifier);
std::pair<CCoinsMap::iterator, bool> ret = cacheCoins.insert(std::make_pair(txid, CCoinsCacheEntry()));
ret.first->second.coins.Clear();
ret.first->second.flags = CCoinsCacheEntry::FRESH;
ret.first->second.flags |= CCoinsCacheEntry::DIRTY;
return CCoinsModifier(*this, ret.first, 0);
}
const CCoins* CCoinsViewCache::AccessCoins(const uint256 &txid) const { const CCoins* CCoinsViewCache::AccessCoins(const uint256 &txid) const {
CCoinsMap::const_iterator it = FetchCoins(txid); CCoinsMap::const_iterator it = FetchCoins(txid);
if (it == cacheCoins.end()) { if (it == cacheCoins.end()) {

11
src/coins.h

@ -419,6 +419,17 @@ public:
*/ */
CCoinsModifier ModifyCoins(const uint256 &txid); CCoinsModifier ModifyCoins(const uint256 &txid);
/**
* Return a modifiable reference to a CCoins. Assumes that no entry with the given
* txid exists and creates a new one. This saves a database access in the case where
* the coins were to be wiped out by FromTx anyway. This should not be called with
* the 2 historical coinbase duplicate pairs because the new coins are marked fresh, and
* in the event the duplicate coinbase was spent before a flush, the now pruned coins
* would not properly overwrite the first coinbase of the pair. Simultaneous modifications
* are not allowed.
*/
CCoinsModifier ModifyNewCoins(const uint256 &txid);
/** /**
* Push the modifications applied to this cache to its base. * Push the modifications applied to this cache to its base.
* Failure to call this method before destruction will cause the changes to be forgotten. * Failure to call this method before destruction will cause the changes to be forgotten.

11
src/main.cpp

@ -1285,11 +1285,18 @@ void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCach
undo.nVersion = coins->nVersion; undo.nVersion = coins->nVersion;
} }
} }
}
// add outputs // add outputs
inputs.ModifyNewCoins(tx.GetHash())->FromTx(tx, nHeight);
}
else {
// add outputs for coinbase tx
// In this case call the full ModifyCoins which will do a database
// lookup to be sure the coins do not already exist otherwise we do not
// know whether to mark them fresh or not. We want the duplicate coinbases
// before BIP30 to still be properly overwritten.
inputs.ModifyCoins(tx.GetHash())->FromTx(tx, nHeight); inputs.ModifyCoins(tx.GetHash())->FromTx(tx, nHeight);
} }
}
void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCache &inputs, int nHeight) void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCache &inputs, int nHeight)
{ {

Loading…
Cancel
Save