-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Add more variance to coin selection in PS mixing #2261
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
0a8a127
1dc7e9a
8025de8
6eb1cc5
e0b0f4e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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,25 +1180,45 @@ 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(PrepareDenominate(i, i + 1, strError, vecTxDSInRet, vecTxOutRet)) { | ||
| LogPrintf("CPrivateSendClientSession::SubmitDenominate -- Running PrivateSend denominate for %d rounds, success\n", i); | ||
| return SendDenominate(vecTxDSInRet, vecTxOutRet, connman); | ||
| 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); | ||
| } | ||
| 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--) { | ||
| 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); | ||
| // 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)) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| 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; | ||
| } | ||
| 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; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But will not this lead to the situation that most mixing transactions will contain only 1 input from each participant?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, it shouldn't. Even if it does that's fine for privacy. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, it's very fine for privacy. But mixing time will increase significantly. And mixing will cost much more.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This sounds like a valid concern. I'll have a look.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fees would go up, but I see no situation where a participant would only be able to submit one denom, maybe the first mix when they are all fresh out of create denoms There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @PastaPastaPasta not only after create denoms. What we have: in most cases ( After "create denoms" the participant will be able to provide from 1 to several inputs (depending on amount he is trying to mix - can be several "create denoms" Txs). And after every mixing round where participant will be able to provide more than 1 input, on the next round in most cases he will not be able to provide more than 1 input because all inputs with highest round will be from the same Tx. The number of inputs in this situation will always tends to one. |
||
| 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; | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for(->for (