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;
|
CAmount nMaxAmount = nBalanceNeedsAnonymized;
|
||||||
|
|
||||||
// Try to match their denominations if possible, select exact number of denominations
|
// 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));
|
LogPrintf("CPrivateSendClientSession::JoinExistingQueue -- Couldn't match %d denominations %d (%s)\n", vecBits.front(), dsq.nDenom, CPrivateSend::GetDenominationsToString(dsq.nDenom));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -1180,25 +1180,45 @@ bool CPrivateSendClientSession::SubmitDenominate(CConnman& connman)
|
|||||||
std::string strError;
|
std::string strError;
|
||||||
std::vector<CTxDSIn> vecTxDSInRet;
|
std::vector<CTxDSIn> vecTxDSInRet;
|
||||||
std::vector<CTxOut> vecTxOutRet;
|
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
|
// Submit transaction to the pool if we get here
|
||||||
if (privateSendClient.nLiquidityProvider) {
|
if (fMixLowest) {
|
||||||
// Try to use only inputs with the same number of rounds starting from the lowest number of rounds possible
|
// Try to use only inputs with the same number of rounds, from low to high
|
||||||
for(int i = 0; i< privateSendClient.nPrivateSendRounds; i++) {
|
while (true) {
|
||||||
if(PrepareDenominate(i, i + 1, strError, vecTxDSInRet, vecTxOutRet)) {
|
for(int i = nRoundStart; i < privateSendClient.nPrivateSendRounds; i++) {
|
||||||
LogPrintf("CPrivateSendClientSession::SubmitDenominate -- Running PrivateSend denominate for %d rounds, success\n", i);
|
if(PrepareDenominate(i, i + 1, strError, vecTxDSInRet, vecTxOutRet)) {
|
||||||
return SendDenominate(vecTxDSInRet, vecTxOutRet, connman);
|
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);
|
||||||
}
|
}
|
||||||
LogPrint("privatesend", "CPrivateSendClientSession::SubmitDenominate -- Running PrivateSend denominate for %d rounds, error: %s\n", i, strError);
|
if (nRoundStart == 0) break;
|
||||||
|
nRoundStart = 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Try to use only inputs with the same number of rounds starting from the highest number of rounds possible
|
// Try to use only inputs with the same number of rounds, from high to low
|
||||||
for(int i = privateSendClient.nPrivateSendRounds; i > 0; i--) {
|
while (true) {
|
||||||
if(PrepareDenominate(i - 1, i, strError, vecTxDSInRet, vecTxOutRet)) {
|
for(int i = nRoundStart; i > 0; i--) {
|
||||||
LogPrintf("CPrivateSendClientSession::SubmitDenominate -- Running PrivateSend denominate for %d rounds, success\n", i);
|
if(PrepareDenominate(i - 1, i, strError, vecTxDSInRet, vecTxOutRet)) {
|
||||||
return SendDenominate(vecTxDSInRet, vecTxOutRet, connman);
|
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);
|
||||||
}
|
}
|
||||||
LogPrint("privatesend", "CPrivateSendClientSession::SubmitDenominate -- Running PrivateSend denominate for %d rounds, error: %s\n", i, strError);
|
if (nRoundStart == privateSendClient.nPrivateSendRounds) break;
|
||||||
|
nRoundStart = privateSendClient.nPrivateSendRounds;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1251,7 +1271,7 @@ bool CPrivateSendClientSession::PrepareDenominate(int nMinRounds, int nMaxRounds
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
std::vector<CAmount> vecStandardDenoms = CPrivateSend::GetStandardDenominations();
|
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) {
|
if (nMinRounds >= 0 && !fSelected) {
|
||||||
strErrorRet = "Can't select current denominated inputs";
|
strErrorRet = "Can't select current denominated inputs";
|
||||||
return false;
|
return false;
|
||||||
|
@ -3007,8 +3007,10 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, bool ov
|
|||||||
return true;
|
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();
|
vecTxDSInRet.clear();
|
||||||
vCoinsRet.clear();
|
vCoinsRet.clear();
|
||||||
nValueRet = 0;
|
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
|
// masternode-like input should not be selected by AvailableCoins now anyway
|
||||||
//if(out.tx->vout[out.i].nValue == 1000*COIN) continue;
|
//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){
|
if(nValueRet + out.tx->tx->vout[out.i].nValue <= nValueMax){
|
||||||
|
|
||||||
CTxIn txin = CTxIn(out.tx->GetHash(), out.i);
|
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));
|
vecTxDSInRet.push_back(CTxDSIn(txin, out.tx->tx->vout[out.i].scriptPubKey));
|
||||||
vCoinsRet.push_back(out);
|
vCoinsRet.push_back(out);
|
||||||
nDenomResult |= 1 << nBit;
|
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;
|
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;
|
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
|
// 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 GetCollateralTxDSIn(CTxDSIn& txdsinRet, CAmount& nValueRet) const;
|
||||||
bool SelectCoinsDark(CAmount nValueMin, CAmount nValueMax, std::vector<CTxIn>& vecTxInRet, CAmount& nValueRet, int nPrivateSendRoundsMin, int nPrivateSendRoundsMax) 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