Skip to content

Commit 1e88b7f

Browse files
morcosrandom-zebra
authored andcommitted
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 91c373c commit 1e88b7f

File tree

3 files changed

+31
-3
lines changed

3 files changed

+31
-3
lines changed

src/coins.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,16 @@ CCoinsModifier CCoinsViewCache::ModifyCoins(const uint256& txid)
121121
return CCoinsModifier(*this, ret.first, cachedCoinUsage);
122122
}
123123

124+
CCoinsModifier CCoinsViewCache::ModifyNewCoins(const uint256 &txid)
125+
{
126+
assert(!hasModifier);
127+
std::pair<CCoinsMap::iterator, bool> ret = cacheCoins.insert(std::make_pair(txid, CCoinsCacheEntry()));
128+
ret.first->second.coins.Clear();
129+
ret.first->second.flags = CCoinsCacheEntry::FRESH;
130+
ret.first->second.flags |= CCoinsCacheEntry::DIRTY;
131+
return CCoinsModifier(*this, ret.first, 0);
132+
}
133+
124134
const CCoins* CCoinsViewCache::AccessCoins(const uint256& txid) const
125135
{
126136
CCoinsMap::const_iterator it = FetchCoins(txid);

src/coins.h

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

427+
/**
428+
* Return a modifiable reference to a CCoins. Assumes that no entry with the given
429+
* txid exists and creates a new one. This saves a database access in the case where
430+
* the coins were to be wiped out by FromTx anyway. This should not be called with
431+
* the 2 historical coinbase duplicate pairs because the new coins are marked fresh, and
432+
* in the event the duplicate coinbase was spent before a flush, the now pruned coins
433+
* would not properly overwrite the first coinbase of the pair. Simultaneous modifications
434+
* are not allowed.
435+
*/
436+
CCoinsModifier ModifyNewCoins(const uint256 &txid);
437+
427438
/**
428439
* Push the modifications applied to this cache to its base.
429440
* 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
@@ -1720,10 +1720,17 @@ void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, CTxUndo& txund
17201720
undo.nVersion = coins->nVersion;
17211721
}
17221722
}
1723+
// add outputs
1724+
inputs.ModifyNewCoins(tx.GetHash())->FromTx(tx, nHeight);
1725+
}
1726+
else {
1727+
// add outputs for coinbase tx
1728+
// In this case call the full ModifyCoins which will do a database
1729+
// lookup to be sure the coins do not already exist otherwise we do not
1730+
// know whether to mark them fresh or not. We want the duplicate coinbases
1731+
// before BIP30 to still be properly overwritten.
1732+
inputs.ModifyCoins(tx.GetHash())->FromTx(tx, nHeight);
17231733
}
1724-
1725-
// add outputs
1726-
inputs.ModifyCoins(tx.GetHash())->FromTx(tx, nHeight);
17271734
}
17281735

17291736
void UpdateCoins(const CTransaction& tx, CCoinsViewCache &inputs, int nHeight)

0 commit comments

Comments
 (0)