privatesend: Implement multiwallet support

With the introduction of better mutliwallet support, privatesend only worked for your first wallet. This commit implements multiwallet for privatesend such that the wallet you start the mixing from is the wallet mixing will occur in.

Signed-off-by: pasta <pasta@dashboost.org>
This commit is contained in:
pasta 2020-07-12 00:52:25 -05:00
parent c240e70e38
commit 8acba46205
No known key found for this signature in database
GPG Key ID: 52527BEDABE87984
7 changed files with 135 additions and 88 deletions

View File

@ -32,7 +32,7 @@ void CPrivateSendClientManager::ProcessMessage(CNode* pfrom, const std::string&
if (!CheckDiskSpace()) { if (!CheckDiskSpace()) {
ResetPool(); ResetPool();
fPrivateSendRunning = false; StopMixing();
LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientManager::ProcessMessage -- Not enough disk space, disabling PrivateSend.\n"); LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientManager::ProcessMessage -- Not enough disk space, disabling PrivateSend.\n");
return; return;
} }
@ -225,6 +225,24 @@ void CPrivateSendClientSession::ProcessMessage(CNode* pfrom, const std::string&
} }
} }
bool CPrivateSendClientManager::StartMixing(CWallet* pwallet) {
if (IsMixing()) {
return false;
}
assert(pwallet != nullptr);
mixingWallet = pwallet;
return true;
}
void CPrivateSendClientManager::StopMixing() {
mixingWallet = nullptr;
}
bool CPrivateSendClientManager::IsMixing() const
{
return mixingWallet != nullptr;
}
void CPrivateSendClientSession::ResetPool() void CPrivateSendClientSession::ResetPool()
{ {
txMyCollateral = CMutableTransaction(); txMyCollateral = CMutableTransaction();
@ -261,13 +279,13 @@ void CPrivateSendClientSession::UnlockCoins()
if (!privateSendClient.fEnablePrivateSend) return; if (!privateSendClient.fEnablePrivateSend) return;
while (true) { while (true) {
TRY_LOCK(GetWallets()[0]->cs_wallet, lockWallet); TRY_LOCK(GetMixingWallet()->cs_wallet, lockWallet);
if (!lockWallet) { if (!lockWallet) {
MilliSleep(50); MilliSleep(50);
continue; continue;
} }
for (const auto& outpoint : vecOutPointLocked) for (const auto& outpoint : vecOutPointLocked)
GetWallets()[0]->UnlockCoin(outpoint); GetMixingWallet()->UnlockCoin(outpoint);
break; break;
} }
@ -355,6 +373,17 @@ bool CPrivateSendClientManager::GetMixingMasternodesInfo(std::vector<CDeterminis
return !vecDmnsRet.empty(); return !vecDmnsRet.empty();
} }
CWallet* CPrivateSendClientSession::GetMixingWallet() const
{
return privateSendClient.GetMixingWallet();
}
CWallet* CPrivateSendClientManager::GetMixingWallet() const
{
assert(mixingWallet != nullptr);
return mixingWallet;
}
// //
// Check session timeouts // Check session timeouts
// //
@ -400,7 +429,7 @@ void CPrivateSendClientManager::CheckTimeout()
CheckQueue(); CheckQueue();
if (!fEnablePrivateSend || !fPrivateSendRunning) return; if (!fEnablePrivateSend || !IsMixing()) return;
LOCK(cs_deqsessions); LOCK(cs_deqsessions);
for (auto& session : deqSessions) { for (auto& session : deqSessions) {
@ -524,7 +553,7 @@ void CPrivateSendClientSession::ProcessPoolStateUpdate(CPrivateSendStatusUpdate
// //
bool CPrivateSendClientSession::SignFinalTransaction(const CTransaction& finalTransactionNew, CNode* pnode, CConnman& connman) bool CPrivateSendClientSession::SignFinalTransaction(const CTransaction& finalTransactionNew, CNode* pnode, CConnman& connman)
{ {
if (!privateSendClient.fEnablePrivateSend || !privateSendClient.fPrivateSendRunning) return false; if (!privateSendClient.fEnablePrivateSend || !privateSendClient.IsMixing()) return false;
if (fMasternodeMode || pnode == nullptr) return false; if (fMasternodeMode || pnode == nullptr) return false;
if (!mixingMasternode) return false; if (!mixingMasternode) return false;
@ -604,7 +633,7 @@ bool CPrivateSendClientSession::SignFinalTransaction(const CTransaction& finalTr
return false; return false;
} }
const CKeyStore& keystore = *GetWallets()[0]; const CKeyStore& keystore = *GetMixingWallet();
LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::%s -- Signing my input %i\n", __func__, nMyInputIndex); LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::%s -- Signing my input %i\n", __func__, nMyInputIndex);
// TODO we're using amount=0 here but we should use the correct amount. This works because Dash ignores the amount while signing/verifying (only used in Bitcoin/Segwit) // TODO we're using amount=0 here but we should use the correct amount. This works because Dash ignores the amount while signing/verifying (only used in Bitcoin/Segwit)
@ -673,14 +702,14 @@ bool CPrivateSendClientManager::WaitForAnotherBlock()
bool CPrivateSendClientManager::CheckAutomaticBackup() bool CPrivateSendClientManager::CheckAutomaticBackup()
{ {
if (!fEnablePrivateSend || !fPrivateSendRunning) return false; if (!fEnablePrivateSend || !IsMixing()) return false;
switch (nWalletBackups) { switch (nWalletBackups) {
case 0: case 0:
LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientManager::CheckAutomaticBackup -- Automatic backups disabled, no mixing available.\n"); LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientManager::CheckAutomaticBackup -- Automatic backups disabled, no mixing available.\n");
strAutoDenomResult = _("Automatic backups disabled") + ", " + _("no mixing available."); strAutoDenomResult = _("Automatic backups disabled") + ", " + _("no mixing available.");
fPrivateSendRunning = false; // stop mixing StopMixing();
GetWallets()[0]->nKeysLeftSinceAutoBackup = 0; // no backup, no "keys since last backup" GetMixingWallet()->nKeysLeftSinceAutoBackup = 0; // no backup, no "keys since last backup"
return false; return false;
case -1: case -1:
// Automatic backup failed, nothing else we can do until user fixes the issue manually. // Automatic backup failed, nothing else we can do until user fixes the issue manually.
@ -698,24 +727,24 @@ bool CPrivateSendClientManager::CheckAutomaticBackup()
return false; return false;
} }
if (GetWallets()[0]->nKeysLeftSinceAutoBackup < PRIVATESEND_KEYS_THRESHOLD_STOP) { if (GetMixingWallet()->nKeysLeftSinceAutoBackup < PRIVATESEND_KEYS_THRESHOLD_STOP) {
// We should never get here via mixing itself but probably something else is still actively using keypool // We should never get here via mixing itself but probably something else is still actively using keypool
LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientManager::CheckAutomaticBackup -- Very low number of keys left: %d, no mixing available.\n", GetWallets()[0]->nKeysLeftSinceAutoBackup); LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientManager::CheckAutomaticBackup -- Very low number of keys left: %d, no mixing available.\n", GetMixingWallet()->nKeysLeftSinceAutoBackup);
strAutoDenomResult = strprintf(_("Very low number of keys left: %d") + ", " + _("no mixing available."), GetWallets()[0]->nKeysLeftSinceAutoBackup); strAutoDenomResult = strprintf(_("Very low number of keys left: %d") + ", " + _("no mixing available."), GetMixingWallet()->nKeysLeftSinceAutoBackup);
// It's getting really dangerous, stop mixing // It's getting really dangerous, stop mixing
fPrivateSendRunning = false; StopMixing();
return false; return false;
} else if (GetWallets()[0]->nKeysLeftSinceAutoBackup < PRIVATESEND_KEYS_THRESHOLD_WARNING) { } else if (GetMixingWallet()->nKeysLeftSinceAutoBackup < PRIVATESEND_KEYS_THRESHOLD_WARNING) {
// Low number of keys left but it's still more or less safe to continue // Low number of keys left but it's still more or less safe to continue
LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientManager::CheckAutomaticBackup -- Very low number of keys left: %d\n", GetWallets()[0]->nKeysLeftSinceAutoBackup); LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientManager::CheckAutomaticBackup -- Very low number of keys left: %d\n", GetMixingWallet()->nKeysLeftSinceAutoBackup);
strAutoDenomResult = strprintf(_("Very low number of keys left: %d"), GetWallets()[0]->nKeysLeftSinceAutoBackup); strAutoDenomResult = strprintf(_("Very low number of keys left: %d"), GetMixingWallet()->nKeysLeftSinceAutoBackup);
if (fCreateAutoBackups) { if (fCreateAutoBackups) {
LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientManager::CheckAutomaticBackup -- Trying to create new backup.\n"); LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientManager::CheckAutomaticBackup -- Trying to create new backup.\n");
std::string warningString; std::string warningString;
std::string errorString; std::string errorString;
if (!GetWallets()[0]->AutoBackupWallet("", warningString, errorString)) { if (!GetMixingWallet()->AutoBackupWallet("", warningString, errorString)) {
if (!warningString.empty()) { if (!warningString.empty()) {
// There were some issues saving backup but yet more or less safe to continue // There were some issues saving backup but yet more or less safe to continue
LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientManager::CheckAutomaticBackup -- WARNING! Something went wrong on automatic backup: %s\n", warningString); LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientManager::CheckAutomaticBackup -- WARNING! Something went wrong on automatic backup: %s\n", warningString);
@ -733,7 +762,7 @@ bool CPrivateSendClientManager::CheckAutomaticBackup()
} }
} }
LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientManager::CheckAutomaticBackup -- Keys left since latest backup: %d\n", GetWallets()[0]->nKeysLeftSinceAutoBackup); LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientManager::CheckAutomaticBackup -- Keys left since latest backup: %d\n", GetMixingWallet()->nKeysLeftSinceAutoBackup);
return true; return true;
} }
@ -751,15 +780,15 @@ bool CPrivateSendClientSession::DoAutomaticDenominating(CConnman& connman, bool
return false; return false;
} }
if (!privateSendClient.fEnablePrivateSend || !privateSendClient.fPrivateSendRunning) return false; if (!privateSendClient.fEnablePrivateSend || !privateSendClient.IsMixing()) return false;
CAmount nBalanceNeedsAnonymized; CAmount nBalanceNeedsAnonymized;
{ {
LOCK2(cs_main, mempool.cs); LOCK2(cs_main, mempool.cs);
LOCK(GetWallets()[0]->cs_wallet); LOCK(GetMixingWallet()->cs_wallet);
if (!fDryRun && GetWallets()[0]->IsLocked(true)) { if (!fDryRun && GetMixingWallet()->IsLocked(true)) {
strAutoDenomResult = _("Wallet is locked."); strAutoDenomResult = _("Wallet is locked.");
return false; return false;
} }
@ -783,7 +812,7 @@ bool CPrivateSendClientSession::DoAutomaticDenominating(CConnman& connman, bool
} }
// check if there is anything left to do // check if there is anything left to do
CAmount nBalanceAnonymized = GetWallets()[0]->GetAnonymizedBalance(); CAmount nBalanceAnonymized = GetMixingWallet()->GetAnonymizedBalance();
nBalanceNeedsAnonymized = privateSendClient.nPrivateSendAmount*COIN - nBalanceAnonymized; nBalanceNeedsAnonymized = privateSendClient.nPrivateSendAmount*COIN - nBalanceAnonymized;
if (nBalanceNeedsAnonymized < 0) { if (nBalanceNeedsAnonymized < 0) {
@ -795,13 +824,13 @@ bool CPrivateSendClientSession::DoAutomaticDenominating(CConnman& connman, bool
CAmount nValueMin = CPrivateSend::GetSmallestDenomination(); CAmount nValueMin = CPrivateSend::GetSmallestDenomination();
// if there are no confirmed DS collateral inputs yet // if there are no confirmed DS collateral inputs yet
if (!GetWallets()[0]->HasCollateralInputs()) { if (!GetMixingWallet()->HasCollateralInputs()) {
// should have some additional amount for them // should have some additional amount for them
nValueMin += CPrivateSend::GetMaxCollateralAmount(); nValueMin += CPrivateSend::GetMaxCollateralAmount();
} }
// including denoms but applying some restrictions // including denoms but applying some restrictions
CAmount nBalanceAnonymizable = GetWallets()[0]->GetAnonymizableBalance(); CAmount nBalanceAnonymizable = GetMixingWallet()->GetAnonymizableBalance();
// mixable balance is way too small // mixable balance is way too small
if (nBalanceAnonymizable < nValueMin) { if (nBalanceAnonymizable < nValueMin) {
@ -811,10 +840,10 @@ bool CPrivateSendClientSession::DoAutomaticDenominating(CConnman& connman, bool
} }
// excluding denoms // excluding denoms
CAmount nBalanceAnonimizableNonDenom = GetWallets()[0]->GetAnonymizableBalance(true); CAmount nBalanceAnonimizableNonDenom = GetMixingWallet()->GetAnonymizableBalance(true);
// denoms // denoms
CAmount nBalanceDenominatedConf = GetWallets()[0]->GetDenominatedBalance(); CAmount nBalanceDenominatedConf = GetMixingWallet()->GetDenominatedBalance();
CAmount nBalanceDenominatedUnconf = GetWallets()[0]->GetDenominatedBalance(true); CAmount nBalanceDenominatedUnconf = GetMixingWallet()->GetDenominatedBalance(true);
CAmount nBalanceDenominated = nBalanceDenominatedConf + nBalanceDenominatedUnconf; CAmount nBalanceDenominated = nBalanceDenominatedConf + nBalanceDenominatedUnconf;
CAmount nBalanceToDenominate = privateSendClient.nPrivateSendAmount * COIN - nBalanceDenominated; CAmount nBalanceToDenominate = privateSendClient.nPrivateSendAmount * COIN - nBalanceDenominated;
@ -863,8 +892,8 @@ bool CPrivateSendClientSession::DoAutomaticDenominating(CConnman& connman, bool
} }
//check if we have the collateral sized inputs //check if we have the collateral sized inputs
if (!GetWallets()[0]->HasCollateralInputs()) { if (!GetMixingWallet()->HasCollateralInputs()) {
return !GetWallets()[0]->HasCollateralInputs(false) && MakeCollateralAmounts(connman); return !GetMixingWallet()->HasCollateralInputs(false) && MakeCollateralAmounts(connman);
} }
if (nSessionID) { if (nSessionID) {
@ -888,14 +917,14 @@ bool CPrivateSendClientSession::DoAutomaticDenominating(CConnman& connman, bool
//check our collateral and create new if needed //check our collateral and create new if needed
std::string strReason; std::string strReason;
if (txMyCollateral == CMutableTransaction()) { if (txMyCollateral == CMutableTransaction()) {
if (!GetWallets()[0]->CreateCollateralTransaction(txMyCollateral, strReason)) { if (!GetMixingWallet()->CreateCollateralTransaction(txMyCollateral, strReason)) {
LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::DoAutomaticDenominating -- create collateral error:%s\n", strReason); LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::DoAutomaticDenominating -- create collateral error:%s\n", strReason);
return false; return false;
} }
} else { } else {
if (!CPrivateSend::IsCollateralValid(txMyCollateral)) { if (!CPrivateSend::IsCollateralValid(txMyCollateral)) {
LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::DoAutomaticDenominating -- invalid collateral, recreating...\n"); LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::DoAutomaticDenominating -- invalid collateral, recreating...\n");
if (!GetWallets()[0]->CreateCollateralTransaction(txMyCollateral, strReason)) { if (!GetMixingWallet()->CreateCollateralTransaction(txMyCollateral, strReason)) {
LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::DoAutomaticDenominating -- create collateral error: %s\n", strReason); LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::DoAutomaticDenominating -- create collateral error: %s\n", strReason);
return false; return false;
} }
@ -903,10 +932,10 @@ bool CPrivateSendClientSession::DoAutomaticDenominating(CConnman& connman, bool
} }
// lock the funds we're going to use for our collateral // lock the funds we're going to use for our collateral
for (const auto& txin : txMyCollateral.vin) { for (const auto& txin : txMyCollateral.vin) {
GetWallets()[0]->LockCoin(txin.prevout); GetMixingWallet()->LockCoin(txin.prevout);
vecOutPointLocked.push_back(txin.prevout); vecOutPointLocked.push_back(txin.prevout);
} }
} // LOCK2(cs_main, GetWallets()[0]->cs_wallet); } // LOCK2(cs_main, GetMixingWallet()->cs_wallet);
// Always attempt to join an existing queue // Always attempt to join an existing queue
if (JoinExistingQueue(nBalanceNeedsAnonymized, connman)) { if (JoinExistingQueue(nBalanceNeedsAnonymized, connman)) {
@ -923,14 +952,14 @@ bool CPrivateSendClientSession::DoAutomaticDenominating(CConnman& connman, bool
bool CPrivateSendClientManager::DoAutomaticDenominating(CConnman& connman, bool fDryRun) bool CPrivateSendClientManager::DoAutomaticDenominating(CConnman& connman, bool fDryRun)
{ {
if (fMasternodeMode) return false; // no client-side mixing on masternodes if (fMasternodeMode) return false; // no client-side mixing on masternodes
if (!fEnablePrivateSend || !fPrivateSendRunning) return false; if (!fEnablePrivateSend || !IsMixing()) return false;
if (!masternodeSync.IsBlockchainSynced()) { if (!masternodeSync.IsBlockchainSynced()) {
strAutoDenomResult = _("Can't mix while sync in progress."); strAutoDenomResult = _("Can't mix while sync in progress.");
return false; return false;
} }
if (!fDryRun && GetWallets()[0]->IsLocked(true)) { if (!fDryRun && GetMixingWallet()->IsLocked(true)) {
strAutoDenomResult = _("Wallet is locked."); strAutoDenomResult = _("Wallet is locked.");
return false; return false;
} }
@ -1013,7 +1042,7 @@ CDeterministicMNCPtr CPrivateSendClientManager::GetRandomNotUsedMasternode()
bool CPrivateSendClientSession::JoinExistingQueue(CAmount nBalanceNeedsAnonymized, CConnman& connman) bool CPrivateSendClientSession::JoinExistingQueue(CAmount nBalanceNeedsAnonymized, CConnman& connman)
{ {
if (!privateSendClient.fEnablePrivateSend || !privateSendClient.fPrivateSendRunning) return false; if (!privateSendClient.fEnablePrivateSend || !privateSendClient.IsMixing()) return false;
auto mnList = deterministicMNManager->GetListAtChainTip(); auto mnList = deterministicMNManager->GetListAtChainTip();
@ -1042,7 +1071,7 @@ bool CPrivateSendClientSession::JoinExistingQueue(CAmount nBalanceNeedsAnonymize
std::vector<std::pair<CTxDSIn, CTxOut> > vecPSInOutPairsTmp; std::vector<std::pair<CTxDSIn, CTxOut> > vecPSInOutPairsTmp;
// 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 (!GetWallets()[0]->SelectPSInOutPairsByDenominations(dsq.nDenom, nBalanceNeedsAnonymized, vecPSInOutPairsTmp)) { if (!GetMixingWallet()->SelectPSInOutPairsByDenominations(dsq.nDenom, nBalanceNeedsAnonymized, vecPSInOutPairsTmp)) {
LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::JoinExistingQueue -- Couldn't match denomination %d (%s)\n", dsq.nDenom, CPrivateSend::DenominationToString(dsq.nDenom)); LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::JoinExistingQueue -- Couldn't match denomination %d (%s)\n", dsq.nDenom, CPrivateSend::DenominationToString(dsq.nDenom));
continue; continue;
} }
@ -1072,7 +1101,7 @@ bool CPrivateSendClientSession::JoinExistingQueue(CAmount nBalanceNeedsAnonymize
bool CPrivateSendClientSession::StartNewQueue(CAmount nBalanceNeedsAnonymized, CConnman& connman) bool CPrivateSendClientSession::StartNewQueue(CAmount nBalanceNeedsAnonymized, CConnman& connman)
{ {
if (!privateSendClient.fEnablePrivateSend || !privateSendClient.fPrivateSendRunning) return false; if (!privateSendClient.fEnablePrivateSend || !privateSendClient.IsMixing()) return false;
if (nBalanceNeedsAnonymized <= 0) return false; if (nBalanceNeedsAnonymized <= 0) return false;
int nTries = 0; int nTries = 0;
@ -1081,7 +1110,7 @@ bool CPrivateSendClientSession::StartNewQueue(CAmount nBalanceNeedsAnonymized, C
// find available denominated amounts // find available denominated amounts
std::set<CAmount> setAmounts; std::set<CAmount> setAmounts;
if (!GetWallets()[0]->SelectDenominatedAmounts(nBalanceNeedsAnonymized, setAmounts)) { if (!GetMixingWallet()->SelectDenominatedAmounts(nBalanceNeedsAnonymized, setAmounts)) {
// this should never happen // this should never happen
LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::StartNewQueue -- Can't mix: no compatible inputs found!\n"); LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::StartNewQueue -- Can't mix: no compatible inputs found!\n");
strAutoDenomResult = _("Can't mix: no compatible inputs found!"); strAutoDenomResult = _("Can't mix: no compatible inputs found!");
@ -1187,7 +1216,7 @@ void CPrivateSendClientManager::ProcessPendingDsaRequest(CConnman& connman)
bool CPrivateSendClientSession::SubmitDenominate(CConnman& connman) bool CPrivateSendClientSession::SubmitDenominate(CConnman& connman)
{ {
LOCK2(cs_main, mempool.cs); LOCK2(cs_main, mempool.cs);
LOCK(GetWallets()[0]->cs_wallet); LOCK(GetMixingWallet()->cs_wallet);
std::string strError; std::string strError;
std::vector<std::pair<CTxDSIn, CTxOut> > vecPSInOutPairs, vecPSInOutPairsTmp; std::vector<std::pair<CTxDSIn, CTxOut> > vecPSInOutPairs, vecPSInOutPairsTmp;
@ -1238,9 +1267,9 @@ bool CPrivateSendClientSession::SubmitDenominate(CConnman& connman)
bool CPrivateSendClientSession::SelectDenominate(std::string& strErrorRet, std::vector<std::pair<CTxDSIn, CTxOut> >& vecPSInOutPairsRet) bool CPrivateSendClientSession::SelectDenominate(std::string& strErrorRet, std::vector<std::pair<CTxDSIn, CTxOut> >& vecPSInOutPairsRet)
{ {
if (!privateSendClient.fEnablePrivateSend || !privateSendClient.fPrivateSendRunning) return false; if (!privateSendClient.fEnablePrivateSend || !privateSendClient.IsMixing()) return false;
if (GetWallets()[0]->IsLocked(true)) { if (GetMixingWallet()->IsLocked(true)) {
strErrorRet = "Wallet locked, unable to create transaction!"; strErrorRet = "Wallet locked, unable to create transaction!";
return false; return false;
} }
@ -1252,7 +1281,7 @@ bool CPrivateSendClientSession::SelectDenominate(std::string& strErrorRet, std::
vecPSInOutPairsRet.clear(); vecPSInOutPairsRet.clear();
bool fSelected = GetWallets()[0]->SelectPSInOutPairsByDenominations(nSessionDenom, CPrivateSend::GetMaxPoolAmount(), vecPSInOutPairsRet); bool fSelected = GetMixingWallet()->SelectPSInOutPairsByDenominations(nSessionDenom, CPrivateSend::GetMaxPoolAmount(), vecPSInOutPairsRet);
if (!fSelected) { if (!fSelected) {
strErrorRet = "Can't select current denominated inputs"; strErrorRet = "Can't select current denominated inputs";
return false; return false;
@ -1264,7 +1293,7 @@ bool CPrivateSendClientSession::SelectDenominate(std::string& strErrorRet, std::
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) 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)
{ {
AssertLockHeld(cs_main); AssertLockHeld(cs_main);
AssertLockHeld(GetWallets()[0]->cs_wallet); AssertLockHeld(GetMixingWallet()->cs_wallet);
if (!CPrivateSend::IsValidDenomination(nSessionDenom)) { if (!CPrivateSend::IsValidDenomination(nSessionDenom)) {
strErrorRet = "Incorrect session denom"; strErrorRet = "Incorrect session denom";
@ -1295,7 +1324,7 @@ bool CPrivateSendClientSession::PrepareDenominate(int nMinRounds, int nMaxRounds
++nSteps; ++nSteps;
continue; continue;
} }
scriptDenom = keyHolderStorage.AddKey(GetWallets()[0]); scriptDenom = keyHolderStorage.AddKey(GetMixingWallet());
} }
vecPSInOutPairsRet.emplace_back(pair.first, CTxOut(nDenomAmount, scriptDenom)); vecPSInOutPairsRet.emplace_back(pair.first, CTxOut(nDenomAmount, scriptDenom));
// step is complete // step is complete
@ -1313,7 +1342,7 @@ bool CPrivateSendClientSession::PrepareDenominate(int nMinRounds, int nMaxRounds
} }
for (const auto& pair : vecPSInOutPairsRet) { for (const auto& pair : vecPSInOutPairsRet) {
GetWallets()[0]->LockCoin(pair.first.prevout); GetMixingWallet()->LockCoin(pair.first.prevout);
vecOutPointLocked.push_back(pair.first.prevout); vecOutPointLocked.push_back(pair.first.prevout);
} }
@ -1323,17 +1352,17 @@ bool CPrivateSendClientSession::PrepareDenominate(int nMinRounds, int nMaxRounds
// Create collaterals by looping through inputs grouped by addresses // Create collaterals by looping through inputs grouped by addresses
bool CPrivateSendClientSession::MakeCollateralAmounts(CConnman& connman) bool CPrivateSendClientSession::MakeCollateralAmounts(CConnman& connman)
{ {
if (!privateSendClient.fEnablePrivateSend || !privateSendClient.fPrivateSendRunning) return false; if (!privateSendClient.fEnablePrivateSend || !privateSendClient.IsMixing()) return false;
LOCK2(cs_main, mempool.cs); LOCK2(cs_main, mempool.cs);
LOCK(GetWallets()[0]->cs_wallet); LOCK(GetMixingWallet()->cs_wallet);
// NOTE: We do not allow txes larger than 100kB, so we have to limit number of inputs here. // NOTE: We do not allow txes larger than 100kB, so we have to limit number of inputs here.
// We still want to consume a lot of inputs to avoid creating only smaller denoms though. // We still want to consume a lot of inputs to avoid creating only smaller denoms though.
// Knowing that each CTxIn is at least 148b big, 400 inputs should take 400 x ~148b = ~60kB. // Knowing that each CTxIn is at least 148b big, 400 inputs should take 400 x ~148b = ~60kB.
// This still leaves more than enough room for another data of typical MakeCollateralAmounts tx. // This still leaves more than enough room for another data of typical MakeCollateralAmounts tx.
std::vector<CompactTallyItem> vecTally; std::vector<CompactTallyItem> vecTally;
if (!GetWallets()[0]->SelectCoinsGroupedByAddresses(vecTally, false, false, true, 400)) { if (!GetMixingWallet()->SelectCoinsGroupedByAddresses(vecTally, false, false, true, 400)) {
LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::MakeCollateralAmounts -- SelectCoinsGroupedByAddresses can't find any inputs!\n"); LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::MakeCollateralAmounts -- SelectCoinsGroupedByAddresses can't find any inputs!\n");
return false; return false;
} }
@ -1365,9 +1394,9 @@ bool CPrivateSendClientSession::MakeCollateralAmounts(const CompactTallyItem& ta
{ {
AssertLockHeld(cs_main); AssertLockHeld(cs_main);
AssertLockHeld(mempool.cs); AssertLockHeld(mempool.cs);
AssertLockHeld(GetWallets()[0]->cs_wallet); AssertLockHeld(GetMixingWallet()->cs_wallet);
if (!privateSendClient.fEnablePrivateSend || !privateSendClient.fPrivateSendRunning) return false; if (!privateSendClient.fEnablePrivateSend || !privateSendClient.IsMixing()) return false;
// Skip way too tiny amounts // Skip way too tiny amounts
if (tallyItem.nAmount < CPrivateSend::GetCollateralAmount()) { if (tallyItem.nAmount < CPrivateSend::GetCollateralAmount()) {
@ -1391,9 +1420,9 @@ bool CPrivateSendClientSession::MakeCollateralAmounts(const CompactTallyItem& ta
std::vector<CRecipient> vecSend; std::vector<CRecipient> vecSend;
// make our collateral address // make our collateral address
CReserveKey reservekeyCollateral(GetWallets()[0]); CReserveKey reservekeyCollateral(GetMixingWallet());
// make our change address // make our change address
CReserveKey reservekeyChange(GetWallets()[0]); CReserveKey reservekeyChange(GetMixingWallet());
CScript scriptCollateral; CScript scriptCollateral;
CPubKey vchPubKey; CPubKey vchPubKey;
@ -1422,7 +1451,7 @@ bool CPrivateSendClientSession::MakeCollateralAmounts(const CompactTallyItem& ta
coinControl.Select(outpoint); coinControl.Select(outpoint);
} }
bool fSuccess = GetWallets()[0]->CreateTransaction(vecSend, wtx, reservekeyChange, bool fSuccess = GetMixingWallet()->CreateTransaction(vecSend, wtx, reservekeyChange,
nFeeRet, nChangePosRet, strFail, coinControl); nFeeRet, nChangePosRet, strFail, coinControl);
if (!fSuccess) { if (!fSuccess) {
LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::MakeCollateralAmounts -- ONLY_NONDENOMINATED: %s\n", strFail); LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::MakeCollateralAmounts -- ONLY_NONDENOMINATED: %s\n", strFail);
@ -1430,7 +1459,7 @@ bool CPrivateSendClientSession::MakeCollateralAmounts(const CompactTallyItem& ta
if (fTryDenominated) { if (fTryDenominated) {
// Try to also use denominated coins (we can't mix denominated without collaterals anyway). // Try to also use denominated coins (we can't mix denominated without collaterals anyway).
coinControl.nCoinType = CoinType::ALL_COINS; coinControl.nCoinType = CoinType::ALL_COINS;
if (!GetWallets()[0]->CreateTransaction(vecSend, wtx, reservekeyChange, if (!GetMixingWallet()->CreateTransaction(vecSend, wtx, reservekeyChange,
nFeeRet, nChangePosRet, strFail, coinControl)) { nFeeRet, nChangePosRet, strFail, coinControl)) {
LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::MakeCollateralAmounts -- ALL_COINS Error: %s\n", strFail); LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::MakeCollateralAmounts -- ALL_COINS Error: %s\n", strFail);
reservekeyCollateral.ReturnKey(); reservekeyCollateral.ReturnKey();
@ -1449,7 +1478,7 @@ bool CPrivateSendClientSession::MakeCollateralAmounts(const CompactTallyItem& ta
// use the same nCachedLastSuccessBlock as for DS mixing to prevent race // use the same nCachedLastSuccessBlock as for DS mixing to prevent race
CValidationState state; CValidationState state;
if (!GetWallets()[0]->CommitTransaction(wtx, reservekeyChange, &connman, state)) { if (!GetMixingWallet()->CommitTransaction(wtx, reservekeyChange, &connman, state)) {
LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::MakeCollateralAmounts -- CommitTransaction failed! Reason given: %s\n", state.GetRejectReason()); LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::MakeCollateralAmounts -- CommitTransaction failed! Reason given: %s\n", state.GetRejectReason());
return false; return false;
} }
@ -1462,17 +1491,17 @@ bool CPrivateSendClientSession::MakeCollateralAmounts(const CompactTallyItem& ta
// Create denominations by looping through inputs grouped by addresses // Create denominations by looping through inputs grouped by addresses
bool CPrivateSendClientSession::CreateDenominated(CAmount nBalanceToDenominate, CConnman& connman) bool CPrivateSendClientSession::CreateDenominated(CAmount nBalanceToDenominate, CConnman& connman)
{ {
if (!privateSendClient.fEnablePrivateSend || !privateSendClient.fPrivateSendRunning) return false; if (!privateSendClient.fEnablePrivateSend || !privateSendClient.IsMixing()) return false;
LOCK2(cs_main, mempool.cs); LOCK2(cs_main, mempool.cs);
LOCK(GetWallets()[0]->cs_wallet); LOCK(GetMixingWallet()->cs_wallet);
// NOTE: We do not allow txes larger than 100kB, so we have to limit number of inputs here. // NOTE: We do not allow txes larger than 100kB, so we have to limit number of inputs here.
// We still want to consume a lot of inputs to avoid creating only smaller denoms though. // We still want to consume a lot of inputs to avoid creating only smaller denoms though.
// Knowing that each CTxIn is at least 148b big, 400 inputs should take 400 x ~148b = ~60kB. // Knowing that each CTxIn is at least 148b big, 400 inputs should take 400 x ~148b = ~60kB.
// This still leaves more than enough room for another data of typical CreateDenominated tx. // This still leaves more than enough room for another data of typical CreateDenominated tx.
std::vector<CompactTallyItem> vecTally; std::vector<CompactTallyItem> vecTally;
if (!GetWallets()[0]->SelectCoinsGroupedByAddresses(vecTally, true, true, true, 400)) { if (!GetMixingWallet()->SelectCoinsGroupedByAddresses(vecTally, true, true, true, 400)) {
LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::CreateDenominated -- SelectCoinsGroupedByAddresses can't find any inputs!\n"); LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::CreateDenominated -- SelectCoinsGroupedByAddresses can't find any inputs!\n");
return false; return false;
} }
@ -1482,7 +1511,7 @@ bool CPrivateSendClientSession::CreateDenominated(CAmount nBalanceToDenominate,
return a.nAmount > b.nAmount; return a.nAmount > b.nAmount;
}); });
bool fCreateMixingCollaterals = !GetWallets()[0]->HasCollateralInputs(); bool fCreateMixingCollaterals = !GetMixingWallet()->HasCollateralInputs();
for (const auto& item : vecTally) { for (const auto& item : vecTally) {
if (!CreateDenominated(nBalanceToDenominate, item, fCreateMixingCollaterals, connman)) continue; if (!CreateDenominated(nBalanceToDenominate, item, fCreateMixingCollaterals, connman)) continue;
@ -1498,9 +1527,9 @@ bool CPrivateSendClientSession::CreateDenominated(CAmount nBalanceToDenominate,
{ {
AssertLockHeld(cs_main); AssertLockHeld(cs_main);
AssertLockHeld(mempool.cs); AssertLockHeld(mempool.cs);
AssertLockHeld(GetWallets()[0]->cs_wallet); AssertLockHeld(GetMixingWallet()->cs_wallet);
if (!privateSendClient.fEnablePrivateSend || !privateSendClient.fPrivateSendRunning) return false; if (!privateSendClient.fEnablePrivateSend || !privateSendClient.IsMixing()) return false;
std::vector<CRecipient> vecSend; std::vector<CRecipient> vecSend;
CKeyHolderStorage keyHolderStorageDenom; CKeyHolderStorage keyHolderStorageDenom;
@ -1520,7 +1549,7 @@ bool CPrivateSendClientSession::CreateDenominated(CAmount nBalanceToDenominate,
// ****** Add an output for mixing collaterals ************ / // ****** Add an output for mixing collaterals ************ /
if (fCreateMixingCollaterals) { if (fCreateMixingCollaterals) {
CScript scriptCollateral = keyHolderStorageDenom.AddKey(GetWallets()[0]); CScript scriptCollateral = keyHolderStorageDenom.AddKey(GetMixingWallet());
vecSend.push_back((CRecipient){scriptCollateral, CPrivateSend::GetMaxCollateralAmount(), false}); vecSend.push_back((CRecipient){scriptCollateral, CPrivateSend::GetMaxCollateralAmount(), false});
nValueLeft -= CPrivateSend::GetMaxCollateralAmount() + nOutputFee; nValueLeft -= CPrivateSend::GetMaxCollateralAmount() + nOutputFee;
} }
@ -1533,7 +1562,7 @@ bool CPrivateSendClientSession::CreateDenominated(CAmount nBalanceToDenominate,
std::map<CAmount, int> mapDenomCount; std::map<CAmount, int> mapDenomCount;
for (auto nDenomValue : vecStandardDenoms) { for (auto nDenomValue : vecStandardDenoms) {
mapDenomCount.insert(std::pair<CAmount, int>(nDenomValue, GetWallets()[0]->CountInputsWithAmount(nDenomValue))); mapDenomCount.insert(std::pair<CAmount, int>(nDenomValue, GetMixingWallet()->CountInputsWithAmount(nDenomValue)));
} }
// Will generate outputs for the createdenoms up to privatesendmaxdenoms per denom // Will generate outputs for the createdenoms up to privatesendmaxdenoms per denom
@ -1571,7 +1600,7 @@ bool CPrivateSendClientSession::CreateDenominated(CAmount nBalanceToDenominate,
// add each output up to 11 times or until it can't be added again or until we reach nPrivateSendDenomsGoal // add each output up to 11 times or until it can't be added again or until we reach nPrivateSendDenomsGoal
while (needMoreOutputs() && nOutputs <= 10 && currentDenomIt->second < privateSendClient.nPrivateSendDenomsGoal) { while (needMoreOutputs() && nOutputs <= 10 && currentDenomIt->second < privateSendClient.nPrivateSendDenomsGoal) {
CScript scriptDenom = keyHolderStorageDenom.AddKey(GetWallets()[0]); CScript scriptDenom = keyHolderStorageDenom.AddKey(GetMixingWallet());
vecSend.push_back((CRecipient) {scriptDenom, nDenomValue, false}); vecSend.push_back((CRecipient) {scriptDenom, nDenomValue, false});
@ -1635,7 +1664,7 @@ bool CPrivateSendClientSession::CreateDenominated(CAmount nBalanceToDenominate,
// Never go above the cap unless it's the largest denom // Never go above the cap unless it's the largest denom
if (nDenomValue != nLargestDenomValue && it->second >= privateSendClient.nPrivateSendDenomsHardCap) break; if (nDenomValue != nLargestDenomValue && it->second >= privateSendClient.nPrivateSendDenomsHardCap) break;
CScript scriptDenom = keyHolderStorageDenom.AddKey(GetWallets()[0]); CScript scriptDenom = keyHolderStorageDenom.AddKey(GetMixingWallet());
vecSend.push_back((CRecipient) {scriptDenom, nDenomValue, false}); vecSend.push_back((CRecipient) {scriptDenom, nDenomValue, false});
// increment outputs and subtract denomination amount // increment outputs and subtract denomination amount
@ -1681,9 +1710,9 @@ bool CPrivateSendClientSession::CreateDenominated(CAmount nBalanceToDenominate,
int nChangePosRet = -1; int nChangePosRet = -1;
std::string strFail = ""; std::string strFail = "";
// make our change address // make our change address
CReserveKey reservekeyChange(GetWallets()[0]); CReserveKey reservekeyChange(GetMixingWallet());
bool fSuccess = GetWallets()[0]->CreateTransaction(vecSend, wtx, reservekeyChange, bool fSuccess = GetMixingWallet()->CreateTransaction(vecSend, wtx, reservekeyChange,
nFeeRet, nChangePosRet, strFail, coinControl); nFeeRet, nChangePosRet, strFail, coinControl);
if (!fSuccess) { if (!fSuccess) {
LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::CreateDenominated -- Error: %s\n", strFail); LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::CreateDenominated -- Error: %s\n", strFail);
@ -1694,7 +1723,7 @@ bool CPrivateSendClientSession::CreateDenominated(CAmount nBalanceToDenominate,
keyHolderStorageDenom.KeepAll(); keyHolderStorageDenom.KeepAll();
CValidationState state; CValidationState state;
if (!GetWallets()[0]->CommitTransaction(wtx, reservekeyChange, &connman, state)) { if (!GetMixingWallet()->CommitTransaction(wtx, reservekeyChange, &connman, state)) {
LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::CreateDenominated -- CommitTransaction failed! Reason given: %s\n", state.GetRejectReason()); LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::CreateDenominated -- CommitTransaction failed! Reason given: %s\n", state.GetRejectReason());
return false; return false;
} }
@ -1770,7 +1799,7 @@ void CPrivateSendClientManager::GetJsonInfo(UniValue& obj) const
obj.clear(); obj.clear();
obj.setObject(); obj.setObject();
obj.pushKV("enabled", fEnablePrivateSend); obj.pushKV("enabled", fEnablePrivateSend);
obj.pushKV("running", fPrivateSendRunning); obj.pushKV("running", IsMixing());
obj.pushKV("multisession", fPrivateSendMultiSession); obj.pushKV("multisession", fPrivateSendMultiSession);
obj.pushKV("max_sessions", nPrivateSendSessions); obj.pushKV("max_sessions", nPrivateSendSessions);
obj.pushKV("max_rounds", nPrivateSendRounds); obj.pushKV("max_rounds", nPrivateSendRounds);

View File

@ -163,6 +163,7 @@ public:
std::string GetStatus(bool fWaitForBlock); std::string GetStatus(bool fWaitForBlock);
bool GetMixingMasternodeInfo(CDeterministicMNCPtr& ret) const; bool GetMixingMasternodeInfo(CDeterministicMNCPtr& ret) const;
CWallet* GetMixingWallet() const;
/// Passively run mixing in the background according to the configuration in settings /// Passively run mixing in the background according to the configuration in settings
bool DoAutomaticDenominating(CConnman& connman, bool fDryRun = false); bool DoAutomaticDenominating(CConnman& connman, bool fDryRun = false);
@ -193,6 +194,8 @@ private:
int nMinBlocksToWait; // how many blocks to wait after one successful mixing tx in non-multisession mode int nMinBlocksToWait; // how many blocks to wait after one successful mixing tx in non-multisession mode
std::string strAutoDenomResult; std::string strAutoDenomResult;
CWallet* mixingWallet;
// Keep track of current block height // Keep track of current block height
int nCachedBlockHeight; int nCachedBlockHeight;
@ -208,7 +211,6 @@ public:
int nPrivateSendDenomsGoal; int nPrivateSendDenomsGoal;
int nPrivateSendDenomsHardCap; int nPrivateSendDenomsHardCap;
bool fEnablePrivateSend; bool fEnablePrivateSend;
bool fPrivateSendRunning;
bool fPrivateSendMultiSession; bool fPrivateSendMultiSession;
int nCachedNumBlocks; //used for the overview screen int nCachedNumBlocks; //used for the overview screen
@ -226,15 +228,20 @@ public:
nPrivateSendDenomsGoal(DEFAULT_PRIVATESEND_DENOMS_GOAL), nPrivateSendDenomsGoal(DEFAULT_PRIVATESEND_DENOMS_GOAL),
nPrivateSendDenomsHardCap(DEFAULT_PRIVATESEND_DENOMS_HARDCAP), nPrivateSendDenomsHardCap(DEFAULT_PRIVATESEND_DENOMS_HARDCAP),
fEnablePrivateSend(false), fEnablePrivateSend(false),
fPrivateSendRunning(false),
fPrivateSendMultiSession(DEFAULT_PRIVATESEND_MULTISESSION), fPrivateSendMultiSession(DEFAULT_PRIVATESEND_MULTISESSION),
nCachedNumBlocks(std::numeric_limits<int>::max()), nCachedNumBlocks(std::numeric_limits<int>::max()),
fCreateAutoBackups(true) fCreateAutoBackups(true),
mixingWallet(nullptr)
{ {
} }
void ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, CConnman& connman, bool enable_bip61); void ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, CConnman& connman, bool enable_bip61);
bool StartMixing(CWallet* pwallet);
void StopMixing();
bool IsMixing() const;
void ResetPool(); void ResetPool();
std::string GetStatuses(); std::string GetStatuses();
@ -242,6 +249,8 @@ public:
bool GetMixingMasternodesInfo(std::vector<CDeterministicMNCPtr>& vecDmnsRet) const; bool GetMixingMasternodesInfo(std::vector<CDeterministicMNCPtr>& vecDmnsRet) const;
CWallet* GetMixingWallet() const;
/// Passively run mixing in the background according to the configuration in settings /// Passively run mixing in the background according to the configuration in settings
bool DoAutomaticDenominating(CConnman& connman, bool fDryRun = false); bool DoAutomaticDenominating(CConnman& connman, bool fDryRun = false);

View File

@ -1049,7 +1049,7 @@ void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVer
// Disabling macOS App Nap on initial sync, disk, reindex operations and mixing. // Disabling macOS App Nap on initial sync, disk, reindex operations and mixing.
bool disableAppNap = !masternodeSync.IsSynced(); bool disableAppNap = !masternodeSync.IsSynced();
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
disableAppNap |= privateSendClient.fPrivateSendRunning; disableAppNap |= privateSendClient.IsMixing();
#endif // ENABLE_WALLET #endif // ENABLE_WALLET
if (disableAppNap) { if (disableAppNap) {
m_app_nap_inhibitor->disableAppNap(); m_app_nap_inhibitor->disableAppNap();

View File

@ -181,7 +181,7 @@ OverviewPage::OverviewPage(const PlatformStyle *platformStyle, QWidget *parent)
ui->labelPrivateSendEnabled->setToolTip(tr("Automatic backups are disabled, no mixing available!")); ui->labelPrivateSendEnabled->setToolTip(tr("Automatic backups are disabled, no mixing available!"));
} }
} else { } else {
if(!privateSendClient.fPrivateSendRunning){ if(!privateSendClient.IsMixing()){
ui->togglePrivateSend->setText(tr("Start Mixing")); ui->togglePrivateSend->setText(tr("Start Mixing"));
} else { } else {
ui->togglePrivateSend->setText(tr("Stop Mixing")); ui->togglePrivateSend->setText(tr("Stop Mixing"));
@ -500,7 +500,7 @@ void OverviewPage::privateSendStatus(bool fForce)
} }
ui->labelPrivateSendEnabled->setToolTip(strKeysLeftText); ui->labelPrivateSendEnabled->setToolTip(strKeysLeftText);
if (!privateSendClient.fPrivateSendRunning) { if (!privateSendClient.IsMixing()) {
if (nBestHeight != privateSendClient.nCachedNumBlocks) { if (nBestHeight != privateSendClient.nCachedNumBlocks) {
privateSendClient.nCachedNumBlocks = nBestHeight; privateSendClient.nCachedNumBlocks = nBestHeight;
updatePrivateSendProgress(); updatePrivateSendProgress();
@ -557,7 +557,7 @@ void OverviewPage::privateSendStatus(bool fForce)
} }
} }
QString strEnabled = privateSendClient.fPrivateSendRunning ? tr("Enabled") : tr("Disabled"); QString strEnabled = privateSendClient.IsMixing() ? tr("Enabled") : tr("Disabled");
// Show how many keys left in advanced PS UI mode only // Show how many keys left in advanced PS UI mode only
if(fShowAdvancedPSUI) strEnabled += ", " + strKeysLeftText; if(fShowAdvancedPSUI) strEnabled += ", " + strKeysLeftText;
ui->labelPrivateSendEnabled->setText(strEnabled); ui->labelPrivateSendEnabled->setText(strEnabled);
@ -600,7 +600,7 @@ void OverviewPage::togglePrivateSend(){
QMessageBox::Ok, QMessageBox::Ok); QMessageBox::Ok, QMessageBox::Ok);
settings.setValue("hasMixed", "hasMixed"); settings.setValue("hasMixed", "hasMixed");
} }
if(!privateSendClient.fPrivateSendRunning){ if(!privateSendClient.IsMixing()){
const CAmount nMinAmount = CPrivateSend::GetSmallestDenomination() + CPrivateSend::GetMaxCollateralAmount(); const CAmount nMinAmount = CPrivateSend::GetSmallestDenomination() + CPrivateSend::GetMaxCollateralAmount();
if(currentBalance < nMinAmount){ if(currentBalance < nMinAmount){
QString strMinAmount(BitcoinUnits::formatWithUnit(nDisplayUnit, nMinAmount)); QString strMinAmount(BitcoinUnits::formatWithUnit(nDisplayUnit, nMinAmount));
@ -628,14 +628,15 @@ void OverviewPage::togglePrivateSend(){
} }
privateSendClient.fPrivateSendRunning = !privateSendClient.fPrivateSendRunning;
privateSendClient.nCachedNumBlocks = std::numeric_limits<int>::max(); privateSendClient.nCachedNumBlocks = std::numeric_limits<int>::max();
if(!privateSendClient.fPrivateSendRunning){ if (privateSendClient.IsMixing()) {
ui->togglePrivateSend->setText(tr("Start Mixing")); ui->togglePrivateSend->setText(tr("Start Mixing"));
privateSendClient.ResetPool(); privateSendClient.ResetPool();
privateSendClient.StopMixing();
} else { } else {
ui->togglePrivateSend->setText(tr("Stop Mixing")); ui->togglePrivateSend->setText(tr("Stop Mixing"));
privateSendClient.StartMixing(walletModel->getWallet());
} }
} }
@ -663,5 +664,5 @@ void OverviewPage::DisablePrivateSendCompletely() {
if (nWalletBackups <= 0) { if (nWalletBackups <= 0) {
ui->labelPrivateSendEnabled->setText("<span style='" + GUIUtil::getThemedStyleQString(GUIUtil::ThemedStyle::TS_ERROR) + "'>(" + tr("Disabled") + ")</span>"); ui->labelPrivateSendEnabled->setText("<span style='" + GUIUtil::getThemedStyleQString(GUIUtil::ThemedStyle::TS_ERROR) + "'>(" + tr("Disabled") + ")</span>");
} }
privateSendClient.fPrivateSendRunning = false; privateSendClient.StopMixing();
} }

View File

@ -50,13 +50,16 @@ UniValue privatesend(const JSONRPCRequest& request)
throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please unlock wallet for mixing with walletpassphrase first."); throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please unlock wallet for mixing with walletpassphrase first.");
} }
privateSendClient.fPrivateSendRunning = true; if (!privateSendClient.StartMixing(pwallet)) {
throw JSONRPCError(RPC_INTERNAL_ERROR, "Mixing has been started already.");
}
bool result = privateSendClient.DoAutomaticDenominating(*g_connman); bool result = privateSendClient.DoAutomaticDenominating(*g_connman);
return "Mixing " + (result ? "started successfully" : ("start failed: " + privateSendClient.GetStatuses() + ", will retry")); return "Mixing " + (result ? "started successfully" : ("start failed: " + privateSendClient.GetStatuses() + ", will retry"));
} }
if (request.params[0].get_str() == "stop") { if (request.params[0].get_str() == "stop") {
privateSendClient.fPrivateSendRunning = false; privateSendClient.StopMixing();
return "Mixing was stopped"; return "Mixing was stopped";
} }

View File

@ -374,8 +374,8 @@ void WalletInit::Flush()
{ {
if (privateSendClient.fEnablePrivateSend) { if (privateSendClient.fEnablePrivateSend) {
// Stop PrivateSend, release keys // Stop PrivateSend, release keys
privateSendClient.fPrivateSendRunning = false;
privateSendClient.ResetPool(); privateSendClient.ResetPool();
privateSendClient.StopMixing();
} }
for (CWallet* pwallet : GetWallets()) { for (CWallet* pwallet : GetWallets()) {
pwallet->Flush(false); pwallet->Flush(false);
@ -408,10 +408,15 @@ void WalletInit::AutoLockMasternodeCollaterals()
void WalletInit::InitPrivateSendSettings() void WalletInit::InitPrivateSendSettings()
{ {
if (!HasWallets()) { if (!HasWallets()) {
privateSendClient.fEnablePrivateSend = privateSendClient.fPrivateSendRunning = false; privateSendClient.fEnablePrivateSend = false;
privateSendClient.StopMixing();
} else { } else {
privateSendClient.fEnablePrivateSend = gArgs.GetBoolArg("-enableprivatesend", true); privateSendClient.fEnablePrivateSend = gArgs.GetBoolArg("-enableprivatesend", true);
privateSendClient.fPrivateSendRunning = GetWallets()[0]->IsLocked() ? false : gArgs.GetBoolArg("-privatesendautostart", DEFAULT_PRIVATESEND_AUTOSTART); if (GetWallets()[0]->IsLocked()) {
privateSendClient.StopMixing();
} else if (gArgs.GetBoolArg("-privatesendautostart", DEFAULT_PRIVATESEND_AUTOSTART)) {
privateSendClient.StartMixing(GetWallets()[0]);
}
} }
privateSendClient.fPrivateSendMultiSession = gArgs.GetBoolArg("-privatesendmultisession", DEFAULT_PRIVATESEND_MULTISESSION); privateSendClient.fPrivateSendMultiSession = gArgs.GetBoolArg("-privatesendmultisession", DEFAULT_PRIVATESEND_MULTISESSION);
privateSendClient.nPrivateSendSessions = std::min(std::max((int)gArgs.GetArg("-privatesendsessions", DEFAULT_PRIVATESEND_SESSIONS), MIN_PRIVATESEND_SESSIONS), MAX_PRIVATESEND_SESSIONS); privateSendClient.nPrivateSendSessions = std::min(std::max((int)gArgs.GetArg("-privatesendsessions", DEFAULT_PRIVATESEND_SESSIONS), MIN_PRIVATESEND_SESSIONS), MAX_PRIVATESEND_SESSIONS);
@ -423,7 +428,7 @@ void WalletInit::InitPrivateSendSettings()
if (privateSendClient.fEnablePrivateSend) { if (privateSendClient.fEnablePrivateSend) {
LogPrintf("PrivateSend: autostart=%d, multisession=%d," /* Continued */ LogPrintf("PrivateSend: autostart=%d, multisession=%d," /* Continued */
"sessions=%d, rounds=%d, amount=%d, denoms_goal=%d, denoms_hardcap=%d\n", "sessions=%d, rounds=%d, amount=%d, denoms_goal=%d, denoms_hardcap=%d\n",
privateSendClient.fPrivateSendRunning, privateSendClient.fPrivateSendMultiSession, privateSendClient.IsMixing(), privateSendClient.fPrivateSendMultiSession,
privateSendClient.nPrivateSendSessions, privateSendClient.nPrivateSendRounds, privateSendClient.nPrivateSendSessions, privateSendClient.nPrivateSendRounds,
privateSendClient.nPrivateSendAmount, privateSendClient.nPrivateSendAmount,
privateSendClient.nPrivateSendDenomsGoal, privateSendClient.nPrivateSendDenomsHardCap); privateSendClient.nPrivateSendDenomsGoal, privateSendClient.nPrivateSendDenomsHardCap);

View File

@ -4342,7 +4342,7 @@ bool CWallet::NewKeyPool()
batch.ErasePool(nIndex); batch.ErasePool(nIndex);
} }
setExternalKeyPool.clear(); setExternalKeyPool.clear();
privateSendClient.fPrivateSendRunning = false; privateSendClient.StopMixing();
nKeysLeftSinceAutoBackup = 0; nKeysLeftSinceAutoBackup = 0;
m_pool_key_to_index.clear(); m_pool_key_to_index.clear();