Skip to content
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

Backport 12610 + PrivateSend multiwallet support. #3604

Merged
merged 13 commits into from
Jul 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/dsnotificationinterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,9 @@ void CDSNotificationInterface::UpdatedBlockTip(const CBlockIndex *pindexNew, con

CPrivateSend::UpdatedBlockTip(pindexNew);
#ifdef ENABLE_WALLET
privateSendClient.UpdatedBlockTip(pindexNew);
for (auto& pair : privateSendClientManagers) {
pair.second->UpdatedBlockTip(pindexNew);
}
#endif // ENABLE_WALLET

llmq::quorumInstantSendManager->UpdatedBlockTip(pindexNew);
Expand Down
3 changes: 3 additions & 0 deletions src/httprpc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,9 @@ void StopHTTPRPC()
{
LogPrint(BCLog::RPC, "Stopping HTTP RPC server\n");
UnregisterHTTPHandler("/", true);
#ifdef ENABLE_WALLET
UnregisterHTTPHandler("/wallet/", false);
#endif
if (httpRPCTimerInterface) {
RPCUnsetTimerInterface(httpRPCTimerInterface.get());
httpRPCTimerInterface.reset();
Expand Down
4 changes: 3 additions & 1 deletion src/masternode/masternode-utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ void CMasternodeUtils::ProcessMasternodeConnections(CConnman& connman)
{
std::vector<CDeterministicMNCPtr> vecDmns; // will be empty when no wallet
#ifdef ENABLE_WALLET
privateSendClient.GetMixingMasternodesInfo(vecDmns);
for (const auto& pair : privateSendClientManagers) {
pair.second->GetMixingMasternodesInfo(vecDmns);
}
#endif // ENABLE_WALLET

// Don't disconnect masternode connections when we have less then the desired amount of outbound nodes
Expand Down
5 changes: 4 additions & 1 deletion src/net_processing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3542,7 +3542,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
{
//probably one the extensions
#ifdef ENABLE_WALLET
privateSendClient.ProcessMessage(pfrom, strCommand, vRecv, *connman, enable_bip61);
privateSendClientQueueManager.ProcessMessage(pfrom, strCommand, vRecv, *connman, enable_bip61);
for (auto& pair : privateSendClientManagers) {
pair.second->ProcessMessage(pfrom, strCommand, vRecv, *connman, enable_bip61);
}
#endif // ENABLE_WALLET
privateSendServer.ProcessMessage(pfrom, strCommand, vRecv, *connman, enable_bip61);
sporkManager.ProcessSpork(pfrom, strCommand, vRecv, *connman);
Expand Down
367 changes: 246 additions & 121 deletions src/privatesend/privatesend-client.cpp

Large diffs are not rendered by default.

107 changes: 86 additions & 21 deletions src/privatesend/privatesend-client.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,13 @@

#include <evo/deterministicmns.h>

class CPrivateSendClientOptions;
class CPrivateSendClientManager;
class CPrivateSendClientQueueManager;

class CConnman;
class CNode;

class UniValue;

static const int MIN_PRIVATESEND_SESSIONS = 1;
Expand Down Expand Up @@ -52,7 +56,10 @@ static const int PRIVATESEND_KEYS_THRESHOLD_WARNING = 100;
static const int PRIVATESEND_KEYS_THRESHOLD_STOP = 50;

// The main object for accessing mixing
extern CPrivateSendClientManager privateSendClient;
extern std::map<const std::string, CPrivateSendClientManager*> privateSendClientManagers;

// The object to track mixing queues
extern CPrivateSendClientQueueManager privateSendClientQueueManager;

class CPendingDsaRequest
{
Expand Down Expand Up @@ -110,6 +117,8 @@ class CPrivateSendClientSession : public CPrivateSendBaseSession

CKeyHolderStorage keyHolderStorage; // storage for keys used in PrepareDenominate

CWallet* mixingWallet;

/// Create denominations
bool CreateDenominated(CAmount nBalanceToDenominate, CConnman& connman);
bool CreateDenominated(CAmount nBalanceToDenominate, const CompactTallyItem& tallyItem, bool fCreateMixingCollaterals, CConnman& connman);
Expand Down Expand Up @@ -143,14 +152,15 @@ class CPrivateSendClientSession : public CPrivateSendBaseSession
void SetNull();

public:
CPrivateSendClientSession() :
CPrivateSendClientSession(CWallet* pwallet) :
vecOutPointLocked(),
strLastMessage(),
strAutoDenomResult(),
mixingMasternode(),
txMyCollateral(),
pendingDsaRequest(),
keyHolderStorage()
keyHolderStorage(),
mixingWallet(pwallet)
{
}

Expand All @@ -177,9 +187,19 @@ class CPrivateSendClientSession : public CPrivateSendBaseSession
void GetJsonInfo(UniValue& obj) const;
};

/** Used to keep track of mixing queues
*/
class CPrivateSendClientQueueManager : public CPrivateSendBaseManager
{
public:
void ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, CConnman& connman, bool enable_bip61);

void DoMaintenance();
};

/** Used to keep track of current status of mixing pool
*/
class CPrivateSendClientManager : public CPrivateSendBaseManager
class CPrivateSendClientManager
{
private:
// Keep track of the used Masternodes
Expand All @@ -193,6 +213,8 @@ class CPrivateSendClientManager : public CPrivateSendBaseManager
int nMinBlocksToWait; // how many blocks to wait after one successful mixing tx in non-multisession mode
std::string strAutoDenomResult;

CWallet* mixingWallet;

// Keep track of current block height
int nCachedBlockHeight;

Expand All @@ -202,15 +224,6 @@ class CPrivateSendClientManager : public CPrivateSendBaseManager
bool CheckAutomaticBackup();

public:
int nPrivateSendSessions;
int nPrivateSendRounds;
int nPrivateSendAmount;
int nPrivateSendDenomsGoal;
int nPrivateSendDenomsHardCap;
bool fEnablePrivateSend;
bool fPrivateSendRunning;
bool fPrivateSendMultiSession;

int nCachedNumBlocks; //used for the overview screen
bool fCreateAutoBackups; //builtin support for automatic backups

Expand All @@ -221,20 +234,17 @@ class CPrivateSendClientManager : public CPrivateSendBaseManager
nMinBlocksToWait(1),
strAutoDenomResult(),
nCachedBlockHeight(0),
nPrivateSendRounds(DEFAULT_PRIVATESEND_ROUNDS),
nPrivateSendAmount(DEFAULT_PRIVATESEND_AMOUNT),
nPrivateSendDenomsGoal(DEFAULT_PRIVATESEND_DENOMS_GOAL),
nPrivateSendDenomsHardCap(DEFAULT_PRIVATESEND_DENOMS_HARDCAP),
fEnablePrivateSend(false),
fPrivateSendRunning(false),
fPrivateSendMultiSession(DEFAULT_PRIVATESEND_MULTISESSION),
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);

bool StartMixing(CWallet* pwallet);
void StopMixing();
bool IsMixing() const;
void ResetPool();

std::string GetStatuses();
Expand All @@ -245,6 +255,9 @@ class CPrivateSendClientManager : public CPrivateSendBaseManager
/// Passively run mixing in the background according to the configuration in settings
bool DoAutomaticDenominating(CConnman& connman, bool fDryRun = false);

bool TrySubmitDenominate(const CService& mnAddr, CConnman& connman);
bool MarkAlreadyJoinedQueueAsTried(CPrivateSendQueue& dsq) const;

void CheckTimeout();

void ProcessPendingDsaRequest(CConnman& connman);
Expand All @@ -261,4 +274,56 @@ class CPrivateSendClientManager : public CPrivateSendBaseManager
void GetJsonInfo(UniValue& obj) const;
};

/* Application wide mixing options */
class CPrivateSendClientOptions
{
public:
static int GetSessions() { return CPrivateSendClientOptions::Get().nPrivateSendSessions; }
static int GetRounds() { return CPrivateSendClientOptions::Get().nPrivateSendRounds; }
static int GetAmount() { return CPrivateSendClientOptions::Get().nPrivateSendAmount; }
static int GetDenomsGoal() { return CPrivateSendClientOptions::Get().nPrivateSendDenomsGoal; }
static int GetDenomsHardCap() { return CPrivateSendClientOptions::Get().nPrivateSendDenomsHardCap; }

static void SetEnabled(bool fEnabled);
static void SetMultiSessionEnabled(bool fEnabled);
static void SetRounds(int nRounds);
static void SetAmount(CAmount amount);

static int IsEnabled() { return CPrivateSendClientOptions::Get().fEnablePrivateSend; }
static int IsMultiSessionEnabled() { return CPrivateSendClientOptions::Get().fPrivateSendMultiSession; }

static void GetJsonInfo(UniValue& obj);

private:
static CPrivateSendClientOptions* _instance;
static std::once_flag onceFlag;

CCriticalSection cs_ps_options;
int nPrivateSendSessions;
int nPrivateSendRounds;
int nPrivateSendAmount;
int nPrivateSendDenomsGoal;
int nPrivateSendDenomsHardCap;
bool fEnablePrivateSend;
bool fPrivateSendMultiSession;

CPrivateSendClientOptions() :
nPrivateSendRounds(DEFAULT_PRIVATESEND_ROUNDS),
nPrivateSendAmount(DEFAULT_PRIVATESEND_AMOUNT),
nPrivateSendDenomsGoal(DEFAULT_PRIVATESEND_DENOMS_GOAL),
nPrivateSendDenomsHardCap(DEFAULT_PRIVATESEND_DENOMS_HARDCAP),
fEnablePrivateSend(false),
fPrivateSendMultiSession(DEFAULT_PRIVATESEND_MULTISESSION)
{
}

CPrivateSendClientOptions(const CPrivateSendClientOptions& other) = delete;
CPrivateSendClientOptions& operator=(const CPrivateSendClientOptions&) = delete;

static CPrivateSendClientOptions& Get();
static void Init();
};

void DoPrivateSendMaintenance(CConnman& connman);

#endif // BITCOIN_PRIVATESEND_PRIVATESEND_CLIENT_H
70 changes: 56 additions & 14 deletions src/qt/bitcoingui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <privatesend/privatesend-client.h>
#include <qt/walletframe.h>
#include <qt/walletmodel.h>
#include <qt/walletview.h>
#endif // ENABLE_WALLET

#ifdef Q_OS_MAC
Expand All @@ -41,6 +42,7 @@
#include <QAction>
#include <QApplication>
#include <QButtonGroup>
#include <QComboBox>
#include <QDateTime>
#include <QDesktopWidget>
#include <QDragEnterEvent>
Expand Down Expand Up @@ -70,10 +72,6 @@ const std::string BitcoinGUI::DEFAULT_UIPLATFORM =
#endif
;

/** Display name for default wallet name. Uses tilde to avoid name
* collisions in the future with additional wallets */
const QString BitcoinGUI::DEFAULT_WALLET = "~Default";

BitcoinGUI::BitcoinGUI(const PlatformStyle *_platformStyle, const NetworkStyle *networkStyle, QWidget *parent) :
QMainWindow(parent),
enableWallet(false),
Expand All @@ -88,6 +86,8 @@ BitcoinGUI::BitcoinGUI(const PlatformStyle *_platformStyle, const NetworkStyle *
progressBar(0),
progressDialog(0),
appMenuBar(0),
appToolBar(0),
appToolBarLogoAction(0),
overviewAction(0),
historyAction(0),
masternodeAction(0),
Expand Down Expand Up @@ -588,6 +588,7 @@ void BitcoinGUI::createToolBars()
if(walletFrame)
{
QToolBar *toolbar = new QToolBar(tr("Tabs toolbar"));
appToolBar = toolbar;
toolbar->setContextMenuPolicy(Qt::PreventContextMenu);
toolbar->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
toolbar->setToolButtonStyle(Qt::ToolButtonTextOnly);
Expand All @@ -612,11 +613,17 @@ void BitcoinGUI::createToolBars()
toolbar->setMovable(false); // remove unused icon in upper left corner
overviewAction->setChecked(true);

#ifdef ENABLE_WALLET
m_wallet_selector = new QComboBox(this);
m_wallet_selector->setHidden(true);
connect(m_wallet_selector, SIGNAL(currentIndexChanged(const QString&)), this, SLOT(setCurrentWallet(const QString&)));
#endif

QLabel *logoLabel = new QLabel();
logoLabel->setObjectName("lblToolbarLogo");
logoLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);

toolbar->addWidget(logoLabel);
appToolBarLogoAction = toolbar->addWidget(logoLabel);

/** Create additional container for toolbar and walletFrame and make it the central widget.
This is a workaround mostly for toolbar styling on Mac OS but should work fine for every other OSes too.
Expand Down Expand Up @@ -729,12 +736,28 @@ void BitcoinGUI::setClientModel(ClientModel *_clientModel)
}

#ifdef ENABLE_WALLET
bool BitcoinGUI::addWallet(const QString& name, WalletModel *walletModel)
bool BitcoinGUI::addWallet(WalletModel *walletModel)
{
if(!walletFrame)
return false;
const QString name = walletModel->getWalletName();
setWalletActionsEnabled(true);
return walletFrame->addWallet(name, walletModel);
m_wallet_selector->addItem(name);
if (m_wallet_selector->count() == 2) {
m_wallet_selector->setHidden(false);
QVBoxLayout* layout = new QVBoxLayout(this);
layout->addWidget(m_wallet_selector);
layout->setSpacing(0);
layout->setMargin(0);
layout->setContentsMargins(5, 0, 5, 0);
QWidget* walletSelector = new QWidget(this);
walletSelector->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
walletSelector->setObjectName("walletSelector");
walletSelector->setLayout(layout);
appToolBar->insertWidget(appToolBarLogoAction, walletSelector);
}
rpcConsole->addWallet(walletModel);
return walletFrame->addWallet(walletModel);
}

bool BitcoinGUI::setCurrentWallet(const QString& name)
Expand All @@ -759,8 +782,8 @@ void BitcoinGUI::setWalletActionsEnabled(bool enabled)
sendCoinsAction->setEnabled(enabled);
sendCoinsMenuAction->setEnabled(enabled);
#ifdef ENABLE_WALLET
privateSendCoinsAction->setEnabled(enabled && privateSendClient.fEnablePrivateSend);
privateSendCoinsMenuAction->setEnabled(enabled && privateSendClient.fEnablePrivateSend);
privateSendCoinsAction->setEnabled(enabled && CPrivateSendClientOptions::IsEnabled());
privateSendCoinsMenuAction->setEnabled(enabled && CPrivateSendClientOptions::IsEnabled());
#else
privateSendCoinsAction->setEnabled(enabled);
privateSendCoinsMenuAction->setEnabled(enabled);
Expand Down Expand Up @@ -1028,7 +1051,9 @@ void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVer
// Disabling macOS App Nap on initial sync, disk, reindex operations and mixing.
bool disableAppNap = !masternodeSync.IsSynced();
#ifdef ENABLE_WALLET
disableAppNap |= privateSendClient.fPrivateSendRunning;
for (const auto& pair : privateSendClientManagers) {
disableAppNap |= pair.second->IsMixing();
}
#endif // ENABLE_WALLET
if (disableAppNap) {
m_app_nap_inhibitor->disableAppNap();
Expand Down Expand Up @@ -1317,10 +1342,10 @@ void BitcoinGUI::showEvent(QShowEvent *event)
}

#ifdef ENABLE_WALLET
void BitcoinGUI::incomingTransaction(const QString& date, int unit, const CAmount& amount, const QString& type, const QString& address, const QString& label)
void BitcoinGUI::incomingTransaction(const QString& date, int unit, const CAmount& amount, const QString& type, const QString& address, const QString& label, const QString& walletName)
{
IncomingTransactionMessage itx = {
date, unit, amount, type, address, label
date, unit, amount, type, address, label, walletName
};
incomingTransactions.emplace_back(itx);

Expand Down Expand Up @@ -1386,8 +1411,11 @@ void BitcoinGUI::showIncomingTransactions()
for (auto& itx : txs) {
// On new transaction, make an info balloon
QString msg = tr("Date: %1\n").arg(itx.date) +
tr("Amount: %1\n").arg(BitcoinUnits::formatWithUnit(itx.unit, itx.amount, true)) +
tr("Type: %1\n").arg(itx.type);
tr("Amount: %1\n").arg(BitcoinUnits::formatWithUnit(itx.unit, itx.amount, true));
if (WalletModel::isMultiwallet() && !itx.walletName.isEmpty()) {
msg += tr("Wallet: %1\n").arg(itx.walletName);
}
msg += tr("Type: %1\n").arg(itx.type);
if (!itx.label.isEmpty())
msg += tr("Label: %1\n").arg(itx.label);
else if (!itx.address.isEmpty())
Expand Down Expand Up @@ -1496,6 +1524,20 @@ void BitcoinGUI::setEncryptionStatus(int status)
break;
}
}

void BitcoinGUI::updateWalletStatus()
{
if (!walletFrame) {
return;
}
WalletView * const walletView = walletFrame->currentWalletView();
if (!walletView) {
return;
}
WalletModel * const walletModel = walletView->getWalletModel();
setEncryptionStatus(walletModel->getEncryptionStatus());
setHDStatus(walletModel->hdEnabled());
}
#endif // ENABLE_WALLET

void BitcoinGUI::showNormalIfMinimized(bool fToggleHidden)
Expand Down