|
|
@ -65,10 +65,10 @@ const uint256 CMerkleTx::ABANDON_HASH(uint256S("00000000000000000000000000000000 |
|
|
|
|
|
|
|
|
|
|
|
struct CompareValueOnly |
|
|
|
struct CompareValueOnly |
|
|
|
{ |
|
|
|
{ |
|
|
|
bool operator()(const std::pair<CAmount, CInputCoin>& t1, |
|
|
|
bool operator()(const CInputCoin& t1, |
|
|
|
const std::pair<CAmount, CInputCoin>& t2) const |
|
|
|
const CInputCoin& t2) const |
|
|
|
{ |
|
|
|
{ |
|
|
|
return t1.first < t2.first; |
|
|
|
return t1.txout.nValue < t2.txout.nValue; |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
@ -2032,7 +2032,7 @@ void CWallet::AvailableCoins(std::vector<COutput>& vCoins, bool fOnlySafe, const |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void ApproximateBestSubset(const std::vector<std::pair<CAmount, CInputCoin> >& vValue, const CAmount& nTotalLower, const CAmount& nTargetValue, |
|
|
|
static void ApproximateBestSubset(const std::vector<CInputCoin>& vValue, const CAmount& nTotalLower, const CAmount& nTargetValue, |
|
|
|
std::vector<char>& vfBest, CAmount& nBest, int iterations = 1000) |
|
|
|
std::vector<char>& vfBest, CAmount& nBest, int iterations = 1000) |
|
|
|
{ |
|
|
|
{ |
|
|
|
std::vector<char> vfIncluded; |
|
|
|
std::vector<char> vfIncluded; |
|
|
@ -2059,7 +2059,7 @@ static void ApproximateBestSubset(const std::vector<std::pair<CAmount, CInputCoi |
|
|
|
//the selection random.
|
|
|
|
//the selection random.
|
|
|
|
if (nPass == 0 ? insecure_rand.rand32()&1 : !vfIncluded[i]) |
|
|
|
if (nPass == 0 ? insecure_rand.rand32()&1 : !vfIncluded[i]) |
|
|
|
{ |
|
|
|
{ |
|
|
|
nTotal += vValue[i].first; |
|
|
|
nTotal += vValue[i].txout.nValue; |
|
|
|
vfIncluded[i] = true; |
|
|
|
vfIncluded[i] = true; |
|
|
|
if (nTotal >= nTargetValue) |
|
|
|
if (nTotal >= nTargetValue) |
|
|
|
{ |
|
|
|
{ |
|
|
@ -2069,7 +2069,7 @@ static void ApproximateBestSubset(const std::vector<std::pair<CAmount, CInputCoi |
|
|
|
nBest = nTotal; |
|
|
|
nBest = nTotal; |
|
|
|
vfBest = vfIncluded; |
|
|
|
vfBest = vfIncluded; |
|
|
|
} |
|
|
|
} |
|
|
|
nTotal -= vValue[i].first; |
|
|
|
nTotal -= vValue[i].txout.nValue; |
|
|
|
vfIncluded[i] = false; |
|
|
|
vfIncluded[i] = false; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -2085,9 +2085,8 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, const int nConfMin |
|
|
|
nValueRet = 0; |
|
|
|
nValueRet = 0; |
|
|
|
|
|
|
|
|
|
|
|
// List of values less than target
|
|
|
|
// List of values less than target
|
|
|
|
std::pair<CAmount, CInputCoin> coinLowestLarger; |
|
|
|
CInputCoin coinLowestLarger; |
|
|
|
coinLowestLarger.first = std::numeric_limits<CAmount>::max(); |
|
|
|
std::vector<CInputCoin> vValue; |
|
|
|
std::vector<std::pair<CAmount, CInputCoin> > vValue; |
|
|
|
|
|
|
|
CAmount nTotalLower = 0; |
|
|
|
CAmount nTotalLower = 0; |
|
|
|
|
|
|
|
|
|
|
|
random_shuffle(vCoins.begin(), vCoins.end(), GetRandInt); |
|
|
|
random_shuffle(vCoins.begin(), vCoins.end(), GetRandInt); |
|
|
@ -2106,22 +2105,21 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, const int nConfMin |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
|
|
int i = output.i; |
|
|
|
int i = output.i; |
|
|
|
CAmount n = pcoin->tx->vout[i].nValue; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::pair<CAmount,CInputCoin> coin = std::make_pair(n, CInputCoin(pcoin, i)); |
|
|
|
CInputCoin coin = CInputCoin(pcoin, i); |
|
|
|
|
|
|
|
|
|
|
|
if (n == nTargetValue) |
|
|
|
if (coin.txout.nValue == nTargetValue) |
|
|
|
{ |
|
|
|
{ |
|
|
|
setCoinsRet.insert(coin.second); |
|
|
|
setCoinsRet.insert(coin); |
|
|
|
nValueRet += coin.first; |
|
|
|
nValueRet += coin.txout.nValue; |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
else if (n < nTargetValue + MIN_CHANGE) |
|
|
|
else if (coin.txout.nValue < nTargetValue + MIN_CHANGE) |
|
|
|
{ |
|
|
|
{ |
|
|
|
vValue.push_back(coin); |
|
|
|
vValue.push_back(coin); |
|
|
|
nTotalLower += n; |
|
|
|
nTotalLower += coin.txout.nValue; |
|
|
|
} |
|
|
|
} |
|
|
|
else if (n < coinLowestLarger.first) |
|
|
|
else if (coinLowestLarger.IsNull() || coin.txout.nValue < coinLowestLarger.txout.nValue) |
|
|
|
{ |
|
|
|
{ |
|
|
|
coinLowestLarger = coin; |
|
|
|
coinLowestLarger = coin; |
|
|
|
} |
|
|
|
} |
|
|
@ -2131,18 +2129,18 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, const int nConfMin |
|
|
|
{ |
|
|
|
{ |
|
|
|
for (unsigned int i = 0; i < vValue.size(); ++i) |
|
|
|
for (unsigned int i = 0; i < vValue.size(); ++i) |
|
|
|
{ |
|
|
|
{ |
|
|
|
setCoinsRet.insert(vValue[i].second); |
|
|
|
setCoinsRet.insert(vValue[i]); |
|
|
|
nValueRet += vValue[i].first; |
|
|
|
nValueRet += vValue[i].txout.nValue; |
|
|
|
} |
|
|
|
} |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (nTotalLower < nTargetValue) |
|
|
|
if (nTotalLower < nTargetValue) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (coinLowestLarger.second.IsNull()) |
|
|
|
if (coinLowestLarger.IsNull()) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
setCoinsRet.insert(coinLowestLarger.second); |
|
|
|
setCoinsRet.insert(coinLowestLarger); |
|
|
|
nValueRet += coinLowestLarger.first; |
|
|
|
nValueRet += coinLowestLarger.txout.nValue; |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -2158,25 +2156,25 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, const int nConfMin |
|
|
|
|
|
|
|
|
|
|
|
// If we have a bigger coin and (either the stochastic approximation didn't find a good solution,
|
|
|
|
// If we have a bigger coin and (either the stochastic approximation didn't find a good solution,
|
|
|
|
// or the next bigger coin is closer), return the bigger coin
|
|
|
|
// or the next bigger coin is closer), return the bigger coin
|
|
|
|
if (coinLowestLarger.second.IsNull() && |
|
|
|
if (!coinLowestLarger.IsNull() && |
|
|
|
((nBest != nTargetValue && nBest < nTargetValue + MIN_CHANGE) || coinLowestLarger.first <= nBest)) |
|
|
|
((nBest != nTargetValue && nBest < nTargetValue + MIN_CHANGE) || coinLowestLarger.txout.nValue <= nBest)) |
|
|
|
{ |
|
|
|
{ |
|
|
|
setCoinsRet.insert(coinLowestLarger.second); |
|
|
|
setCoinsRet.insert(coinLowestLarger); |
|
|
|
nValueRet += coinLowestLarger.first; |
|
|
|
nValueRet += coinLowestLarger.txout.nValue; |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
else { |
|
|
|
for (unsigned int i = 0; i < vValue.size(); i++) |
|
|
|
for (unsigned int i = 0; i < vValue.size(); i++) |
|
|
|
if (vfBest[i]) |
|
|
|
if (vfBest[i]) |
|
|
|
{ |
|
|
|
{ |
|
|
|
setCoinsRet.insert(vValue[i].second); |
|
|
|
setCoinsRet.insert(vValue[i]); |
|
|
|
nValueRet += vValue[i].first; |
|
|
|
nValueRet += vValue[i].txout.nValue; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (LogAcceptCategory(BCLog::SELECTCOINS)) { |
|
|
|
if (LogAcceptCategory(BCLog::SELECTCOINS)) { |
|
|
|
LogPrint(BCLog::SELECTCOINS, "SelectCoins() best subset: "); |
|
|
|
LogPrint(BCLog::SELECTCOINS, "SelectCoins() best subset: "); |
|
|
|
for (unsigned int i = 0; i < vValue.size(); i++) { |
|
|
|
for (unsigned int i = 0; i < vValue.size(); i++) { |
|
|
|
if (vfBest[i]) { |
|
|
|
if (vfBest[i]) { |
|
|
|
LogPrint(BCLog::SELECTCOINS, "%s ", FormatMoney(vValue[i].first)); |
|
|
|
LogPrint(BCLog::SELECTCOINS, "%s ", FormatMoney(vValue[i].txout.nValue)); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
LogPrint(BCLog::SELECTCOINS, "total %s\n", FormatMoney(nBest)); |
|
|
|
LogPrint(BCLog::SELECTCOINS, "total %s\n", FormatMoney(nBest)); |
|
|
|