Split PS into Manager and Session and allow running multiple mixing sessions in parallel (client side) (#2203)
* Split PS into Manager and Session * Adjust log messages accordingly * add -privatesendsessions cmd-line option * address review comments * bump MAX_OUTBOUND_MASTERNODE_CONNECTIONS to 30 +10 for parallel mixing * protect vecSessions * constructors * Rewrite CMasternodeMan::ProcessMasternodeConnections() to use CPrivateSendClientManager::GetMixingMasternodesInfo(). This should solve potential deadlock cs_vecqueue vs cs_vNodes. * Drop no longer used IsMixingMasternode() * lock cs_wallet when mixing uses balance related functions
This commit is contained in:
parent
794921b7b5
commit
b164bcc7a5
@ -579,6 +579,7 @@ std::string HelpMessage(HelpMessageMode mode)
|
|||||||
strUsage += HelpMessageGroup(_("PrivateSend options:"));
|
strUsage += HelpMessageGroup(_("PrivateSend options:"));
|
||||||
strUsage += HelpMessageOpt("-enableprivatesend=<n>", strprintf(_("Enable use of automated PrivateSend for funds stored in this wallet (0-1, default: %u)"), 0));
|
strUsage += HelpMessageOpt("-enableprivatesend=<n>", strprintf(_("Enable use of automated PrivateSend for funds stored in this wallet (0-1, default: %u)"), 0));
|
||||||
strUsage += HelpMessageOpt("-privatesendmultisession=<n>", strprintf(_("Enable multiple PrivateSend mixing sessions per block, experimental (0-1, default: %u)"), DEFAULT_PRIVATESEND_MULTISESSION));
|
strUsage += HelpMessageOpt("-privatesendmultisession=<n>", strprintf(_("Enable multiple PrivateSend mixing sessions per block, experimental (0-1, default: %u)"), DEFAULT_PRIVATESEND_MULTISESSION));
|
||||||
|
strUsage += HelpMessageOpt("-privatesendsessions=<n>", strprintf(_("Use N separate masternodes in parallel to mix funds (%u-%u, default: %u)"), MIN_PRIVATESEND_SESSIONS, MAX_PRIVATESEND_SESSIONS, DEFAULT_PRIVATESEND_SESSIONS));
|
||||||
strUsage += HelpMessageOpt("-privatesendrounds=<n>", strprintf(_("Use N separate masternodes for each denominated input to mix funds (%u-%u, default: %u)"), MIN_PRIVATESEND_ROUNDS, MAX_PRIVATESEND_ROUNDS, DEFAULT_PRIVATESEND_ROUNDS));
|
strUsage += HelpMessageOpt("-privatesendrounds=<n>", strprintf(_("Use N separate masternodes for each denominated input to mix funds (%u-%u, default: %u)"), MIN_PRIVATESEND_ROUNDS, MAX_PRIVATESEND_ROUNDS, DEFAULT_PRIVATESEND_ROUNDS));
|
||||||
strUsage += HelpMessageOpt("-privatesendamount=<n>", strprintf(_("Keep N DASH anonymized (%u-%u, default: %u)"), MIN_PRIVATESEND_AMOUNT, MAX_PRIVATESEND_AMOUNT, DEFAULT_PRIVATESEND_AMOUNT));
|
strUsage += HelpMessageOpt("-privatesendamount=<n>", strprintf(_("Keep N DASH anonymized (%u-%u, default: %u)"), MIN_PRIVATESEND_AMOUNT, MAX_PRIVATESEND_AMOUNT, DEFAULT_PRIVATESEND_AMOUNT));
|
||||||
strUsage += HelpMessageOpt("-liquidityprovider=<n>", strprintf(_("Provide liquidity to PrivateSend by infrequently mixing coins on a continual basis (%u-%u, default: %u, 1=very frequent, high fees, %u=very infrequent, low fees)"),
|
strUsage += HelpMessageOpt("-liquidityprovider=<n>", strprintf(_("Provide liquidity to PrivateSend by infrequently mixing coins on a continual basis (%u-%u, default: %u, 1=very frequent, high fees, %u=very infrequent, low fees)"),
|
||||||
@ -918,6 +919,8 @@ void InitParameterInteraction()
|
|||||||
if (nLiqProvTmp > 0) {
|
if (nLiqProvTmp > 0) {
|
||||||
ForceSetArg("-enableprivatesend", "1");
|
ForceSetArg("-enableprivatesend", "1");
|
||||||
LogPrintf("%s: parameter interaction: -liquidityprovider=%d -> setting -enableprivatesend=1\n", __func__, nLiqProvTmp);
|
LogPrintf("%s: parameter interaction: -liquidityprovider=%d -> setting -enableprivatesend=1\n", __func__, nLiqProvTmp);
|
||||||
|
ForceSetArg("-privatesendsessions", itostr(MIN_PRIVATESEND_SESSIONS));
|
||||||
|
LogPrintf("%s: parameter interaction: -liquidityprovider=%d -> setting -privatesendsessions=%d\n", __func__, nLiqProvTmp, itostr(std::numeric_limits<int>::max()));
|
||||||
ForceSetArg("-privatesendrounds", itostr(std::numeric_limits<int>::max()));
|
ForceSetArg("-privatesendrounds", itostr(std::numeric_limits<int>::max()));
|
||||||
LogPrintf("%s: parameter interaction: -liquidityprovider=%d -> setting -privatesendrounds=%d\n", __func__, nLiqProvTmp, itostr(std::numeric_limits<int>::max()));
|
LogPrintf("%s: parameter interaction: -liquidityprovider=%d -> setting -privatesendrounds=%d\n", __func__, nLiqProvTmp, itostr(std::numeric_limits<int>::max()));
|
||||||
ForceSetArg("-privatesendamount", itostr(MAX_PRIVATESEND_AMOUNT));
|
ForceSetArg("-privatesendamount", itostr(MAX_PRIVATESEND_AMOUNT));
|
||||||
@ -1921,6 +1924,7 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler)
|
|||||||
|
|
||||||
privateSendClient.fEnablePrivateSend = GetBoolArg("-enableprivatesend", false);
|
privateSendClient.fEnablePrivateSend = GetBoolArg("-enableprivatesend", false);
|
||||||
privateSendClient.fPrivateSendMultiSession = GetBoolArg("-privatesendmultisession", DEFAULT_PRIVATESEND_MULTISESSION);
|
privateSendClient.fPrivateSendMultiSession = GetBoolArg("-privatesendmultisession", DEFAULT_PRIVATESEND_MULTISESSION);
|
||||||
|
privateSendClient.nPrivateSendSessions = std::min(std::max((int)GetArg("-privatesendsessions", DEFAULT_PRIVATESEND_SESSIONS), MIN_PRIVATESEND_SESSIONS), MAX_PRIVATESEND_SESSIONS);
|
||||||
privateSendClient.nPrivateSendRounds = std::min(std::max((int)GetArg("-privatesendrounds", DEFAULT_PRIVATESEND_ROUNDS), MIN_PRIVATESEND_ROUNDS), nMaxRounds);
|
privateSendClient.nPrivateSendRounds = std::min(std::max((int)GetArg("-privatesendrounds", DEFAULT_PRIVATESEND_ROUNDS), MIN_PRIVATESEND_ROUNDS), nMaxRounds);
|
||||||
privateSendClient.nPrivateSendAmount = std::min(std::max((int)GetArg("-privatesendamount", DEFAULT_PRIVATESEND_AMOUNT), MIN_PRIVATESEND_AMOUNT), MAX_PRIVATESEND_AMOUNT);
|
privateSendClient.nPrivateSendAmount = std::min(std::max((int)GetArg("-privatesendamount", DEFAULT_PRIVATESEND_AMOUNT), MIN_PRIVATESEND_AMOUNT), MAX_PRIVATESEND_AMOUNT);
|
||||||
#endif // ENABLE_WALLET
|
#endif // ENABLE_WALLET
|
||||||
@ -2023,7 +2027,7 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler)
|
|||||||
scheduler.scheduleEvery(boost::bind(&CPrivateSendServer::DoMaintenance, boost::ref(privateSendServer), boost::ref(*g_connman)), 1);
|
scheduler.scheduleEvery(boost::bind(&CPrivateSendServer::DoMaintenance, boost::ref(privateSendServer), boost::ref(*g_connman)), 1);
|
||||||
#ifdef ENABLE_WALLET
|
#ifdef ENABLE_WALLET
|
||||||
else
|
else
|
||||||
scheduler.scheduleEvery(boost::bind(&CPrivateSendClient::DoMaintenance, boost::ref(privateSendClient), boost::ref(*g_connman)), 1);
|
scheduler.scheduleEvery(boost::bind(&CPrivateSendClientManager::DoMaintenance, boost::ref(privateSendClient), boost::ref(*g_connman)), 1);
|
||||||
#endif // ENABLE_WALLET
|
#endif // ENABLE_WALLET
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -882,11 +882,22 @@ void CMasternodeMan::ProcessMasternodeConnections(CConnman& connman)
|
|||||||
//we don't care about this for regtest
|
//we don't care about this for regtest
|
||||||
if(Params().NetworkIDString() == CBaseChainParams::REGTEST) return;
|
if(Params().NetworkIDString() == CBaseChainParams::REGTEST) return;
|
||||||
|
|
||||||
connman.ForEachNode(CConnman::AllNodes, [](CNode* pnode) {
|
std::vector<masternode_info_t> vecMnInfo; // will be empty when no wallet
|
||||||
#ifdef ENABLE_WALLET
|
#ifdef ENABLE_WALLET
|
||||||
if(pnode->fMasternode && !privateSendClient.IsMixingMasternode(pnode)) {
|
privateSendClient.GetMixingMasternodesInfo(vecMnInfo);
|
||||||
#else
|
#endif // ENABLE_WALLET
|
||||||
if(pnode->fMasternode) {
|
|
||||||
|
connman.ForEachNode(CConnman::AllNodes, [&vecMnInfo](CNode* pnode) {
|
||||||
|
if (pnode->fMasternode) {
|
||||||
|
#ifdef ENABLE_WALLET
|
||||||
|
bool fFound = false;
|
||||||
|
for (const auto& mnInfo : vecMnInfo) {
|
||||||
|
if (pnode->addr == mnInfo.addr) {
|
||||||
|
fFound = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fFound) return; // do NOT disconnect mixing masternodes
|
||||||
#endif // ENABLE_WALLET
|
#endif // ENABLE_WALLET
|
||||||
LogPrintf("Closing Masternode connection: peer=%d, addr=%s\n", pnode->id, pnode->addr.ToString());
|
LogPrintf("Closing Masternode connection: peer=%d, addr=%s\n", pnode->id, pnode->addr.ToString());
|
||||||
pnode->fDisconnect = true;
|
pnode->fDisconnect = true;
|
||||||
|
@ -65,7 +65,7 @@ static const int MAX_OUTBOUND_CONNECTIONS = 8;
|
|||||||
/** Maximum number of addnode outgoing nodes */
|
/** Maximum number of addnode outgoing nodes */
|
||||||
static const int MAX_ADDNODE_CONNECTIONS = 8;
|
static const int MAX_ADDNODE_CONNECTIONS = 8;
|
||||||
/** Maximum number if outgoing masternodes */
|
/** Maximum number if outgoing masternodes */
|
||||||
static const int MAX_OUTBOUND_MASTERNODE_CONNECTIONS = 20;
|
static const int MAX_OUTBOUND_MASTERNODE_CONNECTIONS = 30;
|
||||||
/** -listen default */
|
/** -listen default */
|
||||||
static const bool DEFAULT_LISTEN = true;
|
static const bool DEFAULT_LISTEN = true;
|
||||||
/** -upnp default */
|
/** -upnp default */
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -10,17 +10,20 @@
|
|||||||
#include "wallet/wallet.h"
|
#include "wallet/wallet.h"
|
||||||
#include "privatesend-util.h"
|
#include "privatesend-util.h"
|
||||||
|
|
||||||
class CPrivateSendClient;
|
class CPrivateSendClientManager;
|
||||||
class CConnman;
|
class CConnman;
|
||||||
|
|
||||||
static const int DENOMS_COUNT_MAX = 100;
|
static const int DENOMS_COUNT_MAX = 100;
|
||||||
|
|
||||||
|
static const int MIN_PRIVATESEND_SESSIONS = 1;
|
||||||
static const int MIN_PRIVATESEND_ROUNDS = 2;
|
static const int MIN_PRIVATESEND_ROUNDS = 2;
|
||||||
static const int MIN_PRIVATESEND_AMOUNT = 2;
|
static const int MIN_PRIVATESEND_AMOUNT = 2;
|
||||||
static const int MIN_PRIVATESEND_LIQUIDITY = 0;
|
static const int MIN_PRIVATESEND_LIQUIDITY = 0;
|
||||||
|
static const int MAX_PRIVATESEND_SESSIONS = 10;
|
||||||
static const int MAX_PRIVATESEND_ROUNDS = 16;
|
static const int MAX_PRIVATESEND_ROUNDS = 16;
|
||||||
static const int MAX_PRIVATESEND_AMOUNT = MAX_MONEY / COIN;
|
static const int MAX_PRIVATESEND_AMOUNT = MAX_MONEY / COIN;
|
||||||
static const int MAX_PRIVATESEND_LIQUIDITY = 100;
|
static const int MAX_PRIVATESEND_LIQUIDITY = 100;
|
||||||
|
static const int DEFAULT_PRIVATESEND_SESSIONS = 4;
|
||||||
static const int DEFAULT_PRIVATESEND_ROUNDS = 4;
|
static const int DEFAULT_PRIVATESEND_ROUNDS = 4;
|
||||||
static const int DEFAULT_PRIVATESEND_AMOUNT = 1000;
|
static const int DEFAULT_PRIVATESEND_AMOUNT = 1000;
|
||||||
static const int DEFAULT_PRIVATESEND_LIQUIDITY = 0;
|
static const int DEFAULT_PRIVATESEND_LIQUIDITY = 0;
|
||||||
@ -34,7 +37,7 @@ static const int PRIVATESEND_KEYS_THRESHOLD_WARNING = 100;
|
|||||||
static const int PRIVATESEND_KEYS_THRESHOLD_STOP = 50;
|
static const int PRIVATESEND_KEYS_THRESHOLD_STOP = 50;
|
||||||
|
|
||||||
// The main object for accessing mixing
|
// The main object for accessing mixing
|
||||||
extern CPrivateSendClient privateSendClient;
|
extern CPrivateSendClientManager privateSendClient;
|
||||||
|
|
||||||
class CPendingDsaRequest
|
class CPendingDsaRequest
|
||||||
{
|
{
|
||||||
@ -75,23 +78,11 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Used to keep track of current status of mixing pool
|
class CPrivateSendClientSession : public CPrivateSendBaseSession
|
||||||
*/
|
|
||||||
class CPrivateSendClient : public CPrivateSendBase
|
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
// Keep track of the used Masternodes
|
|
||||||
std::vector<COutPoint> vecMasternodesUsed;
|
|
||||||
|
|
||||||
std::vector<CAmount> vecDenominationsSkipped;
|
|
||||||
std::vector<COutPoint> vecOutPointLocked;
|
std::vector<COutPoint> vecOutPointLocked;
|
||||||
|
|
||||||
int nCachedLastSuccessBlock;
|
|
||||||
int nMinBlocksToWait; // how many blocks to wait after one successful mixing tx in non-multisession mode
|
|
||||||
|
|
||||||
// Keep track of current block height
|
|
||||||
int nCachedBlockHeight;
|
|
||||||
|
|
||||||
int nEntriesCount;
|
int nEntriesCount;
|
||||||
bool fLastEntryAccepted;
|
bool fLastEntryAccepted;
|
||||||
|
|
||||||
@ -104,19 +95,6 @@ private:
|
|||||||
|
|
||||||
CKeyHolderStorage keyHolderStorage; // storage for keys used in PrepareDenominate
|
CKeyHolderStorage keyHolderStorage; // storage for keys used in PrepareDenominate
|
||||||
|
|
||||||
/// Check for process
|
|
||||||
void CheckPool();
|
|
||||||
void CompletedTransaction(PoolMessage nMessageID);
|
|
||||||
|
|
||||||
bool IsDenomSkipped(CAmount nDenomValue);
|
|
||||||
|
|
||||||
bool WaitForAnotherBlock();
|
|
||||||
|
|
||||||
// Make sure we have enough keys since last backup
|
|
||||||
bool CheckAutomaticBackup();
|
|
||||||
bool JoinExistingQueue(CAmount nBalanceNeedsAnonymized, CConnman& connman);
|
|
||||||
bool StartNewQueue(CAmount nValueMin, CAmount nBalanceNeedsAnonymized, CConnman& connman);
|
|
||||||
|
|
||||||
/// Create denominations
|
/// Create denominations
|
||||||
bool CreateDenominated(CConnman& connman);
|
bool CreateDenominated(CConnman& connman);
|
||||||
bool CreateDenominated(const CompactTallyItem& tallyItem, bool fCreateMixingCollaterals, CConnman& connman);
|
bool CreateDenominated(const CompactTallyItem& tallyItem, bool fCreateMixingCollaterals, CConnman& connman);
|
||||||
@ -125,8 +103,9 @@ private:
|
|||||||
bool MakeCollateralAmounts(CConnman& connman);
|
bool MakeCollateralAmounts(CConnman& connman);
|
||||||
bool MakeCollateralAmounts(const CompactTallyItem& tallyItem, bool fTryDenominated, CConnman& connman);
|
bool MakeCollateralAmounts(const CompactTallyItem& tallyItem, bool fTryDenominated, CConnman& connman);
|
||||||
|
|
||||||
/// As a client, submit part of a future mixing transaction to a Masternode to start the process
|
bool JoinExistingQueue(CAmount nBalanceNeedsAnonymized, CConnman& connman);
|
||||||
bool SubmitDenominate(CConnman& connman);
|
bool StartNewQueue(CAmount nValueMin, CAmount nBalanceNeedsAnonymized, CConnman& connman);
|
||||||
|
|
||||||
/// step 1: prepare denominated inputs and outputs
|
/// step 1: prepare denominated inputs and outputs
|
||||||
bool PrepareDenominate(int nMinRounds, int nMaxRounds, std::string& strErrorRet, std::vector<CTxDSIn>& vecTxDSInRet, std::vector<CTxOut>& vecTxOutRet);
|
bool PrepareDenominate(int nMinRounds, int nMaxRounds, std::string& strErrorRet, std::vector<CTxDSIn>& vecTxDSInRet, std::vector<CTxOut>& vecTxOutRet);
|
||||||
/// step 2: send denominated inputs and outputs prepared in step 1
|
/// step 2: send denominated inputs and outputs prepared in step 1
|
||||||
@ -137,6 +116,10 @@ private:
|
|||||||
// Set the 'state' value, with some logging and capturing when the state changed
|
// Set the 'state' value, with some logging and capturing when the state changed
|
||||||
void SetState(PoolState nStateNew);
|
void SetState(PoolState nStateNew);
|
||||||
|
|
||||||
|
/// Check for process
|
||||||
|
void CheckPool();
|
||||||
|
void CompletedTransaction(PoolMessage nMessageID);
|
||||||
|
|
||||||
/// As a client, check and sign the final transaction
|
/// As a client, check and sign the final transaction
|
||||||
bool SignFinalTransaction(const CTransaction& finalTransactionNew, CNode* pnode, CConnman& connman);
|
bool SignFinalTransaction(const CTransaction& finalTransactionNew, CNode* pnode, CConnman& connman);
|
||||||
|
|
||||||
@ -145,6 +128,68 @@ private:
|
|||||||
void SetNull();
|
void SetNull();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
CPrivateSendClientSession() :
|
||||||
|
vecOutPointLocked(),
|
||||||
|
nEntriesCount(0),
|
||||||
|
fLastEntryAccepted(false),
|
||||||
|
strLastMessage(),
|
||||||
|
strAutoDenomResult(),
|
||||||
|
infoMixingMasternode(),
|
||||||
|
txMyCollateral(),
|
||||||
|
pendingDsaRequest(),
|
||||||
|
keyHolderStorage()
|
||||||
|
{}
|
||||||
|
CPrivateSendClientSession(const CPrivateSendClientSession& other) { /* dummy copy constructor*/ SetNull(); }
|
||||||
|
|
||||||
|
void ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, CConnman& connman);
|
||||||
|
|
||||||
|
void UnlockCoins();
|
||||||
|
|
||||||
|
void ResetPool();
|
||||||
|
|
||||||
|
std::string GetStatus(bool fWaitForBlock);
|
||||||
|
|
||||||
|
bool GetMixingMasternodeInfo(masternode_info_t& mnInfoRet) const;
|
||||||
|
|
||||||
|
/// Passively run mixing in the background according to the configuration in settings
|
||||||
|
bool DoAutomaticDenominating(CConnman& connman, bool fDryRun=false);
|
||||||
|
|
||||||
|
/// As a client, submit part of a future mixing transaction to a Masternode to start the process
|
||||||
|
bool SubmitDenominate(CConnman& connman);
|
||||||
|
|
||||||
|
bool ProcessPendingDsaRequest(CConnman& connman);
|
||||||
|
|
||||||
|
bool CheckTimeout();
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Used to keep track of current status of mixing pool
|
||||||
|
*/
|
||||||
|
class CPrivateSendClientManager : public CPrivateSendBaseManager
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
// Keep track of the used Masternodes
|
||||||
|
std::vector<COutPoint> vecMasternodesUsed;
|
||||||
|
|
||||||
|
std::vector<CAmount> vecDenominationsSkipped;
|
||||||
|
|
||||||
|
// TODO: or map<denom, CPrivateSendClientSession> ??
|
||||||
|
std::vector<CPrivateSendClientSession> vecSessions;
|
||||||
|
mutable CCriticalSection cs_vecsessions;
|
||||||
|
|
||||||
|
int nCachedLastSuccessBlock;
|
||||||
|
int nMinBlocksToWait; // how many blocks to wait after one successful mixing tx in non-multisession mode
|
||||||
|
std::string strAutoDenomResult;
|
||||||
|
|
||||||
|
// Keep track of current block height
|
||||||
|
int nCachedBlockHeight;
|
||||||
|
|
||||||
|
bool WaitForAnotherBlock();
|
||||||
|
|
||||||
|
// Make sure we have enough keys since last backup
|
||||||
|
bool CheckAutomaticBackup();
|
||||||
|
|
||||||
|
public:
|
||||||
|
int nPrivateSendSessions;
|
||||||
int nPrivateSendRounds;
|
int nPrivateSendRounds;
|
||||||
int nPrivateSendAmount;
|
int nPrivateSendAmount;
|
||||||
int nLiquidityProvider;
|
int nLiquidityProvider;
|
||||||
@ -154,40 +199,49 @@ public:
|
|||||||
int nCachedNumBlocks; //used for the overview screen
|
int nCachedNumBlocks; //used for the overview screen
|
||||||
bool fCreateAutoBackups; //builtin support for automatic backups
|
bool fCreateAutoBackups; //builtin support for automatic backups
|
||||||
|
|
||||||
CPrivateSendClient() :
|
CPrivateSendClientManager() :
|
||||||
|
vecMasternodesUsed(),
|
||||||
|
vecDenominationsSkipped(),
|
||||||
|
vecSessions(),
|
||||||
nCachedLastSuccessBlock(0),
|
nCachedLastSuccessBlock(0),
|
||||||
nMinBlocksToWait(1),
|
nMinBlocksToWait(1),
|
||||||
txMyCollateral(CMutableTransaction()),
|
strAutoDenomResult(),
|
||||||
|
nCachedBlockHeight(0),
|
||||||
nPrivateSendRounds(DEFAULT_PRIVATESEND_ROUNDS),
|
nPrivateSendRounds(DEFAULT_PRIVATESEND_ROUNDS),
|
||||||
nPrivateSendAmount(DEFAULT_PRIVATESEND_AMOUNT),
|
nPrivateSendAmount(DEFAULT_PRIVATESEND_AMOUNT),
|
||||||
nLiquidityProvider(DEFAULT_PRIVATESEND_LIQUIDITY),
|
nLiquidityProvider(DEFAULT_PRIVATESEND_LIQUIDITY),
|
||||||
fEnablePrivateSend(false),
|
fEnablePrivateSend(false),
|
||||||
fPrivateSendMultiSession(DEFAULT_PRIVATESEND_MULTISESSION),
|
fPrivateSendMultiSession(DEFAULT_PRIVATESEND_MULTISESSION),
|
||||||
nCachedNumBlocks(std::numeric_limits<int>::max()),
|
nCachedNumBlocks(std::numeric_limits<int>::max()),
|
||||||
fCreateAutoBackups(true) { SetNull(); }
|
fCreateAutoBackups(true)
|
||||||
|
{}
|
||||||
|
|
||||||
void ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, CConnman& connman);
|
void ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, CConnman& connman);
|
||||||
|
|
||||||
|
bool IsDenomSkipped(const CAmount& nDenomValue);
|
||||||
|
void AddSkippedDenom(const CAmount& nDenomValue);
|
||||||
void ClearSkippedDenominations() { vecDenominationsSkipped.clear(); }
|
void ClearSkippedDenominations() { vecDenominationsSkipped.clear(); }
|
||||||
|
|
||||||
void SetMinBlocksToWait(int nMinBlocksToWaitIn) { nMinBlocksToWait = nMinBlocksToWaitIn; }
|
void SetMinBlocksToWait(int nMinBlocksToWaitIn) { nMinBlocksToWait = nMinBlocksToWaitIn; }
|
||||||
|
|
||||||
|
|
||||||
void ResetPool();
|
void ResetPool();
|
||||||
|
|
||||||
void UnlockCoins();
|
std::string GetStatuses();
|
||||||
|
std::string GetSessionDenoms();
|
||||||
|
|
||||||
std::string GetStatus();
|
bool GetMixingMasternodesInfo(std::vector<masternode_info_t>& vecMnInfoRet) const;
|
||||||
|
|
||||||
bool GetMixingMasternodeInfo(masternode_info_t& mnInfoRet);
|
|
||||||
bool IsMixingMasternode(const CNode* pnode);
|
|
||||||
|
|
||||||
/// 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);
|
||||||
|
|
||||||
|
void CheckTimeout();
|
||||||
|
|
||||||
void ProcessPendingDsaRequest(CConnman& connman);
|
void ProcessPendingDsaRequest(CConnman& connman);
|
||||||
|
|
||||||
void CheckTimeout();
|
void AddUsedMasternode(const COutPoint& outpointMn);
|
||||||
|
masternode_info_t GetNotUsedMasternode();
|
||||||
|
|
||||||
|
void UpdatedSuccessBlock();
|
||||||
|
|
||||||
void UpdatedBlockTip(const CBlockIndex *pindex);
|
void UpdatedBlockTip(const CBlockIndex *pindex);
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ void CPrivateSendServer::ProcessMessage(CNode* pfrom, const std::string& strComm
|
|||||||
}
|
}
|
||||||
|
|
||||||
} else if(strCommand == NetMsgType::DSQUEUE) {
|
} else if(strCommand == NetMsgType::DSQUEUE) {
|
||||||
TRY_LOCK(cs_darksend, lockRecv);
|
TRY_LOCK(cs_vecqueue, lockRecv);
|
||||||
if(!lockRecv) return;
|
if(!lockRecv) return;
|
||||||
|
|
||||||
if(pfrom->nVersion < MIN_PRIVATESEND_PEER_PROTO_VERSION) {
|
if(pfrom->nVersion < MIN_PRIVATESEND_PEER_PROTO_VERSION) {
|
||||||
@ -282,7 +282,8 @@ void CPrivateSendServer::SetNull()
|
|||||||
// MN side
|
// MN side
|
||||||
vecSessionCollaterals.clear();
|
vecSessionCollaterals.clear();
|
||||||
|
|
||||||
CPrivateSendBase::SetNull();
|
CPrivateSendBaseSession::SetNull();
|
||||||
|
CPrivateSendBaseManager::SetNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -15,7 +15,7 @@ extern CPrivateSendServer privateSendServer;
|
|||||||
|
|
||||||
/** Used to keep track of current status of mixing pool
|
/** Used to keep track of current status of mixing pool
|
||||||
*/
|
*/
|
||||||
class CPrivateSendServer : public CPrivateSendBase
|
class CPrivateSendServer : public CPrivateSendBaseSession, public CPrivateSendBaseManager
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
// Mixing uses collateral transactions to trust parties entering the pool
|
// Mixing uses collateral transactions to trust parties entering the pool
|
||||||
@ -66,8 +66,7 @@ private:
|
|||||||
void SetNull();
|
void SetNull();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CPrivateSendServer() :
|
CPrivateSendServer() : vecSessionCollaterals(), fUnitTest(false) {}
|
||||||
fUnitTest(false) { SetNull(); }
|
|
||||||
|
|
||||||
void ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, CConnman& connman);
|
void ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, CConnman& connman);
|
||||||
|
|
||||||
|
@ -183,9 +183,10 @@ bool CDarksendBroadcastTx::IsExpired(int nHeight)
|
|||||||
return (nConfirmedHeight != -1) && (nHeight - nConfirmedHeight > 24);
|
return (nConfirmedHeight != -1) && (nHeight - nConfirmedHeight > 24);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPrivateSendBase::SetNull()
|
void CPrivateSendBaseSession::SetNull()
|
||||||
{
|
{
|
||||||
// Both sides
|
// Both sides
|
||||||
|
LOCK(cs_darksend);
|
||||||
nState = POOL_STATE_IDLE;
|
nState = POOL_STATE_IDLE;
|
||||||
nSessionID = 0;
|
nSessionID = 0;
|
||||||
nSessionDenom = 0;
|
nSessionDenom = 0;
|
||||||
@ -196,22 +197,44 @@ void CPrivateSendBase::SetNull()
|
|||||||
nTimeLastSuccessfulStep = GetTime();
|
nTimeLastSuccessfulStep = GetTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPrivateSendBase::CheckQueue()
|
void CPrivateSendBaseManager::SetNull()
|
||||||
{
|
{
|
||||||
TRY_LOCK(cs_darksend, lockDS);
|
LOCK(cs_vecqueue);
|
||||||
|
vecDarksendQueue.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPrivateSendBaseManager::CheckQueue()
|
||||||
|
{
|
||||||
|
TRY_LOCK(cs_vecqueue, lockDS);
|
||||||
if(!lockDS) return; // it's ok to fail here, we run this quite frequently
|
if(!lockDS) return; // it's ok to fail here, we run this quite frequently
|
||||||
|
|
||||||
// check mixing queue objects for timeouts
|
// check mixing queue objects for timeouts
|
||||||
std::vector<CDarksendQueue>::iterator it = vecDarksendQueue.begin();
|
std::vector<CDarksendQueue>::iterator it = vecDarksendQueue.begin();
|
||||||
while(it != vecDarksendQueue.end()) {
|
while(it != vecDarksendQueue.end()) {
|
||||||
if((*it).IsExpired()) {
|
if((*it).IsExpired()) {
|
||||||
LogPrint("privatesend", "CPrivateSendBase::%s -- Removing expired queue (%s)\n", __func__, (*it).ToString());
|
LogPrint("privatesend", "CPrivateSendBaseManager::%s -- Removing expired queue (%s)\n", __func__, (*it).ToString());
|
||||||
it = vecDarksendQueue.erase(it);
|
it = vecDarksendQueue.erase(it);
|
||||||
} else ++it;
|
} else ++it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string CPrivateSendBase::GetStateString() const
|
bool CPrivateSendBaseManager::GetQueueItemAndTry(CDarksendQueue& dsqRet)
|
||||||
|
{
|
||||||
|
TRY_LOCK(cs_vecqueue, lockDS);
|
||||||
|
if(!lockDS) return false; // it's ok to fail here, we run this quite frequently
|
||||||
|
|
||||||
|
for (auto& dsq : vecDarksendQueue) {
|
||||||
|
// only try each queue once
|
||||||
|
if(dsq.fTried || dsq.IsExpired()) continue;
|
||||||
|
dsq.fTried = true;
|
||||||
|
dsqRet = dsq;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string CPrivateSendBaseSession::GetStateString() const
|
||||||
{
|
{
|
||||||
switch(nState) {
|
switch(nState) {
|
||||||
case POOL_STATE_IDLE: return "IDLE";
|
case POOL_STATE_IDLE: return "IDLE";
|
||||||
@ -504,5 +527,5 @@ void CPrivateSend::SyncTransaction(const CTransaction& tx, const CBlockIndex *pi
|
|||||||
|
|
||||||
// When tx is 0-confirmed or conflicted, posInBlock is SYNC_TRANSACTION_NOT_IN_BLOCK and nConfirmedHeight should be set to -1
|
// When tx is 0-confirmed or conflicted, posInBlock is SYNC_TRANSACTION_NOT_IN_BLOCK and nConfirmedHeight should be set to -1
|
||||||
mapDSTX[txHash].SetConfirmedHeight(posInBlock == CMainSignals::SYNC_TRANSACTION_NOT_IN_BLOCK ? -1 : pindex->nHeight);
|
mapDSTX[txHash].SetConfirmedHeight(posInBlock == CMainSignals::SYNC_TRANSACTION_NOT_IN_BLOCK ? -1 : pindex->nHeight);
|
||||||
LogPrint("privatesend", "CPrivateSendClient::SyncTransaction -- txid=%s\n", txHash.ToString());
|
LogPrint("privatesend", "CPrivateSend::SyncTransaction -- txid=%s\n", txHash.ToString());
|
||||||
}
|
}
|
||||||
|
@ -348,14 +348,11 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
// base class
|
// base class
|
||||||
class CPrivateSendBase
|
class CPrivateSendBaseSession
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
mutable CCriticalSection cs_darksend;
|
mutable CCriticalSection cs_darksend;
|
||||||
|
|
||||||
// The current mixing sessions in progress on the network
|
|
||||||
std::vector<CDarksendQueue> vecDarksendQueue;
|
|
||||||
|
|
||||||
std::vector<CDarkSendEntry> vecEntries; // Masternode/clients entries
|
std::vector<CDarkSendEntry> vecEntries; // Masternode/clients entries
|
||||||
|
|
||||||
PoolState nState; // should be one of the POOL_STATE_XXX values
|
PoolState nState; // should be one of the POOL_STATE_XXX values
|
||||||
@ -366,21 +363,47 @@ protected:
|
|||||||
CMutableTransaction finalMutableTransaction; // the finalized transaction ready for signing
|
CMutableTransaction finalMutableTransaction; // the finalized transaction ready for signing
|
||||||
|
|
||||||
void SetNull();
|
void SetNull();
|
||||||
void CheckQueue();
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int nSessionDenom; //Users must submit an denom matching this
|
int nSessionDenom; //Users must submit a denom matching this
|
||||||
int nSessionInputCount; //Users must submit a count matching this
|
int nSessionInputCount; //Users must submit a count matching this
|
||||||
|
|
||||||
CPrivateSendBase() { SetNull(); }
|
CPrivateSendBaseSession() :
|
||||||
|
vecEntries(),
|
||||||
|
nState(POOL_STATE_IDLE),
|
||||||
|
nTimeLastSuccessfulStep(0),
|
||||||
|
nSessionID(0),
|
||||||
|
finalMutableTransaction(),
|
||||||
|
nSessionDenom(0),
|
||||||
|
nSessionInputCount(0)
|
||||||
|
{}
|
||||||
|
CPrivateSendBaseSession(const CPrivateSendBaseSession& other) { /* dummy copy constructor*/ SetNull(); }
|
||||||
|
|
||||||
int GetQueueSize() const { return vecDarksendQueue.size(); }
|
|
||||||
int GetState() const { return nState; }
|
int GetState() const { return nState; }
|
||||||
std::string GetStateString() const;
|
std::string GetStateString() const;
|
||||||
|
|
||||||
int GetEntriesCount() const { return vecEntries.size(); }
|
int GetEntriesCount() const { return vecEntries.size(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// base class
|
||||||
|
class CPrivateSendBaseManager
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
mutable CCriticalSection cs_vecqueue;
|
||||||
|
|
||||||
|
// The current mixing sessions in progress on the network
|
||||||
|
std::vector<CDarksendQueue> vecDarksendQueue;
|
||||||
|
|
||||||
|
void SetNull();
|
||||||
|
void CheckQueue();
|
||||||
|
|
||||||
|
public:
|
||||||
|
CPrivateSendBaseManager() : vecDarksendQueue() {}
|
||||||
|
|
||||||
|
int GetQueueSize() const { return vecDarksendQueue.size(); }
|
||||||
|
bool GetQueueItemAndTry(CDarksendQueue& dsqRet);
|
||||||
|
};
|
||||||
|
|
||||||
// helper class
|
// helper class
|
||||||
class CPrivateSend
|
class CPrivateSend
|
||||||
{
|
{
|
||||||
|
@ -564,7 +564,7 @@ void OverviewPage::privateSendStatus()
|
|||||||
updatePrivateSendProgress();
|
updatePrivateSendProgress();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString strStatus = QString(privateSendClient.GetStatus().c_str());
|
QString strStatus = QString(privateSendClient.GetStatuses().c_str());
|
||||||
|
|
||||||
QString s = tr("Last PrivateSend message:\n") + strStatus;
|
QString s = tr("Last PrivateSend message:\n") + strStatus;
|
||||||
|
|
||||||
@ -573,13 +573,7 @@ void OverviewPage::privateSendStatus()
|
|||||||
|
|
||||||
ui->labelPrivateSendLastMessage->setText(s);
|
ui->labelPrivateSendLastMessage->setText(s);
|
||||||
|
|
||||||
if(privateSendClient.nSessionDenom == 0){
|
ui->labelSubmittedDenom->setText(QString(privateSendClient.GetSessionDenoms().c_str()));
|
||||||
ui->labelSubmittedDenom->setText(tr("N/A"));
|
|
||||||
} else {
|
|
||||||
QString strDenom(CPrivateSend::GetDenominationsToString(privateSendClient.nSessionDenom).c_str());
|
|
||||||
ui->labelSubmittedDenom->setText(strDenom);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OverviewPage::privateSendAuto(){
|
void OverviewPage::privateSendAuto(){
|
||||||
@ -642,7 +636,7 @@ void OverviewPage::togglePrivateSend(){
|
|||||||
|
|
||||||
if(!privateSendClient.fEnablePrivateSend){
|
if(!privateSendClient.fEnablePrivateSend){
|
||||||
ui->togglePrivateSend->setText(tr("Start Mixing"));
|
ui->togglePrivateSend->setText(tr("Start Mixing"));
|
||||||
privateSendClient.UnlockCoins();
|
privateSendClient.ResetPool();
|
||||||
} else {
|
} else {
|
||||||
ui->togglePrivateSend->setText(tr("Stop Mixing"));
|
ui->togglePrivateSend->setText(tr("Stop Mixing"));
|
||||||
}
|
}
|
||||||
|
@ -63,7 +63,7 @@ UniValue privatesend(const JSONRPCRequest& request)
|
|||||||
|
|
||||||
privateSendClient.fEnablePrivateSend = true;
|
privateSendClient.fEnablePrivateSend = true;
|
||||||
bool result = privateSendClient.DoAutomaticDenominating(*g_connman);
|
bool result = privateSendClient.DoAutomaticDenominating(*g_connman);
|
||||||
return "Mixing " + (result ? "started successfully" : ("start failed: " + privateSendClient.GetStatus() + ", 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") {
|
||||||
@ -88,19 +88,25 @@ UniValue getpoolinfo(const JSONRPCRequest& request)
|
|||||||
"Returns an object containing mixing pool related information.\n");
|
"Returns an object containing mixing pool related information.\n");
|
||||||
|
|
||||||
#ifdef ENABLE_WALLET
|
#ifdef ENABLE_WALLET
|
||||||
CPrivateSendBase* pprivateSendBase = fMasternodeMode ? (CPrivateSendBase*)&privateSendServer : (CPrivateSendBase*)&privateSendClient;
|
CPrivateSendBaseManager* pprivateSendBaseManager = fMasternodeMode ? (CPrivateSendBaseManager*)&privateSendServer : (CPrivateSendBaseManager*)&privateSendClient;
|
||||||
|
|
||||||
UniValue obj(UniValue::VOBJ);
|
UniValue obj(UniValue::VOBJ);
|
||||||
obj.push_back(Pair("state", pprivateSendBase->GetStateString()));
|
// TODO:
|
||||||
obj.push_back(Pair("mixing_mode", (!fMasternodeMode && privateSendClient.fPrivateSendMultiSession) ? "multi-session" : "normal"));
|
// obj.push_back(Pair("state", pprivateSendBase->GetStateString()));
|
||||||
obj.push_back(Pair("queue", pprivateSendBase->GetQueueSize()));
|
obj.push_back(Pair("queue", pprivateSendBaseManager->GetQueueSize()));
|
||||||
obj.push_back(Pair("entries", pprivateSendBase->GetEntriesCount()));
|
// obj.push_back(Pair("entries", pprivateSendBase->GetEntriesCount()));
|
||||||
obj.push_back(Pair("status", privateSendClient.GetStatus()));
|
obj.push_back(Pair("status", privateSendClient.GetStatuses()));
|
||||||
|
|
||||||
masternode_info_t mnInfo;
|
std::vector<masternode_info_t> vecMnInfo;
|
||||||
if (privateSendClient.GetMixingMasternodeInfo(mnInfo)) {
|
if (privateSendClient.GetMixingMasternodesInfo(vecMnInfo)) {
|
||||||
obj.push_back(Pair("outpoint", mnInfo.outpoint.ToStringShort()));
|
UniValue pools(UniValue::VARR);
|
||||||
obj.push_back(Pair("addr", mnInfo.addr.ToString()));
|
for (const auto& mnInfo : vecMnInfo) {
|
||||||
|
UniValue pool(UniValue::VOBJ);
|
||||||
|
pool.push_back(Pair("outpoint", mnInfo.outpoint.ToStringShort()));
|
||||||
|
pool.push_back(Pair("addr", mnInfo.addr.ToString()));
|
||||||
|
pools.push_back(pool);
|
||||||
|
}
|
||||||
|
obj.push_back(Pair("pools", pools));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pwalletMain) {
|
if (pwalletMain) {
|
||||||
|
Loading…
Reference in New Issue
Block a user