Skip to content

Commit

Permalink
Alternative solution: pick rounds with the most inputs available to m…
Browse files Browse the repository at this point in the history
…ix first
  • Loading branch information
UdjinM6 committed Sep 15, 2018
1 parent 76599aa commit 617581e
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 34 deletions.
62 changes: 29 additions & 33 deletions src/privatesend-client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1167,17 +1167,6 @@ void CPrivateSendClientManager::ProcessPendingDsaRequest(CConnman& connman)

bool CPrivateSendClientSession::SubmitDenominate(CConnman& connman)
{
// This is just a local helper
auto GetStartRound = [](bool fMixLowest, bool fScanFromTheMiddle) -> int
{
if (fScanFromTheMiddle) {
return privateSendClient.nPrivateSendRounds / 2;
} else if (!fMixLowest) {
return privateSendClient.nPrivateSendRounds - 1;
}
return 0;
};

LOCK2(cs_main, pwalletMain->cs_wallet);

std::string strError;
Expand All @@ -1188,28 +1177,36 @@ bool CPrivateSendClientSession::SubmitDenominate(CConnman& connman)
return false;
}

// lean towards "highest" branch but still mix via "lowest" one someties
bool fMixLowest = privateSendClient.nLiquidityProvider || (GetRandInt(4) == 0);
// Try to use only inputs with the same number of rounds, from low to high, or vice versa
int nLoopStep = fMixLowest ? 1 : -1;
// 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 = GetStartRound(fMixLowest, fScanFromTheMiddle);
int nRoundEdge = GetStartRound(fMixLowest, false);
std::vector< std::pair<int, size_t> > vecInputsByRounds;
// Note: liqudity providers are fine whith whatever numner of inputs they've got
bool fDryRun = privateSendClient.nLiquidityProvider == 0;

// Submit transaction to the pool if we get here
while (true) {
for (int i = nRoundStart; i >= 0 && i < privateSendClient.nPrivateSendRounds; i += nLoopStep) {
if (PrepareDenominate(i, i, strError, vecPSInOutPairs, vecPSInOutPairsTmp)) {
LogPrintf("CPrivateSendClientSession::SubmitDenominate -- Running PrivateSend denominate for %d rounds, success\n", i);
for (int i = 0; i < privateSendClient.nPrivateSendRounds; i++) {
if (PrepareDenominate(i, i, strError, vecPSInOutPairs, vecPSInOutPairsTmp, fDryRun)) {
LogPrintf("CPrivateSendClientSession::SubmitDenominate -- Running PrivateSend denominate for %d rounds, success\n", i);
if (!fDryRun) {
return SendDenominate(vecPSInOutPairsTmp, connman);
}
vecInputsByRounds.emplace_back(i, vecPSInOutPairsTmp.size());
} else {
LogPrint("privatesend", "CPrivateSendClientSession::SubmitDenominate -- Running PrivateSend denominate for %d rounds, error: %s\n", i, strError);
}
if (nRoundStart == nRoundEdge) break;
nRoundStart = nRoundEdge;
}

// more inputs first, for equal input count prefer the one with less rounds
std::sort(vecInputsByRounds.begin(), vecInputsByRounds.end(), [](const auto& a, const auto& b) {
return a.second > b.second || (a.second == b.second && a.first < b.first);
});

LogPrint("privatesend", "vecInputsByRounds for denom %d\n", nSessionDenom);
for (const auto& pair : vecInputsByRounds) {
LogPrint("privatesend", "vecInputsByRounds: rounds: %d, inputs: %d\n", pair.first, pair.second);
}

int nRounds = vecInputsByRounds.begin()->first;
if (PrepareDenominate(nRounds, nRounds, strError, vecPSInOutPairs, vecPSInOutPairsTmp)) {
LogPrintf("CPrivateSendClientSession::SubmitDenominate -- Running PrivateSend denominate for %d rounds, success\n", nRounds);
return SendDenominate(vecPSInOutPairsTmp, connman);
}

// We failed? That's strange but let's just make final attempt and try to mix everything
Expand Down Expand Up @@ -1259,7 +1256,7 @@ bool CPrivateSendClientSession::SelectDenominate(std::string& strErrorRet, std::
return true;
}

bool CPrivateSendClientSession::PrepareDenominate(int nMinRounds, int nMaxRounds, std::string& strErrorRet, const std::vector< std::pair<CTxDSIn, CTxOut> >& vecPSInOutPairsIn, std::vector< std::pair<CTxDSIn, CTxOut> >& vecPSInOutPairsRet)
bool CPrivateSendClientSession::PrepareDenominate(int nMinRounds, int nMaxRounds, std::string& strErrorRet, const std::vector< std::pair<CTxDSIn, CTxOut> >& vecPSInOutPairsIn, std::vector< std::pair<CTxDSIn, CTxOut> >& vecPSInOutPairsRet, bool fDryRun)
{
std::vector<int> vecBits;
if (!CPrivateSend::GetDenominationsBits(nSessionDenom, vecBits)) {
Expand Down Expand Up @@ -1292,7 +1289,7 @@ bool CPrivateSendClientSession::PrepareDenominate(int nMinRounds, int nMaxRounds
if (vecSteps[nBit] >= nStepsMax) break;
CAmount nValueDenom = vecStandardDenoms[nBit];
if (pair.second.nValue == nValueDenom) {
CScript scriptDenom = keyHolderStorage.AddKey(pwalletMain);
CScript scriptDenom = fDryRun ? CScript() : keyHolderStorage.AddKey(pwalletMain);
vecPSInOutPairsRet.emplace_back(pair.first, CTxOut(nValueDenom, scriptDenom));
fFound = true;
nDenomResult |= 1 << nBit;
Expand All @@ -1301,8 +1298,8 @@ bool CPrivateSendClientSession::PrepareDenominate(int nMinRounds, int nMaxRounds
break;
}
}
if (!fFound) {
// unlock unused coins
if (!fFound || fDryRun) {
// unlock unused coins and if we are not going to mix right away
pwalletMain->UnlockCoin(pair.first.prevout);
}
}
Expand All @@ -1317,7 +1314,6 @@ bool CPrivateSendClientSession::PrepareDenominate(int nMinRounds, int nMaxRounds
return false;
}

// We also do not care about full amount as long as we have right denominations
return true;
}

Expand Down
2 changes: 1 addition & 1 deletion src/privatesend-client.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ class CPrivateSendClientSession : public CPrivateSendBaseSession
/// step 0: select denominated inputs and txouts
bool SelectDenominate(std::string& strErrorRet, std::vector< std::pair<CTxDSIn, CTxOut> >& vecPSInOutPairsRet);
/// step 1: prepare denominated inputs and outputs
bool PrepareDenominate(int nMinRounds, int nMaxRounds, std::string& strErrorRet, const std::vector< std::pair<CTxDSIn, CTxOut> >& vecPSInOutPairsIn, std::vector< std::pair<CTxDSIn, CTxOut> >& vecPSInOutPairsRet);
bool PrepareDenominate(int nMinRounds, int nMaxRounds, std::string& strErrorRet, const std::vector< std::pair<CTxDSIn, CTxOut> >& vecPSInOutPairsIn, std::vector< std::pair<CTxDSIn, CTxOut> >& vecPSInOutPairsRet, bool fDryRun = false);
/// step 2: send denominated inputs and outputs prepared in step 1
bool SendDenominate(const std::vector< std::pair<CTxDSIn, CTxOut> >& vecPSInOutPairsIn, CConnman& connman);

Expand Down

0 comments on commit 617581e

Please sign in to comment.