Slightly optimize ApproximateBestSubset and its usage for PS txes (#3184)

* From 2 best sets with the same `nTotal` in ApproximateBestSubset prefer the one with less inputs

* There is no reason to run ApproximateBestSubset again if nMinChange is 0

* Apply review suggestions
This commit is contained in:
UdjinM6 2019-11-04 20:35:58 +03:00 committed by Alexander Block
parent 16b6b6f7c2
commit 66e298728e

View File

@ -2570,6 +2570,7 @@ static void ApproximateBestSubset(std::vector<std::pair<CAmount, std::pair<const
vfBest.assign(vValue.size(), true); vfBest.assign(vValue.size(), true);
nBest = nTotalLower; nBest = nTotalLower;
int nBestInputCount = 0;
if (!llmq::IsOldInstantSendEnabled()) { if (!llmq::IsOldInstantSendEnabled()) {
// The new system does not require special handling for InstantSend as this is all done in CInstantSendManager. // The new system does not require special handling for InstantSend as this is all done in CInstantSendManager.
@ -2583,6 +2584,7 @@ static void ApproximateBestSubset(std::vector<std::pair<CAmount, std::pair<const
{ {
vfIncluded.assign(vValue.size(), false); vfIncluded.assign(vValue.size(), false);
CAmount nTotal = 0; CAmount nTotal = 0;
int nTotalInputCount = 0;
bool fReachedTarget = false; bool fReachedTarget = false;
for (int nPass = 0; nPass < 2 && !fReachedTarget; nPass++) for (int nPass = 0; nPass < 2 && !fReachedTarget; nPass++)
{ {
@ -2600,16 +2602,19 @@ static void ApproximateBestSubset(std::vector<std::pair<CAmount, std::pair<const
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].first;
++nTotalInputCount;
vfIncluded[i] = true; vfIncluded[i] = true;
if (nTotal >= nTargetValue) if (nTotal >= nTargetValue)
{ {
fReachedTarget = true; fReachedTarget = true;
if (nTotal < nBest) if (nTotal < nBest || (nTotal == nBest && nTotalInputCount < nBestInputCount))
{ {
nBest = nTotal; nBest = nTotal;
nBestInputCount = nTotalInputCount;
vfBest = vfIncluded; vfBest = vfIncluded;
} }
nTotal -= vValue[i].first; nTotal -= vValue[i].first;
--nTotalInputCount;
vfIncluded[i] = false; vfIncluded[i] = false;
} }
} }
@ -2774,7 +2779,7 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, const int nConfMin
CAmount nBest; CAmount nBest;
ApproximateBestSubset(vValue, nTotalLower, nTargetValue, vfBest, nBest, fUseInstantSend); ApproximateBestSubset(vValue, nTotalLower, nTargetValue, vfBest, nBest, fUseInstantSend);
if (nBest != nTargetValue && nTotalLower >= nTargetValue + nMinChange) if (nBest != nTargetValue && nMinChange != 0 && nTotalLower >= nTargetValue + nMinChange)
ApproximateBestSubset(vValue, nTotalLower, nTargetValue + nMinChange, vfBest, nBest, fUseInstantSend); ApproximateBestSubset(vValue, nTotalLower, nTargetValue + nMinChange, vfBest, nBest, fUseInstantSend);
// 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,