#include "coincontrol.h"
#include <boost/algorithm/string/replace.hpp>
+#include "main.h"
+
using namespace std;
-extern int nStakeMaxAge;
+
bool fCoinsDataActual;
}
}
-void CWallet::AvailableCoinsMinConf(vector<COutput>& vCoins, int nConf) const
+void CWallet::AvailableCoinsMinConf(vector<COutput>& vCoins, int nConf, int64 nMinValue, int64 nMaxValue) const
{
vCoins.clear();
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));
}
}
}
// 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;
// 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;
+ 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 => ((txindex, (tx, vout.n)), (block, modifier))
+ mapMeta[pcoin->first->GetHash()] = 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 => ((txindex, (tx, vout.n)), (block, modifier))
for(MetaMap::const_iterator meta_item = mapMeta.begin(); meta_item != mapMeta.end(); meta_item++)
{
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();
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())
{
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;
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())