]> Git Repo - VerusCoin.git/blobdiff - src/coins.cpp
Complete block reserve conversion solution, final update and import remaining
[VerusCoin.git] / src / coins.cpp
index b49fce18e7f14907cd1116ec62286de8af0a253c..06162c9a5284a75afc2215dea07763e9dc2f3f3d 100644 (file)
@@ -8,6 +8,10 @@
 #include "random.h"
 #include "version.h"
 #include "policy/fees.h"
+#include "komodo_defs.h"
+#include "importcoin.h"
+#include "pbaas/notarization.h"
+#include "pbaas/reserves.h"
 
 #include <assert.h>
 
@@ -42,8 +46,8 @@ bool CCoins::Spend(uint32_t nPos)
     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; }
@@ -62,8 +66,8 @@ bool CCoinsView::GetStats(CCoinsStats &stats) 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); }
@@ -117,7 +121,7 @@ CCoinsMap::const_iterator CCoinsViewCache::FetchCoins(const uint256 &txid) const
 }
 
 
-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) {
@@ -140,7 +144,7 @@ bool CCoinsViewCache::GetSproutAnchorAt(const uint256 &rt, ZCIncrementalMerkleTr
     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) {
@@ -222,9 +226,9 @@ void CCoinsViewCache::AbstractPushAnchor(
     }
 }
 
-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,
@@ -232,9 +236,9 @@ template<> void CCoinsViewCache::PushAnchor(const ZCIncrementalMerkleTree &tree)
     );
 }
 
-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,
@@ -245,7 +249,7 @@ template<> void CCoinsViewCache::PushAnchor(const ZCSaplingIncrementalMerkleTree
 template<>
 void CCoinsViewCache::BringBestAnchorIntoCache(
     const uint256 &currentRoot,
-    ZCIncrementalMerkleTree &tree
+    SproutMerkleTree &tree
 )
 {
     assert(GetSproutAnchorAt(currentRoot, tree));
@@ -254,7 +258,7 @@ void CCoinsViewCache::BringBestAnchorIntoCache(
 template<>
 void CCoinsViewCache::BringBestAnchorIntoCache(
     const uint256 &currentRoot,
-    ZCSaplingIncrementalMerkleTree &tree
+    SaplingMerkleTree &tree
 )
 {
     assert(GetSaplingAnchorAt(currentRoot, tree));
@@ -295,7 +299,7 @@ void CCoinsViewCache::AbstractPopAnchor(
 void CCoinsViewCache::PopAnchor(const uint256 &newrt, ShieldedType type) {
     switch (type) {
         case SPROUT:
-            AbstractPopAnchor<ZCIncrementalMerkleTree, CAnchorsSproutMap, CAnchorsSproutCacheEntry>(
+            AbstractPopAnchor<SproutMerkleTree, CAnchorsSproutMap, CAnchorsSproutCacheEntry>(
                 newrt,
                 SPROUT,
                 cacheSproutAnchors,
@@ -303,7 +307,7 @@ void CCoinsViewCache::PopAnchor(const uint256 &newrt, ShieldedType type) {
             );
             break;
         case SAPLING:
-            AbstractPopAnchor<ZCSaplingIncrementalMerkleTree, CAnchorsSaplingMap, CAnchorsSaplingCacheEntry>(
+            AbstractPopAnchor<SaplingMerkleTree, CAnchorsSaplingMap, CAnchorsSaplingCacheEntry>(
                 newrt,
                 SAPLING,
                 cacheSaplingAnchors,
@@ -380,7 +384,16 @@ bool CCoinsViewCache::HaveCoins(const uint256 &txid) const {
 
 uint256 CCoinsViewCache::GetBestBlock() const {
     if (hashBlock.IsNull())
-        hashBlock = base->GetBestBlock();
+    {
+        if (base)
+        {
+            hashBlock = base->GetBestBlock();
+        }
+        else
+        {
+            hashBlock = uint256();
+        }
+    }
     return hashBlock;
 }
 
@@ -539,23 +552,120 @@ const CTxOut &CCoinsViewCache::GetOutputFor(const CTxIn& input) const
     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;
+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++)
-        nResult += GetOutputFor(tx.vin[i]).nValue;
+    {
+        value = 0;
+        const CCoins* coins = AccessCoins(tx.vin[i].prevout.hash);
+        if (coins && coins->IsAvailable(tx.vin[i].prevout.n))
+        {
+            value = coins->vout[tx.vin[i].prevout.n].nValue;
+        }
+        else
+        {
+            return 0;
+        }
 
+        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;
+                if (interestp)
+                    (*interestp) += interest;
+            }
+        }
+#endif
+    }
     nResult += tx.GetShieldedValueIn();
 
     return nResult;
 }
 
+CAmount CCoinsViewCache::GetReserveValueIn(int32_t nHeight, const CTransaction& tx) const
+{
+    CAmount value, nResult = 0;
+
+    /* we don't support this coin import, so we should add reserve import support and uncomment
+    if ( tx.IsCoinImport() )
+        return GetCoinImportValue(tx);
+    */
+
+    // coinbases have no inputs
+    if ( tx.IsCoinBase() != 0 )
+        return 0;
+
+    for (unsigned int i = 0; i < tx.vin.size(); i++)
+    {
+        value = 0;
+        const CCoins* coins = AccessCoins(tx.vin[i].prevout.hash);
+        if (coins && coins->IsAvailable(tx.vin[i].prevout.n))
+        {
+            COptCCParams p;
+            if (::IsPayToCryptoCondition(coins->vout[tx.vin[i].prevout.n].scriptPubKey, p) && p.evalCode == EVAL_RESERVE_OUTPUT && p.vData.size())
+            {
+                CReserveOutput ro(p.vData[0]);
+                if (ro.IsValid())
+                {
+                    value = ro.nValue;
+                }
+            }
+        }
+        else
+        {
+            return 0;
+        }
+
+        nResult += value;
+    }
+    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)
     {
@@ -568,7 +678,7 @@ bool CCoinsViewCache::HaveJoinSplitRequirements(const CTransaction& tx) const
             }
         }
 
-        ZCIncrementalMerkleTree tree;
+        SproutMerkleTree tree;
         auto it = intermediates.find(joinsplit.anchor);
         if (it != intermediates.end()) {
             tree = it->second;
@@ -588,7 +698,7 @@ bool CCoinsViewCache::HaveJoinSplitRequirements(const CTransaction& tx) const
         if (GetNullifier(spendDescription.nullifier, SAPLING)) // Prevent double spends
             return false;
 
-        ZCSaplingIncrementalMerkleTree tree;
+        SaplingMerkleTree tree;
         if (!GetSaplingAnchorAt(spendDescription.anchor, tree)) {
             return false;
         }
@@ -599,11 +709,12 @@ bool CCoinsViewCache::HaveJoinSplitRequirements(const CTransaction& tx) const
 
 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;
             }
         }
@@ -611,21 +722,21 @@ bool CCoinsViewCache::HaveInputs(const CTransaction& tx) const
     return true;
 }
 
-double CCoinsViewCache::GetPriority(const CTransaction &tx, int nHeight) const
+double CCoinsViewCache::GetPriority(const CTransaction &tx, int nHeight, const CReserveTransactionDescriptor *desc, const CCurrencyState *currencyState) const
 {
     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)
     {
@@ -633,7 +744,26 @@ double CCoinsViewCache::GetPriority(const CTransaction &tx, int nHeight) const
         assert(coins);
         if (!coins->IsAvailable(txin.prevout.n)) continue;
         if (coins->nHeight < nHeight) {
-            dResult += coins->vout[txin.prevout.n].nValue * (nHeight-coins->nHeight);
+            if (currencyState && desc)
+            {
+                if (coins->nHeight < nHeight) {
+                    double confs = nHeight - coins->nHeight;
+                    CAmount nativeVal = coins->vout[txin.prevout.n].nValue;
+                    CAmount reserveVal = coins->vout[txin.prevout.n].ReserveOutValue();
+                    if (nativeVal)
+                    {
+                        dResult += nativeVal * confs;
+                    }
+                    if (reserveVal)
+                    {
+                        dResult += reserveVal * confs;
+                    }
+                }
+            }
+            else
+            {
+                dResult += coins->vout[txin.prevout.n].nValue * (nHeight-coins->nHeight);
+            }
         }
     }
 
This page took 0.038058 seconds and 4 git commands to generate.