#include "memusage.h"
#include "random.h"
+#include "version.h"
+#include "policy/fees.h"
+#include "komodo_defs.h"
+#include "importcoin.h"
#include <assert.h>
// version as fresh.
ret->second.flags = CCoinsCacheEntry::FRESH;
}
- cachedCoinsUsage += memusage::DynamicUsage(ret->second.coins);
+ cachedCoinsUsage += ret->second.coins.DynamicMemoryUsage();
return ret;
}
CAnchorsMap::iterator ret = cacheAnchors.insert(std::make_pair(rt, CAnchorsCacheEntry())).first;
ret->second.entered = true;
ret->second.tree = tree;
- cachedCoinsUsage += memusage::DynamicUsage(ret->second.tree);
+ cachedCoinsUsage += ret->second.tree.DynamicMemoryUsage();
return true;
}
if (insertRet.second) {
// An insert took place
- cachedCoinsUsage += memusage::DynamicUsage(ret->second.tree);
+ cachedCoinsUsage += ret->second.tree.DynamicMemoryUsage();
}
hashAnchor = newrt;
ret.first->second.flags = CCoinsCacheEntry::FRESH;
}
} else {
- cachedCoinUsage = memusage::DynamicUsage(ret.first->second.coins);
+ cachedCoinUsage = ret.first->second.coins.DynamicMemoryUsage();
}
// Assume that whenever ModifyCoins is called, the entry will be modified.
ret.first->second.flags |= CCoinsCacheEntry::DIRTY;
assert(it->second.flags & CCoinsCacheEntry::FRESH);
CCoinsCacheEntry& entry = cacheCoins[it->first];
entry.coins.swap(it->second.coins);
- cachedCoinsUsage += memusage::DynamicUsage(entry.coins);
+ cachedCoinsUsage += entry.coins.DynamicMemoryUsage();
entry.flags = CCoinsCacheEntry::DIRTY | CCoinsCacheEntry::FRESH;
}
} else {
// The grandparent does not have an entry, and the child is
// modified and being pruned. This means we can just delete
// it from the parent.
- cachedCoinsUsage -= memusage::DynamicUsage(itUs->second.coins);
+ cachedCoinsUsage -= itUs->second.coins.DynamicMemoryUsage();
cacheCoins.erase(itUs);
} else {
// A normal modification.
- cachedCoinsUsage -= memusage::DynamicUsage(itUs->second.coins);
+ cachedCoinsUsage -= itUs->second.coins.DynamicMemoryUsage();
itUs->second.coins.swap(it->second.coins);
- cachedCoinsUsage += memusage::DynamicUsage(itUs->second.coins);
+ cachedCoinsUsage += itUs->second.coins.DynamicMemoryUsage();
itUs->second.flags |= CCoinsCacheEntry::DIRTY;
}
}
entry.tree = child_it->second.tree;
entry.flags = CAnchorsCacheEntry::DIRTY;
- cachedCoinsUsage += memusage::DynamicUsage(entry.tree);
+ cachedCoinsUsage += entry.tree.DynamicMemoryUsage();
} else {
if (parent_it->second.entered != child_it->second.entered) {
// The parent may have removed the entry.
return coins->vout[input.prevout.n];
}
-CAmount CCoinsViewCache::GetValueIn(const CTransaction& tx) const
+const CScript &CCoinsViewCache::GetSpendFor(const CTxIn& input) const
{
- if (tx.IsCoinBase())
- return 0;
+ const CCoins* coins = AccessCoins(input.prevout.hash);
+ assert(coins);
+ return coins->vout[input.prevout.n].scriptPubKey;
+}
- CAmount nResult = 0;
- for (unsigned int i = 0; i < tx.vin.size(); i++)
- nResult += GetOutputFor(tx.vin[i]).nValue;
+//uint64_t komodo_interest(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime);
+uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 hash,int32_t n,int32_t checkheight,uint64_t checkvalue,int32_t tipheight);
+extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN];
+CAmount CCoinsViewCache::GetValueIn(int32_t nHeight,int64_t *interestp,const CTransaction& tx,uint32_t tiptime) const
+{
+ CAmount value,nResult = 0;
+ if ( interestp != 0 )
+ *interestp = 0;
+ if ( tx.IsCoinImport() )
+ return GetCoinImportValue(tx);
+ if ( tx.IsCoinBase() != 0 )
+ return 0;
+ for (unsigned int i = 0; i < tx.vin.size(); i++)
+ {
+ value = GetOutputFor(tx.vin[i]).nValue;
+ nResult += value;
+#ifdef KOMODO_ENABLE_INTEREST
+ if ( ASSETCHAINS_SYMBOL[0] == 0 && nHeight >= 60000 )
+ {
+ if ( value >= 10*COIN )
+ {
+ int64_t interest; int32_t txheight; uint32_t locktime;
+ interest = komodo_accrued_interest(&txheight,&locktime,tx.vin[i].prevout.hash,tx.vin[i].prevout.n,0,value,(int32_t)nHeight);
+ //printf("nResult %.8f += val %.8f interest %.8f ht.%d lock.%u tip.%u\n",(double)nResult/COIN,(double)value/COIN,(double)interest/COIN,txheight,locktime,tiptime);
+ //fprintf(stderr,"nResult %.8f += val %.8f interest %.8f ht.%d lock.%u tip.%u\n",(double)nResult/COIN,(double)value/COIN,(double)interest/COIN,txheight,locktime,tiptime);
+ nResult += interest;
+ (*interestp) += interest;
+ }
+ }
+#endif
+ }
nResult += tx.GetJoinSplitValueIn();
return nResult;
}
+
bool CCoinsViewCache::HaveJoinSplitRequirements(const CTransaction& tx) const
{
boost::unordered_map<uint256, ZCIncrementalMerkleTree, CCoinsKeyHasher> intermediates;
bool CCoinsViewCache::HaveInputs(const CTransaction& tx) const
{
- if (!tx.IsCoinBase()) {
+ if (!tx.IsMint()) {
for (unsigned int i = 0; i < tx.vin.size(); i++) {
const COutPoint &prevout = tx.vin[i].prevout;
const CCoins* coins = AccessCoins(prevout.hash);
if (!coins || !coins->IsAvailable(prevout.n)) {
+ //fprintf(stderr,"HaveInputs missing input %s/v%d\n",prevout.hash.ToString().c_str(),prevout.n);
return false;
}
}
{
if (tx.IsCoinBase())
return 0.0;
+ // Joinsplits do not reveal any information about the value or age of a note, so we
+ // cannot apply the priority algorithm used for transparent utxos. Instead, we just
+ // use the maximum priority whenever a transaction contains any JoinSplits.
+ // (Note that coinbase transactions cannot contain JoinSplits.)
+ // FIXME: this logic is partially duplicated between here and CreateNewBlock in miner.cpp.
+
+ if (tx.vjoinsplit.size() > 0) {
+ return MAX_PRIORITY;
+ }
+ if (tx.IsCoinImport()) {
+ return MAX_PRIORITY;
+ }
+
double dResult = 0.0;
BOOST_FOREACH(const CTxIn& txin, tx.vin)
{
dResult += coins->vout[txin.prevout.n].nValue * (nHeight-coins->nHeight);
}
}
+
return tx.ComputePriority(dResult);
}
cache.cacheCoins.erase(it);
} else {
// If the coin still exists after the modification, add the new usage
- cache.cachedCoinsUsage += memusage::DynamicUsage(it->second.coins);
+ cache.cachedCoinsUsage += it->second.coins.DynamicMemoryUsage();
}
}