Browse Source

Remove ModifyCoins/ModifyNewCoins

0.15
Pieter Wuille 8 years ago
parent
commit
05293f3cb7
  1. 83
      src/coins.cpp
  2. 47
      src/coins.h

83
src/coins.cpp

@ -60,12 +60,7 @@ size_t CCoinsViewBacked::EstimateSize() const { return base->EstimateSize(); }
SaltedTxidHasher::SaltedTxidHasher() : k0(GetRand(std::numeric_limits<uint64_t>::max())), k1(GetRand(std::numeric_limits<uint64_t>::max())) {} SaltedTxidHasher::SaltedTxidHasher() : k0(GetRand(std::numeric_limits<uint64_t>::max())), k1(GetRand(std::numeric_limits<uint64_t>::max())) {}
CCoinsViewCache::CCoinsViewCache(CCoinsView *baseIn) : CCoinsViewBacked(baseIn), hasModifier(false), cachedCoinsUsage(0) { } CCoinsViewCache::CCoinsViewCache(CCoinsView *baseIn) : CCoinsViewBacked(baseIn), cachedCoinsUsage(0) { }
CCoinsViewCache::~CCoinsViewCache()
{
assert(!hasModifier);
}
size_t CCoinsViewCache::DynamicMemoryUsage() const { size_t CCoinsViewCache::DynamicMemoryUsage() const {
return memusage::DynamicUsage(cacheCoins) + cachedCoinsUsage; return memusage::DynamicUsage(cacheCoins) + cachedCoinsUsage;
@ -98,62 +93,6 @@ bool CCoinsViewCache::GetCoins(const uint256 &txid, CCoins &coins) const {
return false; return false;
} }
CCoinsModifier CCoinsViewCache::ModifyCoins(const uint256 &txid) {
assert(!hasModifier);
std::pair<CCoinsMap::iterator, bool> ret = cacheCoins.insert(std::make_pair(txid, CCoinsCacheEntry()));
size_t cachedCoinUsage = 0;
if (ret.second) {
if (!base->GetCoins(txid, ret.first->second.coins)) {
// The parent view does not have this entry; mark it as fresh.
ret.first->second.coins.Clear();
ret.first->second.flags = CCoinsCacheEntry::FRESH;
} else if (ret.first->second.coins.IsPruned()) {
// The parent view only has a pruned entry for this; mark it as fresh.
ret.first->second.flags = CCoinsCacheEntry::FRESH;
}
} else {
cachedCoinUsage = ret.first->second.coins.DynamicMemoryUsage();
}
// Assume that whenever ModifyCoins is called, the entry will be modified.
ret.first->second.flags |= CCoinsCacheEntry::DIRTY;
return CCoinsModifier(*this, ret.first, cachedCoinUsage);
}
/* ModifyNewCoins allows for faster coin modification when creating the new
* outputs from a transaction. It assumes that BIP 30 (no duplicate txids)
* applies and has already been tested for (or the test is not required due to
* BIP 34, height in coinbase). If we can assume BIP 30 then we know that any
* non-coinbase transaction we are adding to the UTXO must not already exist in
* the utxo unless it is fully spent. Thus we can check only if it exists DIRTY
* at the current level of the cache, in which case it is not safe to mark it
* FRESH (b/c then its spentness still needs to flushed). If it's not dirty and
* doesn't exist or is pruned in the current cache, we know it either doesn't
* exist or is pruned in parent caches, which is the definition of FRESH. The
* exception to this is the two historical violations of BIP 30 in the chain,
* both of which were coinbases. We do not mark these fresh so we we can ensure
* that they will still be properly overwritten when spent.
*/
CCoinsModifier CCoinsViewCache::ModifyNewCoins(const uint256 &txid, bool coinbase) {
assert(!hasModifier);
std::pair<CCoinsMap::iterator, bool> ret = cacheCoins.insert(std::make_pair(txid, CCoinsCacheEntry()));
if (!coinbase) {
// New coins must not already exist.
if (!ret.first->second.coins.IsPruned())
throw std::logic_error("ModifyNewCoins should not find pre-existing coins on a non-coinbase unless they are pruned!");
if (!(ret.first->second.flags & CCoinsCacheEntry::DIRTY)) {
// If the coin is known to be pruned (have no unspent outputs) in
// the current view and the cache entry is not dirty, we know the
// coin also must be pruned in the parent view as well, so it is safe
// to mark this fresh.
ret.first->second.flags |= CCoinsCacheEntry::FRESH;
}
}
ret.first->second.coins.Clear();
ret.first->second.flags |= CCoinsCacheEntry::DIRTY;
return CCoinsModifier(*this, ret.first, 0);
}
void CCoinsViewCache::AddCoin(const COutPoint &outpoint, Coin&& coin, bool possible_overwrite) { void CCoinsViewCache::AddCoin(const COutPoint &outpoint, Coin&& coin, bool possible_overwrite) {
assert(!coin.IsPruned()); assert(!coin.IsPruned());
if (coin.out.scriptPubKey.IsUnspendable()) return; if (coin.out.scriptPubKey.IsUnspendable()) return;
@ -257,7 +196,6 @@ void CCoinsViewCache::SetBestBlock(const uint256 &hashBlockIn) {
} }
bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlockIn) { bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlockIn) {
assert(!hasModifier);
for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end();) { for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end();) {
if (it->second.flags & CCoinsCacheEntry::DIRTY) { // Ignore non-dirty entries (optimization). if (it->second.flags & CCoinsCacheEntry::DIRTY) { // Ignore non-dirty entries (optimization).
CCoinsMap::iterator itUs = cacheCoins.find(it->first); CCoinsMap::iterator itUs = cacheCoins.find(it->first);
@ -366,25 +304,6 @@ bool CCoinsViewCache::HaveInputs(const CTransaction& tx) const
return true; return true;
} }
CCoinsModifier::CCoinsModifier(CCoinsViewCache& cache_, CCoinsMap::iterator it_, size_t usage) : cache(cache_), it(it_), cachedCoinUsage(usage) {
assert(!cache.hasModifier);
cache.hasModifier = true;
}
CCoinsModifier::~CCoinsModifier()
{
assert(cache.hasModifier);
cache.hasModifier = false;
it->second.coins.Cleanup();
cache.cachedCoinsUsage -= cachedCoinUsage; // Subtract the old usage
if ((it->second.flags & CCoinsCacheEntry::FRESH) && it->second.coins.IsPruned()) {
cache.cacheCoins.erase(it);
} else {
// If the coin still exists after the modification, add the new usage
cache.cachedCoinsUsage += it->second.coins.DynamicMemoryUsage();
}
}
CCoinsViewCursor::~CCoinsViewCursor() CCoinsViewCursor::~CCoinsViewCursor()
{ {
} }

47
src/coins.h

@ -405,36 +405,10 @@ public:
}; };
class CCoinsViewCache;
/**
* A reference to a mutable cache entry. Encapsulating it allows us to run
* cleanup code after the modification is finished, and keeping track of
* concurrent modifications.
*/
class CCoinsModifier
{
private:
CCoinsViewCache& cache;
CCoinsMap::iterator it;
size_t cachedCoinUsage; // Cached memory usage of the CCoins object before modification
CCoinsModifier(CCoinsViewCache& cache_, CCoinsMap::iterator it_, size_t usage);
public:
CCoins* operator->() { return &it->second.coins; }
CCoins& operator*() { return it->second.coins; }
~CCoinsModifier();
friend class CCoinsViewCache;
};
/** CCoinsView that adds a memory cache for transactions to another CCoinsView */ /** CCoinsView that adds a memory cache for transactions to another CCoinsView */
class CCoinsViewCache : public CCoinsViewBacked class CCoinsViewCache : public CCoinsViewBacked
{ {
protected: protected:
/* Whether this cache has an active modifier. */
bool hasModifier;
/** /**
* Make mutable so that we can "fill the cache" even from Get-methods * Make mutable so that we can "fill the cache" even from Get-methods
* declared as "const". * declared as "const".
@ -447,7 +421,6 @@ protected:
public: public:
CCoinsViewCache(CCoinsView *baseIn); CCoinsViewCache(CCoinsView *baseIn);
~CCoinsViewCache();
// Standard CCoinsView methods // Standard CCoinsView methods
bool GetCoins(const uint256 &txid, CCoins &coins) const; bool GetCoins(const uint256 &txid, CCoins &coins) const;
@ -479,24 +452,6 @@ public:
*/ */
const Coin AccessCoin(const COutPoint &output) const; const Coin AccessCoin(const COutPoint &output) const;
/**
* Return a modifiable reference to a CCoins. If no entry with the given
* txid exists, a new one is created. Simultaneous modifications are not
* allowed.
*/
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, bool coinbase);
/** /**
* Add a coin. Set potential_overwrite to true if a non-pruned version may * Add a coin. Set potential_overwrite to true if a non-pruned version may
* already exist. * already exist.
@ -544,8 +499,6 @@ public:
const CTxOut &GetOutputFor(const CTxIn& input) const; const CTxOut &GetOutputFor(const CTxIn& input) const;
friend class CCoinsModifier;
private: private:
CCoinsMap::iterator FetchCoins(const uint256 &txid) const; CCoinsMap::iterator FetchCoins(const uint256 &txid) const;

Loading…
Cancel
Save