Fix miner issues
[novacoin.git] / src / wallet.cpp
index 22659da..dc1000c 100644 (file)
 #include "coincontrol.h"
 #include <boost/algorithm/string/replace.hpp>
 
+#include "main.h"
+
 using namespace std;
-extern int nStakeMaxAge;
+
 
 bool fCoinsDataActual;
 
@@ -1153,7 +1155,7 @@ void CWallet::AvailableCoins(vector<COutput>& vCoins, bool fOnlyConfirmed, const
     }
 }
 
-void CWallet::AvailableCoinsMinConf(vector<COutput>& vCoins, int nConf) const
+void CWallet::AvailableCoinsMinConf(vector<COutput>& vCoins, int nConf, int64 nMinValue, int64 nMaxValue) const
 {
     vCoins.clear();
 
@@ -1172,7 +1174,12 @@ void CWallet::AvailableCoinsMinConf(vector<COutput>& vCoins, int nConf) const
             for (unsigned int i = 0; i < pcoin->vout.size(); i++) {
                 isminetype mine = IsMine(pcoin->vout[i]);
 
-                if (!(pcoin->IsSpent(i)) && mine != MINE_NO && pcoin->vout[i].nValue >= nMinimumInputValue)
+                // ignore coin if it was already spent or we don't own it
+                if (pcoin->IsSpent(i) || mine == MINE_NO)
+                    continue;
+
+                // if coin value is between required limits then add new item to vector
+                if (pcoin->vout[i].nValue >= nMinValue && pcoin->vout[i].nValue < nMaxValue)
                     vCoins.push_back(COutput(pcoin, i, pcoin->GetDepthInMainChain(), mine == MINE_SPENDABLE));
             }
         }
@@ -1402,10 +1409,10 @@ bool CWallet::SelectCoins(int64 nTargetValue, unsigned int nSpendTime, set<pair<
 }
 
 // Select some coins without random shuffle or best subset approximation
-bool CWallet::SelectCoinsSimple(int64 nTargetValue, unsigned int nSpendTime, int nMinConf, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const
+bool CWallet::SelectCoinsSimple(int64 nTargetValue, int64 nMinValue, int64 nMaxValue, unsigned int nSpendTime, int nMinConf, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const
 {
     vector<COutput> vCoins;
-    AvailableCoinsMinConf(vCoins, nMinConf);
+    AvailableCoinsMinConf(vCoins, nMinConf, nMinValue, nMaxValue);
 
     setCoinsRet.clear();
     nValueRet = 0;
@@ -1620,10 +1627,66 @@ void CWallet::GetStakeWeightFromValue(const int64& nTime, const int64& nValue, u
 // NovaCoin: get current stake weight
 bool CWallet::GetStakeWeight(const CKeyStore& keystore, uint64& nMinWeight, uint64& nMaxWeight, uint64& nWeight)
 {
-    if (mapMeta.size() == 0 || !fCoinsDataActual)
+    // Choose coins to use
+    int64 nBalance = GetBalance();
+    int64 nReserveBalance = 0;
+
+    if (mapArgs.count("-reservebalance") && !ParseMoney(mapArgs["-reservebalance"], nReserveBalance))
+        return error("CreateCoinStake : invalid reserve balance amount");
+
+    if (nBalance <= nReserveBalance)
         return false;
 
-    // txid => ((txindex, (tx, vout.n)), (block, modifier))
+    CTxDB txdb("r");
+    {
+        LOCK2(cs_main, cs_wallet);
+        // Cache outputs unless best block or wallet transaction set changed
+        if (!fCoinsDataActual)
+        {
+            mapMeta.clear();
+            int64 nValueIn = 0;
+            CoinsSet setCoins;
+            if (!SelectCoinsSimple(nBalance - nReserveBalance, MIN_TX_FEE, MAX_MONEY, GetAdjustedTime(), nCoinbaseMaturity * 10, setCoins, nValueIn))
+                return false;
+
+            if (setCoins.empty())
+                return false;
+
+            {
+                CTxIndex txindex;
+                CBlock block;
+                for(CoinsSet::iterator pcoin = setCoins.begin(); pcoin != setCoins.end(); pcoin++)
+                {
+                    // Load transaction index item
+                    if (!txdb.ReadTxIndex(pcoin->first->GetHash(), txindex))
+                        continue;
+
+                    // Read block header
+                    if (!block.ReadFromDisk(txindex.pos.nFile, txindex.pos.nBlockPos, false))
+                        continue;
+
+                    uint64 nStakeModifier = 0;
+                    if (!GetKernelStakeModifier(block.GetHash(), nStakeModifier))
+                        continue;
+
+                    // Add meta record
+                    // (txid, vout.n) => ((txindex, (tx, vout.n)), (block, modifier))
+                    mapMeta[make_pair(pcoin->first->GetHash(), pcoin->second)] = make_pair(make_pair(txindex, *pcoin), make_pair(block, nStakeModifier));
+
+                    if (fDebug)
+                        printf("Load coin: %s\n", pcoin->first->GetHash().GetHex().c_str());
+                }
+            }
+
+            if (fDebug)
+                printf("Get stake weight: %zu meta items loaded for %zu coins\n", mapMeta.size(), setCoins.size());
+
+            fCoinsDataActual = true;
+        }
+    }
+
+
+    // (txid, vout.n) => ((txindex, (tx, vout.n)), (block, modifier))
     for(MetaMap::const_iterator meta_item = mapMeta.begin(); meta_item != mapMeta.end(); meta_item++)
     {
         // Get coin
@@ -1654,7 +1717,7 @@ bool CWallet::GetStakeWeight(const CKeyStore& keystore, uint64& nMinWeight, uint
     return true;
 }
 
-bool CWallet::MergeCoins(const int64& nAmount, const int64& nMaxValue, const int64& nOutputValue, list<uint256>& listMerged)
+bool CWallet::MergeCoins(const int64& nAmount, const int64& nMinValue, const int64& nOutputValue, list<uint256>& listMerged)
 {
     int64 nBalance = GetBalance();
 
@@ -1666,7 +1729,7 @@ bool CWallet::MergeCoins(const int64& nAmount, const int64& nMaxValue, const int
     set<pair<const CWalletTx*,unsigned int> > setCoins;
 
     // Simple coins selection - no randomization
-    if (!SelectCoinsSimple(nAmount, GetTime(), 1, setCoins, nValueIn))
+    if (!SelectCoinsSimple(nAmount, nMinValue, nOutputValue, GetTime(), 1, setCoins, nValueIn))
         return false;
 
     if (setCoins.empty())
@@ -1691,10 +1754,6 @@ bool CWallet::MergeCoins(const int64& nAmount, const int64& nMaxValue, const int
     {
         int64 nCredit = pcoin.first->vout[pcoin.second].nValue;
 
-        // Ignore coin if credit is too high
-        if (nCredit >= nMaxValue)
-            continue;
-
         // Add current coin to inputs list and add its credit to transaction output
         wtxNew.vin.push_back(CTxIn(pcoin.first->GetHash(), pcoin.second));
         wtxNew.vout[0].nValue += nCredit;
@@ -1820,7 +1879,7 @@ bool CWallet::CreateCoinStake(const CKeyStore& keystore, unsigned int nBits, int
             mapMeta.clear();
             int64 nValueIn = 0;
             CoinsSet setCoins;
-            if (!SelectCoinsSimple(nBalance - nReserveBalance, txNew.nTime, nCoinbaseMaturity * 10, setCoins, nValueIn))
+            if (!SelectCoinsSimple(nBalance - nReserveBalance, MIN_TX_FEE, MAX_MONEY, txNew.nTime, nCoinbaseMaturity * 10, setCoins, nValueIn))
                 return false;
 
             if (setCoins.empty())
@@ -1845,7 +1904,7 @@ bool CWallet::CreateCoinStake(const CKeyStore& keystore, unsigned int nBits, int
 
                     // Add meta record
                     // txid => ((txindex, (tx, vout.n)), (block, modifier))
-                    mapMeta[pcoin->first->GetHash()] = make_pair(make_pair(txindex, *pcoin), make_pair(block, nStakeModifier));
+                    mapMeta[make_pair(pcoin->first->GetHash(), pcoin->second)] = make_pair(make_pair(txindex, *pcoin), make_pair(block, nStakeModifier));
 
                     if (fDebug)
                         printf("Load coin: %s\n", pcoin->first->GetHash().GetHex().c_str());
@@ -1941,7 +2000,7 @@ bool CWallet::CreateCoinStake(const CKeyStore& keystore, unsigned int nBits, int
     if (nCredit == 0 || nCredit > nBalance - nReserveBalance)
         return false;
 
-    // txid => ((txindex, (tx, vout.n)), (block, modifier))
+    // (txid, vout.n) => ((txindex, (tx, vout.n)), (block, modifier))
     for(MetaMap::const_iterator meta_item = mapMeta.begin(); meta_item != mapMeta.end(); meta_item++)
     {
         // Get coin