Exemple #1
0
CCoinsMap::const_iterator CCoinsViewCache::FetchCoins(const uint256 &txid) const {
    CCoinsMap::iterator it = cacheCoins.find(txid);
    if (it != cacheCoins.end())
        return it;
    CCoins tmp;
    if (!base->GetCoins(txid, tmp))
        return cacheCoins.end();
    CCoinsMap::iterator ret = cacheCoins.insert(std::make_pair(txid, CCoinsCacheEntry())).first;
    tmp.swap(ret->second.coins);
    if (ret->second.coins.IsPruned()) {
        // The parent only has an empty entry for this txid; we can consider our
        // version as fresh.
        ret->second.flags = CCoinsCacheEntry::FRESH;
    }
    return ret;
}
Exemple #2
0
CCoinsMap::const_iterator CCoinsViewCache::FetchCoins(const uint256& txid) const
{
    CCoinsMap::iterator it = cacheCoins.find(txid);
    if (it != cacheCoins.end())
        return it;
    CCoins tmp;
    if (!base->GetCoins(txid, tmp))
        return cacheCoins.end();
    CCoinsMap::iterator ret = cacheCoins.insert(std::make_pair(txid, CCoinsCacheEntry())).first;
    tmp.swap(ret->second.coins);
    if (ret->second.coins.IsPruned()) {

        ret->second.flags = CCoinsCacheEntry::FRESH;
    }
    cachedCoinsUsage += ret->second.coins.DynamicMemoryUsage();
    return ret;
}
Exemple #3
0
CCoinsModifier CCoinsViewCache::ModifyCoins(const uint256 &txid) {
    assert(!hasModifier);
    std::pair<CCoinsMap::iterator, bool> ret = cacheCoins.insert(std::make_pair(txid, CCoinsCacheEntry()));
    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;
        }
    }
    // Assume that whenever ModifyCoins is called, the entry will be modified.
    ret.first->second.flags |= CCoinsCacheEntry::DIRTY;
    return CCoinsModifier(*this, ret.first);
}
Exemple #4
0
// ModifyNewCoins has to know whether the new outputs its creating are for a
// coinbase or not.  If they are for a coinbase, it can not mark them as fresh.
// This is to ensure that the historical duplicate coinbases before BIP30 was
// in effect 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()));
    ret.first->second.coins.Clear();
    if (!coinbase) {
        ret.first->second.flags = CCoinsCacheEntry::FRESH;
    }
    ret.first->second.flags |= CCoinsCacheEntry::DIRTY;
    return CCoinsModifier(*this, ret.first, 0);
}
Exemple #5
0
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)) {

            ret.first->second.coins.Clear();
            ret.first->second.flags = CCoinsCacheEntry::FRESH;
        } else if (ret.first->second.coins.IsPruned()) {

            ret.first->second.flags = CCoinsCacheEntry::FRESH;
        }
    } else {
        cachedCoinUsage = ret.first->second.coins.DynamicMemoryUsage();
    }

    ret.first->second.flags |= CCoinsCacheEntry::DIRTY;
    return CCoinsModifier(*this, ret.first, cachedCoinUsage);
}
Exemple #6
0
CCoinsViewCache::CCoinsViewCache(CCoinsView *baseIn) : CCoinsViewBacked(baseIn), hasModifier(false), cachedCoinsUsage(0)
{
    // emercoin: insert special randpay utxo that can be spent unlimited number of times
    // you can only spent 0 emc from it
    std::pair<CCoinsMap::iterator, bool> ret = cacheCoins.insert(std::make_pair(randpaytx, CCoinsCacheEntry()));
    if (!ret.second)
        throw std::logic_error("Failed to insert randpay utxo!");

    CCoins& coins = ret.first->second.coins;
    coins.fCoinBase = false;
    coins.fCoinStake = false;
    coins.nHeight = 0;
    coins.nVersion = 1;
    coins.nTime = 0;

    CTxOut txout = CTxOut();
    txout.nValue = 0;
    coins.vout.push_back(txout);
    ret.first->second.flags = CCoinsCacheEntry::DIRTY;   // set DIRTY/FRESH flags
}
Exemple #7
0
/* 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);
}