mirror of
https://github.com/dashpay/dash.git
synced 2024-12-28 05:23:01 +01:00
Remove ModifyCoins/ModifyNewCoins
This commit is contained in:
parent
961e483979
commit
05293f3cb7
@ -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
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…
Reference in New Issue
Block a user