Skip to content

Commit 14470f9

Browse files
committed
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.
1 parent 8fe30fb commit 14470f9

File tree

3 files changed

+30
-3
lines changed

3 files changed

+30
-3
lines changed

src/coins.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,15 @@ CCoinsModifier CCoinsViewCache::ModifyCoins(const uint256 &txid) {
117117
return CCoinsModifier(*this, ret.first, cachedCoinUsage);
118118
}
119119

120+
CCoinsModifier CCoinsViewCache::ModifyNewCoins(const uint256 &txid) {
121+
assert(!hasModifier);
122+
std::pair<CCoinsMap::iterator, bool> ret = cacheCoins.insert(std::make_pair(txid, CCoinsCacheEntry()));
123+
ret.first->second.coins.Clear();
124+
ret.first->second.flags = CCoinsCacheEntry::FRESH;
125+
ret.first->second.flags |= CCoinsCacheEntry::DIRTY;
126+
return CCoinsModifier(*this, ret.first, 0);
127+
}
128+
120129
const CCoins* CCoinsViewCache::AccessCoins(const uint256 &txid) const {
121130
CCoinsMap::const_iterator it = FetchCoins(txid);
122131
if (it == cacheCoins.end()) {

src/coins.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,17 @@ class CCoinsViewCache : public CCoinsViewBacked
419419
*/
420420
CCoinsModifier ModifyCoins(const uint256 &txid);
421421

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

src/main.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1285,10 +1285,17 @@ void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCach
12851285
undo.nVersion = coins->nVersion;
12861286
}
12871287
}
1288+
// add outputs
1289+
inputs.ModifyNewCoins(tx.GetHash())->FromTx(tx, nHeight);
1290+
}
1291+
else {
1292+
// add outputs for coinbase tx
1293+
// In this case call the full ModifyCoins which will do a database
1294+
// lookup to be sure the coins do not already exist otherwise we do not
1295+
// know whether to mark them fresh or not. We want the duplicate coinbases
1296+
// before BIP30 to still be properly overwritten.
1297+
inputs.ModifyCoins(tx.GetHash())->FromTx(tx, nHeight);
12881298
}
1289-
1290-
// add outputs
1291-
inputs.ModifyCoins(tx.GetHash())->FromTx(tx, nHeight);
12921299
}
12931300

12941301
void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCache &inputs, int nHeight)

0 commit comments

Comments
 (0)