diff --git a/src/wallet.cpp b/src/wallet.cpp index 46bbe0b6dcb84..3cb7ce153b5b2 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -1249,6 +1249,23 @@ static void ApproximateBestSubset(vectorvout[out1.i].nValue == d) found1 = true; + if(pcoin2->vout[out2.i].nValue == d) found2 = true; + } + return (!found1 && found2); +} + bool CWallet::SelectCoinsMinConf(int64_t nTargetValue, int nConfMine, int nConfTheirs, vector vCoins, set >& setCoinsRet, int64_t& nValueRet) const { @@ -1264,52 +1281,85 @@ bool CWallet::SelectCoinsMinConf(int64_t nTargetValue, int nConfMine, int nConfT random_shuffle(vCoins.begin(), vCoins.end(), GetRandInt); - BOOST_FOREACH(COutput output, vCoins) + // move denoms down on the list + sort(vCoins.begin(), vCoins.end(), less_then_denom); + + // try to find nondenom first to prevent unneeded spending of mixed coins + for (unsigned int tryDenom = 0; tryDenom < 2; tryDenom++) { - const CWalletTx *pcoin = output.tx; + if (fDebug) LogPrint("selectcoins", "tryDenom: %d\n", tryDenom); + setCoinsRet.clear(); + nValueRet = 0; + nTotalLower = 0; - if (output.nDepth < (pcoin->IsFromMe() ? nConfMine : nConfTheirs)) - continue; + BOOST_FOREACH(COutput output, vCoins) + { + const CWalletTx *pcoin = output.tx; - int i = output.i; - int64_t n = pcoin->vout[i].nValue; +// if (fDebug) LogPrint("selectcoins", "value %s confirms %d\n", FormatMoney(pcoin->vout[output.i].nValue), output.nDepth); + if (output.nDepth < (pcoin->IsFromMe() ? nConfMine : nConfTheirs)) + continue; - pair > coin = make_pair(n,make_pair(pcoin, i)); + int i = output.i; + int64_t n = pcoin->vout[i].nValue; - if (n == nTargetValue) - { - setCoinsRet.insert(coin.second); - nValueRet += coin.first; - return true; - } - else if (n < nTargetValue + CENT) - { - vValue.push_back(coin); - nTotalLower += n; + if (tryDenom == 0) // first run? + { + bool found = false; + BOOST_FOREACH(int64_t d, darkSendDenominations) // loop through predefined denoms + if(n == d) + found = true; + if (found) continue; // we don't want denom values on first run + } + + pair > coin = make_pair(n,make_pair(pcoin, i)); + + if (n == nTargetValue) + { + setCoinsRet.insert(coin.second); + nValueRet += coin.first; + return true; + } + else if (n < nTargetValue + CENT) + { + vValue.push_back(coin); + nTotalLower += n; + } + else if (n < coinLowestLarger.first) + { + coinLowestLarger = coin; + } } - else if (n < coinLowestLarger.first) + + if (nTotalLower == nTargetValue) { - coinLowestLarger = coin; + for (unsigned int i = 0; i < vValue.size(); ++i) + { + setCoinsRet.insert(vValue[i].second); + nValueRet += vValue[i].first; + } + return true; } - } - if (nTotalLower == nTargetValue) - { - for (unsigned int i = 0; i < vValue.size(); ++i) + if (nTotalLower < nTargetValue) { - setCoinsRet.insert(vValue[i].second); - nValueRet += vValue[i].first; + if (coinLowestLarger.second.first == NULL) // there is no input larger than nTargetValue + { + if (tryDenom == 0) + // we didn't look at denom yet, let's do it + continue; + else + // we looked at everything possible and didn't find anything, no luck + return false; + } + setCoinsRet.insert(coinLowestLarger.second); + nValueRet += coinLowestLarger.first; + return true; } - return true; - } - if (nTotalLower < nTargetValue) - { - if (coinLowestLarger.second.first == NULL) - return false; - setCoinsRet.insert(coinLowestLarger.second); - nValueRet += coinLowestLarger.first; - return true; + // nTotalLower > nTargetValue + break; + } // Solve subset sum by stochastic approximation