Add more variance to coin selection in PS mixing (#2261)
* Lean towards "from high to low" branch but still mix via "from low to high" one someties * Try to mix non-duplicate txids only * Lean towards edges but still mix starting from the middle sometimes If failed when started from the middle try mixing from the edges right away. Note: liqudity providers always start from 0 * map -> set * Refactor nRoundStart calculations
This commit is contained in:
parent
cb37c39725
commit
ad31dbbd73
@ -1036,7 +1036,7 @@ bool CPrivateSendClientSession::JoinExistingQueue(CAmount nBalanceNeedsAnonymize
|
||||
CAmount nMaxAmount = nBalanceNeedsAnonymized;
|
||||
|
||||
// Try to match their denominations if possible, select exact number of denominations
|
||||
if(!pwalletMain->SelectCoinsByDenominations(dsq.nDenom, nMinAmount, nMaxAmount, vecTxDSInTmp, vCoinsTmp, nValueInTmp, 0, privateSendClient.nPrivateSendRounds)) {
|
||||
if(!pwalletMain->SelectCoinsByDenominations(dsq.nDenom, nMinAmount, nMaxAmount, vecTxDSInTmp, vCoinsTmp, nValueInTmp, 0, privateSendClient.nPrivateSendRounds, true)) {
|
||||
LogPrintf("CPrivateSendClientSession::JoinExistingQueue -- Couldn't match %d denominations %d (%s)\n", vecBits.front(), dsq.nDenom, CPrivateSend::GetDenominationsToString(dsq.nDenom));
|
||||
continue;
|
||||
}
|
||||
@ -1180,26 +1180,46 @@ bool CPrivateSendClientSession::SubmitDenominate(CConnman& connman)
|
||||
std::string strError;
|
||||
std::vector<CTxDSIn> vecTxDSInRet;
|
||||
std::vector<CTxOut> vecTxOutRet;
|
||||
// lean towards "highest" branch but still mix via "lowest" one someties
|
||||
bool fMixLowest = privateSendClient.nLiquidityProvider || (GetRandInt(4) == 0);
|
||||
// lean towards edges but still mix starting from the middle someties
|
||||
// Note: liqudity providers always start from 0
|
||||
bool fScanFromTheMiddle = (privateSendClient.nLiquidityProvider == 0) && (GetRandInt(4) == 0);
|
||||
|
||||
int nRoundStart{0};
|
||||
if (fScanFromTheMiddle) {
|
||||
nRoundStart = privateSendClient.nPrivateSendRounds / 2;
|
||||
} else if (!fMixLowest) {
|
||||
nRoundStart = privateSendClient.nPrivateSendRounds;
|
||||
}
|
||||
|
||||
// Submit transaction to the pool if we get here
|
||||
if (privateSendClient.nLiquidityProvider) {
|
||||
// Try to use only inputs with the same number of rounds starting from the lowest number of rounds possible
|
||||
for(int i = 0; i< privateSendClient.nPrivateSendRounds; i++) {
|
||||
if (fMixLowest) {
|
||||
// Try to use only inputs with the same number of rounds, from low to high
|
||||
while (true) {
|
||||
for(int i = nRoundStart; i < privateSendClient.nPrivateSendRounds; i++) {
|
||||
if(PrepareDenominate(i, i + 1, strError, vecTxDSInRet, vecTxOutRet)) {
|
||||
LogPrintf("CPrivateSendClientSession::SubmitDenominate -- Running PrivateSend denominate for %d rounds, success\n", i);
|
||||
return SendDenominate(vecTxDSInRet, vecTxOutRet, connman);
|
||||
}
|
||||
LogPrint("privatesend", "CPrivateSendClientSession::SubmitDenominate -- Running PrivateSend denominate for %d rounds, error: %s\n", i, strError);
|
||||
}
|
||||
if (nRoundStart == 0) break;
|
||||
nRoundStart = 0;
|
||||
}
|
||||
} else {
|
||||
// Try to use only inputs with the same number of rounds starting from the highest number of rounds possible
|
||||
for(int i = privateSendClient.nPrivateSendRounds; i > 0; i--) {
|
||||
// Try to use only inputs with the same number of rounds, from high to low
|
||||
while (true) {
|
||||
for(int i = nRoundStart; i > 0; i--) {
|
||||
if(PrepareDenominate(i - 1, i, strError, vecTxDSInRet, vecTxOutRet)) {
|
||||
LogPrintf("CPrivateSendClientSession::SubmitDenominate -- Running PrivateSend denominate for %d rounds, success\n", i);
|
||||
return SendDenominate(vecTxDSInRet, vecTxOutRet, connman);
|
||||
}
|
||||
LogPrint("privatesend", "CPrivateSendClientSession::SubmitDenominate -- Running PrivateSend denominate for %d rounds, error: %s\n", i, strError);
|
||||
}
|
||||
if (nRoundStart == privateSendClient.nPrivateSendRounds) break;
|
||||
nRoundStart = privateSendClient.nPrivateSendRounds;
|
||||
}
|
||||
}
|
||||
|
||||
// We failed? That's strange but let's just make final attempt and try to mix everything
|
||||
@ -1251,7 +1271,7 @@ bool CPrivateSendClientSession::PrepareDenominate(int nMinRounds, int nMaxRounds
|
||||
return false;
|
||||
}
|
||||
std::vector<CAmount> vecStandardDenoms = CPrivateSend::GetStandardDenominations();
|
||||
bool fSelected = pwalletMain->SelectCoinsByDenominations(nSessionDenom, vecStandardDenoms[vecBits.front()], CPrivateSend::GetMaxPoolAmount(), vecTxDSIn, vCoins, nValueIn, nMinRounds, nMaxRounds);
|
||||
bool fSelected = pwalletMain->SelectCoinsByDenominations(nSessionDenom, vecStandardDenoms[vecBits.front()], CPrivateSend::GetMaxPoolAmount(), vecTxDSIn, vCoins, nValueIn, nMinRounds, nMaxRounds, true);
|
||||
if (nMinRounds >= 0 && !fSelected) {
|
||||
strErrorRet = "Can't select current denominated inputs";
|
||||
return false;
|
||||
|
@ -3007,8 +3007,10 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, bool ov
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CWallet::SelectCoinsByDenominations(int nDenom, CAmount nValueMin, CAmount nValueMax, std::vector<CTxDSIn>& vecTxDSInRet, std::vector<COutput>& vCoinsRet, CAmount& nValueRet, int nPrivateSendRoundsMin, int nPrivateSendRoundsMax)
|
||||
bool CWallet::SelectCoinsByDenominations(int nDenom, CAmount nValueMin, CAmount nValueMax, std::vector<CTxDSIn>& vecTxDSInRet, std::vector<COutput>& vCoinsRet, CAmount& nValueRet, int nPrivateSendRoundsMin, int nPrivateSendRoundsMax, bool fNoDuplicateTxIds)
|
||||
{
|
||||
std::set<uint256> setRecentTxIds;
|
||||
|
||||
vecTxDSInRet.clear();
|
||||
vCoinsRet.clear();
|
||||
nValueRet = 0;
|
||||
@ -3037,6 +3039,7 @@ bool CWallet::SelectCoinsByDenominations(int nDenom, CAmount nValueMin, CAmount
|
||||
{
|
||||
// masternode-like input should not be selected by AvailableCoins now anyway
|
||||
//if(out.tx->vout[out.i].nValue == 1000*COIN) continue;
|
||||
if(fNoDuplicateTxIds && setRecentTxIds.find(out.tx->GetHash()) != setRecentTxIds.end()) continue;
|
||||
if(nValueRet + out.tx->tx->vout[out.i].nValue <= nValueMax){
|
||||
|
||||
CTxIn txin = CTxIn(out.tx->GetHash(), out.i);
|
||||
@ -3051,11 +3054,15 @@ bool CWallet::SelectCoinsByDenominations(int nDenom, CAmount nValueMin, CAmount
|
||||
vecTxDSInRet.push_back(CTxDSIn(txin, out.tx->tx->vout[out.i].scriptPubKey));
|
||||
vCoinsRet.push_back(out);
|
||||
nDenomResult |= 1 << nBit;
|
||||
setRecentTxIds.emplace(out.tx->GetHash());
|
||||
LogPrint("privatesend", "CWallet::SelectCoinsByDenominations -- hash %s nValue %d\n", out.tx->GetHash().ToString(), out.tx->tx->vout[out.i].nValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LogPrintf("CWallet::SelectCoinsByDenominations -- setRecentTxIds.size() %d\n", setRecentTxIds.size());
|
||||
|
||||
return nValueRet >= nValueMin && nDenom == nDenomResult;
|
||||
}
|
||||
|
||||
|
@ -806,7 +806,7 @@ public:
|
||||
bool SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int nConfTheirs, uint64_t nMaxAncestors, std::vector<COutput> vCoins, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, CAmount& nValueRet, bool fUseInstantSend = false) const;
|
||||
|
||||
// Coin selection
|
||||
bool SelectCoinsByDenominations(int nDenom, CAmount nValueMin, CAmount nValueMax, std::vector<CTxDSIn>& vecTxDSInRet, std::vector<COutput>& vCoinsRet, CAmount& nValueRet, int nPrivateSendRoundsMin, int nPrivateSendRoundsMax);
|
||||
bool SelectCoinsByDenominations(int nDenom, CAmount nValueMin, CAmount nValueMax, std::vector<CTxDSIn>& vecTxDSInRet, std::vector<COutput>& vCoinsRet, CAmount& nValueRet, int nPrivateSendRoundsMin, int nPrivateSendRoundsMax, bool fNoDuplicateTxIds);
|
||||
bool GetCollateralTxDSIn(CTxDSIn& txdsinRet, CAmount& nValueRet) const;
|
||||
bool SelectCoinsDark(CAmount nValueMin, CAmount nValueMax, std::vector<CTxIn>& vecTxInRet, CAmount& nValueRet, int nPrivateSendRoundsMin, int nPrivateSendRoundsMax) const;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user