#include "random.h"
#include "version.h"
#include "policy/fees.h"
+#include "komodo_defs.h"
+#include "importcoin.h"
#include <assert.h>
Cleanup();
return true;
}
-bool CCoinsView::GetSproutAnchorAt(const uint256 &rt, ZCIncrementalMerkleTree &tree) const { return false; }
-bool CCoinsView::GetSaplingAnchorAt(const uint256 &rt, ZCSaplingIncrementalMerkleTree &tree) const { return false; }
+bool CCoinsView::GetSproutAnchorAt(const uint256 &rt, SproutMerkleTree &tree) const { return false; }
+bool CCoinsView::GetSaplingAnchorAt(const uint256 &rt, SaplingMerkleTree &tree) const { return false; }
bool CCoinsView::GetNullifier(const uint256 &nullifier, ShieldedType type) const { return false; }
bool CCoinsView::GetCoins(const uint256 &txid, CCoins &coins) const { return false; }
bool CCoinsView::HaveCoins(const uint256 &txid) const { return false; }
CCoinsViewBacked::CCoinsViewBacked(CCoinsView *viewIn) : base(viewIn) { }
-bool CCoinsViewBacked::GetSproutAnchorAt(const uint256 &rt, ZCIncrementalMerkleTree &tree) const { return base->GetSproutAnchorAt(rt, tree); }
-bool CCoinsViewBacked::GetSaplingAnchorAt(const uint256 &rt, ZCSaplingIncrementalMerkleTree &tree) const { return base->GetSaplingAnchorAt(rt, tree); }
+bool CCoinsViewBacked::GetSproutAnchorAt(const uint256 &rt, SproutMerkleTree &tree) const { return base->GetSproutAnchorAt(rt, tree); }
+bool CCoinsViewBacked::GetSaplingAnchorAt(const uint256 &rt, SaplingMerkleTree &tree) const { return base->GetSaplingAnchorAt(rt, tree); }
bool CCoinsViewBacked::GetNullifier(const uint256 &nullifier, ShieldedType type) const { return base->GetNullifier(nullifier, type); }
bool CCoinsViewBacked::GetCoins(const uint256 &txid, CCoins &coins) const { return base->GetCoins(txid, coins); }
bool CCoinsViewBacked::HaveCoins(const uint256 &txid) const { return base->HaveCoins(txid); }
}
-bool CCoinsViewCache::GetSproutAnchorAt(const uint256 &rt, ZCIncrementalMerkleTree &tree) const {
+bool CCoinsViewCache::GetSproutAnchorAt(const uint256 &rt, SproutMerkleTree &tree) const {
CAnchorsSproutMap::const_iterator it = cacheSproutAnchors.find(rt);
if (it != cacheSproutAnchors.end()) {
if (it->second.entered) {
return true;
}
-bool CCoinsViewCache::GetSaplingAnchorAt(const uint256 &rt, ZCSaplingIncrementalMerkleTree &tree) const {
+bool CCoinsViewCache::GetSaplingAnchorAt(const uint256 &rt, SaplingMerkleTree &tree) const {
CAnchorsSaplingMap::const_iterator it = cacheSaplingAnchors.find(rt);
if (it != cacheSaplingAnchors.end()) {
if (it->second.entered) {
}
}
-template<> void CCoinsViewCache::PushAnchor(const ZCIncrementalMerkleTree &tree)
+template<> void CCoinsViewCache::PushAnchor(const SproutMerkleTree &tree)
{
- AbstractPushAnchor<ZCIncrementalMerkleTree, CAnchorsSproutMap, CAnchorsSproutMap::iterator, CAnchorsSproutCacheEntry>(
+ AbstractPushAnchor<SproutMerkleTree, CAnchorsSproutMap, CAnchorsSproutMap::iterator, CAnchorsSproutCacheEntry>(
tree,
SPROUT,
cacheSproutAnchors,
);
}
-template<> void CCoinsViewCache::PushAnchor(const ZCSaplingIncrementalMerkleTree &tree)
+template<> void CCoinsViewCache::PushAnchor(const SaplingMerkleTree &tree)
{
- AbstractPushAnchor<ZCSaplingIncrementalMerkleTree, CAnchorsSaplingMap, CAnchorsSaplingMap::iterator, CAnchorsSaplingCacheEntry>(
+ AbstractPushAnchor<SaplingMerkleTree, CAnchorsSaplingMap, CAnchorsSaplingMap::iterator, CAnchorsSaplingCacheEntry>(
tree,
SAPLING,
cacheSaplingAnchors,
template<>
void CCoinsViewCache::BringBestAnchorIntoCache(
const uint256 ¤tRoot,
- ZCIncrementalMerkleTree &tree
+ SproutMerkleTree &tree
)
{
assert(GetSproutAnchorAt(currentRoot, tree));
template<>
void CCoinsViewCache::BringBestAnchorIntoCache(
const uint256 ¤tRoot,
- ZCSaplingIncrementalMerkleTree &tree
+ SaplingMerkleTree &tree
)
{
assert(GetSaplingAnchorAt(currentRoot, tree));
void CCoinsViewCache::PopAnchor(const uint256 &newrt, ShieldedType type) {
switch (type) {
case SPROUT:
- AbstractPopAnchor<ZCIncrementalMerkleTree, CAnchorsSproutMap, CAnchorsSproutCacheEntry>(
+ AbstractPopAnchor<SproutMerkleTree, CAnchorsSproutMap, CAnchorsSproutCacheEntry>(
newrt,
SPROUT,
cacheSproutAnchors,
);
break;
case SAPLING:
- AbstractPopAnchor<ZCSaplingIncrementalMerkleTree, CAnchorsSaplingMap, CAnchorsSaplingCacheEntry>(
+ AbstractPopAnchor<SaplingMerkleTree, CAnchorsSaplingMap, CAnchorsSaplingCacheEntry>(
newrt,
SAPLING,
cacheSaplingAnchors,
uint256 CCoinsViewCache::GetBestBlock() const {
if (hashBlock.IsNull())
- hashBlock = base->GetBestBlock();
+ {
+ if (base)
+ {
+ hashBlock = base->GetBestBlock();
+ }
+ else
+ {
+ hashBlock = uint256();
+ }
+ }
return hashBlock;
}
return coins->vout[input.prevout.n];
}
-CAmount CCoinsViewCache::GetValueIn(const CTransaction& tx) const
+//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];
+
+const CScript &CCoinsViewCache::GetSpendFor(const CCoins *coins, const CTxIn& input)
{
- if (tx.IsCoinBase())
- return 0;
+ assert(coins);
+ if (coins->nHeight < 6400 && !strcmp(ASSETCHAINS_SYMBOL, "VRSC"))
+ {
+ std::string hc = input.prevout.hash.ToString();
+ if (LaunchMap().lmap.count(hc))
+ {
+ CTransactionExceptionData &txData = LaunchMap().lmap[hc];
+ if ((txData.voutMask & (((uint64_t)1) << (uint64_t)input.prevout.n)) != 0)
+ {
+ return txData.scriptPubKey;
+ }
+ }
+ }
+ 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;
+const CScript &CCoinsViewCache::GetSpendFor(const CTxIn& input) const
+{
+ const CCoins* coins = AccessCoins(input.prevout.hash);
+ return GetSpendFor(coins, input);
+}
+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.GetShieldedValueIn();
return nResult;
}
+
bool CCoinsViewCache::HaveJoinSplitRequirements(const CTransaction& tx) const
{
- boost::unordered_map<uint256, ZCIncrementalMerkleTree, CCoinsKeyHasher> intermediates;
+ boost::unordered_map<uint256, SproutMerkleTree, CCoinsKeyHasher> intermediates;
BOOST_FOREACH(const JSDescription &joinsplit, tx.vjoinsplit)
{
}
}
- ZCIncrementalMerkleTree tree;
+ SproutMerkleTree tree;
auto it = intermediates.find(joinsplit.anchor);
if (it != intermediates.end()) {
tree = it->second;
if (GetNullifier(spendDescription.nullifier, SAPLING)) // Prevent double spends
return false;
- ZCSaplingIncrementalMerkleTree tree;
+ SaplingMerkleTree tree;
if (!GetSaplingAnchorAt(spendDescription.anchor, tree)) {
return false;
}
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
+ // Shielded transfers 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.
+ // use the maximum priority for all (partially or fully) shielded transactions.
+ // (Note that coinbase transactions cannot contain JoinSplits, or Sapling shielded Spends or Outputs.)
- if (tx.vjoinsplit.size() > 0) {
+ if (tx.vjoinsplit.size() > 0 || tx.vShieldedSpend.size() > 0 || tx.vShieldedOutput.size() > 0 || tx.IsCoinImport()) {
return MAX_PRIORITY;
}
+ // FIXME: this logic is partially duplicated between here and CreateNewBlock in miner.cpp.
double dResult = 0.0;
BOOST_FOREACH(const CTxIn& txin, tx.vin)
{