diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/chainparams.cpp | 1 | ||||
-rw-r--r-- | src/httprpc.cpp | 3 | ||||
-rw-r--r-- | src/init.cpp | 11 | ||||
-rw-r--r-- | src/miner.cpp | 4 | ||||
-rw-r--r-- | src/qt/bitcoin.cpp | 26 | ||||
-rw-r--r-- | src/qt/bitcoingui.cpp | 54 | ||||
-rw-r--r-- | src/qt/bitcoingui.h | 18 | ||||
-rw-r--r-- | src/qt/forms/debugwindow.ui | 16 | ||||
-rw-r--r-- | src/qt/receivecoinsdialog.cpp | 4 | ||||
-rw-r--r-- | src/qt/receiverequestdialog.cpp | 9 | ||||
-rw-r--r-- | src/qt/receiverequestdialog.h | 6 | ||||
-rw-r--r-- | src/qt/rpcconsole.cpp | 58 | ||||
-rw-r--r-- | src/qt/rpcconsole.h | 11 | ||||
-rw-r--r-- | src/qt/sendcoinsdialog.cpp | 5 | ||||
-rw-r--r-- | src/qt/walletframe.cpp | 11 | ||||
-rw-r--r-- | src/qt/walletframe.h | 3 | ||||
-rw-r--r-- | src/qt/walletmodel.cpp | 20 | ||||
-rw-r--r-- | src/qt/walletmodel.h | 7 | ||||
-rw-r--r-- | src/qt/walletview.cpp | 14 | ||||
-rw-r--r-- | src/qt/walletview.h | 7 | ||||
-rw-r--r-- | src/wallet/wallet.cpp | 37 |
21 files changed, 234 insertions, 91 deletions
diff --git a/src/chainparams.cpp b/src/chainparams.cpp index c2b3480f9d..6067503b0b 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -135,6 +135,7 @@ public: vSeeds.emplace_back("seed.bitcoinstats.com"); // Christian Decker, supports x1 - xf vSeeds.emplace_back("seed.bitcoin.jonasschnelli.ch"); // Jonas Schnelli, only supports x1, x5, x9, and xd vSeeds.emplace_back("seed.btc.petertodd.org"); // Peter Todd, only supports x1, x5, x9, and xd + vSeeds.emplace_back("seed.bitcoin.sprovoost.nl"); // Sjors Provoost base58Prefixes[PUBKEY_ADDRESS] = std::vector<unsigned char>(1,0); base58Prefixes[SCRIPT_ADDRESS] = std::vector<unsigned char>(1,5); diff --git a/src/httprpc.cpp b/src/httprpc.cpp index 82ae733006..ed0a030701 100644 --- a/src/httprpc.cpp +++ b/src/httprpc.cpp @@ -252,6 +252,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(); diff --git a/src/init.cpp b/src/init.cpp index 30ee0e694c..e5443eef0e 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -491,8 +491,6 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-whitelistrelay", strprintf(_("Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d)"), DEFAULT_WHITELISTRELAY)); strUsage += HelpMessageGroup(_("Block creation options:")); - if (showDebug) - strUsage += HelpMessageOpt("-blockmaxsize=<n>", "Set maximum BIP141 block weight to this * 4. Deprecated, use blockmaxweight"); strUsage += HelpMessageOpt("-blockmaxweight=<n>", strprintf(_("Set maximum BIP141 block weight (default: %d)"), DEFAULT_BLOCK_MAX_WEIGHT)); strUsage += HelpMessageOpt("-blockmintxfee=<amt>", strprintf(_("Set lowest fee rate (in %s/kB) for transactions to be included in block creation. (default: %s)"), CURRENCY_UNIT, FormatMoney(DEFAULT_BLOCK_MIN_TX_FEE))); if (showDebug) @@ -798,15 +796,6 @@ void InitParameterInteraction() if (gArgs.SoftSetBoolArg("-whitelistrelay", true)) LogPrintf("%s: parameter interaction: -whitelistforcerelay=1 -> setting -whitelistrelay=1\n", __func__); } - - if (gArgs.IsArgSet("-blockmaxsize")) { - unsigned int max_size = gArgs.GetArg("-blockmaxsize", 0); - if (gArgs.SoftSetArg("blockmaxweight", strprintf("%d", max_size * WITNESS_SCALE_FACTOR))) { - LogPrintf("%s: parameter interaction: -blockmaxsize=%d -> setting -blockmaxweight=%d (-blockmaxsize is deprecated!)\n", __func__, max_size, max_size * WITNESS_SCALE_FACTOR); - } else { - LogPrintf("%s: Ignoring blockmaxsize setting which is overridden by blockmaxweight", __func__); - } - } } static std::string ResolveErrMsg(const char * const optname, const std::string& strBind) diff --git a/src/miner.cpp b/src/miner.cpp index 4b86446774..0660df928c 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -68,9 +68,7 @@ BlockAssembler::BlockAssembler(const CChainParams& params, const Options& option static BlockAssembler::Options DefaultOptions(const CChainParams& params) { // Block resource limits - // If neither -blockmaxsize or -blockmaxweight is given, limit to DEFAULT_BLOCK_MAX_* - // If only one is given, only restrict the specified resource. - // If both are given, restrict both. + // If -blockmaxweight is not given, limit to DEFAULT_BLOCK_MAX_WEIGHT BlockAssembler::Options options; options.nBlockMaxWeight = gArgs.GetArg("-blockmaxweight", DEFAULT_BLOCK_MAX_WEIGHT); if (gArgs.IsArgSet("-blockmintxfee")) { diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index ab381bfb5d..df1be35c8d 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -251,7 +251,7 @@ private: QTimer *pollShutdownTimer; #ifdef ENABLE_WALLET PaymentServer* paymentServer; - WalletModel *walletModel; + std::vector<WalletModel*> m_wallet_models; #endif int returnValue; const PlatformStyle *platformStyle; @@ -333,7 +333,7 @@ BitcoinApplication::BitcoinApplication(int &argc, char **argv): pollShutdownTimer(0), #ifdef ENABLE_WALLET paymentServer(0), - walletModel(0), + m_wallet_models(), #endif returnValue(0) { @@ -451,8 +451,10 @@ void BitcoinApplication::requestShutdown() #ifdef ENABLE_WALLET window->removeAllWallets(); - delete walletModel; - walletModel = 0; + for (WalletModel *walletModel : m_wallet_models) { + delete walletModel; + } + m_wallet_models.clear(); #endif delete clientModel; clientModel = 0; @@ -481,16 +483,20 @@ void BitcoinApplication::initializeResult(bool success) window->setClientModel(clientModel); #ifdef ENABLE_WALLET - // TODO: Expose secondary wallets - if (!vpwallets.empty()) - { - walletModel = new WalletModel(platformStyle, vpwallets[0], optionsModel); + bool fFirstWallet = true; + for (CWalletRef pwallet : vpwallets) { + WalletModel * const walletModel = new WalletModel(platformStyle, pwallet, optionsModel); - window->addWallet(BitcoinGUI::DEFAULT_WALLET, walletModel); - window->setCurrentWallet(BitcoinGUI::DEFAULT_WALLET); + window->addWallet(walletModel); + if (fFirstWallet) { + window->setCurrentWallet(walletModel->getWalletName()); + fFirstWallet = false; + } connect(walletModel, SIGNAL(coinsSent(CWallet*,SendCoinsRecipient,QByteArray)), paymentServer, SLOT(fetchPaymentACK(CWallet*,const SendCoinsRecipient&,QByteArray))); + + m_wallet_models.push_back(walletModel); } #endif diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 427eb95a84..4707fcceb9 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -21,6 +21,7 @@ #ifdef ENABLE_WALLET #include <qt/walletframe.h> #include <qt/walletmodel.h> +#include <qt/walletview.h> #endif // ENABLE_WALLET #ifdef Q_OS_MAC @@ -36,6 +37,7 @@ #include <QAction> #include <QApplication> +#include <QComboBox> #include <QDateTime> #include <QDesktopWidget> #include <QDragEnterEvent> @@ -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), @@ -88,6 +86,7 @@ BitcoinGUI::BitcoinGUI(const PlatformStyle *_platformStyle, const NetworkStyle * progressBar(0), progressDialog(0), appMenuBar(0), + appToolBar(0), overviewAction(0), historyAction(0), quitAction(0), @@ -455,6 +454,7 @@ void BitcoinGUI::createToolBars() if(walletFrame) { QToolBar *toolbar = addToolBar(tr("Tabs toolbar")); + appToolBar = toolbar; toolbar->setContextMenuPolicy(Qt::PreventContextMenu); toolbar->setMovable(false); toolbar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); @@ -463,6 +463,15 @@ void BitcoinGUI::createToolBars() toolbar->addAction(receiveCoinsAction); toolbar->addAction(historyAction); overviewAction->setChecked(true); + +#ifdef ENABLE_WALLET + QWidget *spacer = new QWidget(); + spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + toolbar->addWidget(spacer); + + m_wallet_selector = new QComboBox(); + connect(m_wallet_selector, SIGNAL(currentIndexChanged(const QString&)), this, SLOT(setCurrentWallet(const QString&))); +#endif } } @@ -529,12 +538,22 @@ 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_label = new QLabel(); + m_wallet_selector_label->setText(tr("Wallet:") + " "); + m_wallet_selector_label->setBuddy(m_wallet_selector); + appToolBar->addWidget(m_wallet_selector_label); + appToolBar->addWidget(m_wallet_selector); + } + rpcConsole->addWallet(walletModel); + return walletFrame->addWallet(walletModel); } bool BitcoinGUI::setCurrentWallet(const QString& name) @@ -983,12 +1002,15 @@ 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) { // On new transaction, make an info balloon QString msg = tr("Date: %1\n").arg(date) + - tr("Amount: %1\n").arg(BitcoinUnits::formatWithUnit(unit, amount, true)) + - tr("Type: %1\n").arg(type); + tr("Amount: %1\n").arg(BitcoinUnits::formatWithUnit(unit, amount, true)); + if (WalletModel::isMultiwallet() && !walletName.isEmpty()) { + msg += tr("Wallet: %1\n").arg(walletName); + } + msg += tr("Type: %1\n").arg(type); if (!label.isEmpty()) msg += tr("Label: %1\n").arg(label); else if (!address.isEmpty()) @@ -1079,6 +1101,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) diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index ddb7ecb76a..b9e92f2d5b 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -33,6 +33,7 @@ class ModalOverlay; QT_BEGIN_NAMESPACE class QAction; +class QComboBox; class QProgressBar; class QProgressDialog; QT_END_NAMESPACE @@ -46,7 +47,6 @@ class BitcoinGUI : public QMainWindow Q_OBJECT public: - static const QString DEFAULT_WALLET; static const std::string DEFAULT_UIPLATFORM; explicit BitcoinGUI(const PlatformStyle *platformStyle, const NetworkStyle *networkStyle, QWidget *parent = 0); @@ -62,8 +62,7 @@ public: The wallet model represents a bitcoin wallet, and offers access to the list of transactions, address book and sending functionality. */ - bool addWallet(const QString& name, WalletModel *walletModel); - bool setCurrentWallet(const QString& name); + bool addWallet(WalletModel *walletModel); void removeAllWallets(); #endif // ENABLE_WALLET bool enableWallet; @@ -90,6 +89,7 @@ private: QProgressDialog *progressDialog; QMenuBar *appMenuBar; + QToolBar *appToolBar; QAction *overviewAction; QAction *historyAction; QAction *quitAction; @@ -112,6 +112,9 @@ private: QAction *openAction; QAction *showHelpMessageAction; + QLabel *m_wallet_selector_label; + QComboBox *m_wallet_selector; + QSystemTrayIcon *trayIcon; QMenu *trayIconMenu; Notificator *notificator; @@ -171,6 +174,12 @@ public Q_SLOTS: void message(const QString &title, const QString &message, unsigned int style, bool *ret = nullptr); #ifdef ENABLE_WALLET + bool setCurrentWallet(const QString& name); + /** Set the UI status indicators based on the currently selected wallet. + */ + void updateWalletStatus(); + +private: /** Set the encryption status as shown in the UI. @param[in] status current encryption status @see WalletModel::EncryptionStatus @@ -183,10 +192,11 @@ public Q_SLOTS: */ void setHDStatus(int hdEnabled); +public Q_SLOTS: bool handlePaymentRequest(const SendCoinsRecipient& recipient); /** Show incoming transaction notification for new transactions. */ - void incomingTransaction(const QString& date, int unit, const CAmount& amount, const QString& type, const QString& address, const QString& label); + void incomingTransaction(const QString& date, int unit, const CAmount& amount, const QString& type, const QString& address, const QString& label, const QString& walletName); #endif // ENABLE_WALLET private Q_SLOTS: diff --git a/src/qt/forms/debugwindow.ui b/src/qt/forms/debugwindow.ui index bba822882e..695ed61228 100644 --- a/src/qt/forms/debugwindow.ui +++ b/src/qt/forms/debugwindow.ui @@ -413,6 +413,22 @@ <number>4</number> </property> <item> + <widget class="QLabel" name="WalletSelectorLabel"> + <property name="text"> + <string>Wallet: </string> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="WalletSelector"> + <item> + <property name="text"> + <string>(none)</string> + </property> + </item> + </widget> + </item> + <item> <spacer name="horizontalSpacer"> <property name="orientation"> <enum>Qt::Horizontal</enum> diff --git a/src/qt/receivecoinsdialog.cpp b/src/qt/receivecoinsdialog.cpp index 132fb54d66..c8b6366db0 100644 --- a/src/qt/receivecoinsdialog.cpp +++ b/src/qt/receivecoinsdialog.cpp @@ -153,7 +153,7 @@ void ReceiveCoinsDialog::on_receiveButton_clicked() ui->reqAmount->value(), ui->reqMessage->text()); ReceiveRequestDialog *dialog = new ReceiveRequestDialog(this); dialog->setAttribute(Qt::WA_DeleteOnClose); - dialog->setModel(model->getOptionsModel()); + dialog->setModel(model); dialog->setInfo(info); dialog->show(); clear(); @@ -166,7 +166,7 @@ void ReceiveCoinsDialog::on_recentRequestsView_doubleClicked(const QModelIndex & { const RecentRequestsTableModel *submodel = model->getRecentRequestsTableModel(); ReceiveRequestDialog *dialog = new ReceiveRequestDialog(this); - dialog->setModel(model->getOptionsModel()); + dialog->setModel(model); dialog->setInfo(submodel->entry(index.row()).recipient); dialog->setAttribute(Qt::WA_DeleteOnClose); dialog->show(); diff --git a/src/qt/receiverequestdialog.cpp b/src/qt/receiverequestdialog.cpp index d4cb0e5ba2..75146e2214 100644 --- a/src/qt/receiverequestdialog.cpp +++ b/src/qt/receiverequestdialog.cpp @@ -108,12 +108,12 @@ ReceiveRequestDialog::~ReceiveRequestDialog() delete ui; } -void ReceiveRequestDialog::setModel(OptionsModel *_model) +void ReceiveRequestDialog::setModel(WalletModel *_model) { this->model = _model; if (_model) - connect(_model, SIGNAL(displayUnitChanged(int)), this, SLOT(update())); + connect(_model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(update())); // update the display unit if necessary update(); @@ -143,11 +143,14 @@ void ReceiveRequestDialog::update() html += "<a href=\""+uri+"\">" + GUIUtil::HtmlEscape(uri) + "</a><br>"; html += "<b>"+tr("Address")+"</b>: " + GUIUtil::HtmlEscape(info.address) + "<br>"; if(info.amount) - html += "<b>"+tr("Amount")+"</b>: " + BitcoinUnits::formatHtmlWithUnit(model->getDisplayUnit(), info.amount) + "<br>"; + html += "<b>"+tr("Amount")+"</b>: " + BitcoinUnits::formatHtmlWithUnit(model->getOptionsModel()->getDisplayUnit(), info.amount) + "<br>"; if(!info.label.isEmpty()) html += "<b>"+tr("Label")+"</b>: " + GUIUtil::HtmlEscape(info.label) + "<br>"; if(!info.message.isEmpty()) html += "<b>"+tr("Message")+"</b>: " + GUIUtil::HtmlEscape(info.message) + "<br>"; + if(model->isMultiwallet()) { + html += "<b>"+tr("Wallet")+"</b>: " + GUIUtil::HtmlEscape(model->getWalletName()) + "<br>"; + } ui->outUri->setText(html); #ifdef USE_QRCODE diff --git a/src/qt/receiverequestdialog.h b/src/qt/receiverequestdialog.h index 21bbf1edb7..23c5529535 100644 --- a/src/qt/receiverequestdialog.h +++ b/src/qt/receiverequestdialog.h @@ -12,8 +12,6 @@ #include <QLabel> #include <QPainter> -class OptionsModel; - namespace Ui { class ReceiveRequestDialog; } @@ -53,7 +51,7 @@ public: explicit ReceiveRequestDialog(QWidget *parent = 0); ~ReceiveRequestDialog(); - void setModel(OptionsModel *model); + void setModel(WalletModel *model); void setInfo(const SendCoinsRecipient &info); private Q_SLOTS: @@ -64,7 +62,7 @@ private Q_SLOTS: private: Ui::ReceiveRequestDialog *ui; - OptionsModel *model; + WalletModel *model; SendCoinsRecipient info; }; diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 1aa4de03ca..c41e19f6f5 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -12,6 +12,7 @@ #include <qt/bantablemodel.h> #include <qt/clientmodel.h> #include <qt/platformstyle.h> +#include <qt/walletmodel.h> #include <chainparams.h> #include <netbase.h> #include <rpc/server.h> @@ -84,7 +85,7 @@ class RPCExecutor : public QObject Q_OBJECT public Q_SLOTS: - void request(const QString &command); + void request(const QString &command, const QString &walletID); Q_SIGNALS: void reply(int category, const QString &command); @@ -145,7 +146,7 @@ public: * @param[out] pstrFilteredOut Command line, filtered to remove any sensitive data */ -bool RPCConsole::RPCParseCommandLine(std::string &strResult, const std::string &strCommand, const bool fExecute, std::string * const pstrFilteredOut) +bool RPCConsole::RPCParseCommandLine(std::string &strResult, const std::string &strCommand, const bool fExecute, std::string * const pstrFilteredOut, const std::string *walletID) { std::vector< std::vector<std::string> > stack; stack.push_back(std::vector<std::string>()); @@ -303,10 +304,8 @@ bool RPCConsole::RPCParseCommandLine(std::string &strResult, const std::string & req.params = RPCConvertValues(stack.back()[0], std::vector<std::string>(stack.back().begin() + 1, stack.back().end())); req.strMethod = stack.back()[0]; #ifdef ENABLE_WALLET - // TODO: Move this logic to WalletModel - if (!vpwallets.empty()) { - // in Qt, use always the wallet with index 0 when running with multiple wallets - QByteArray encodedName = QUrl::toPercentEncoding(QString::fromStdString(vpwallets[0]->GetName())); + if (walletID && !walletID->empty()) { + QByteArray encodedName = QUrl::toPercentEncoding(QString::fromStdString(*walletID)); req.URI = "/wallet/"+std::string(encodedName.constData(), encodedName.length()); } #endif @@ -385,7 +384,7 @@ bool RPCConsole::RPCParseCommandLine(std::string &strResult, const std::string & } } -void RPCExecutor::request(const QString &command) +void RPCExecutor::request(const QString &command, const QString &walletID) { try { @@ -416,7 +415,8 @@ void RPCExecutor::request(const QString &command) " example: getblock(getblockhash(0),true)[tx][0]\n\n"))); return; } - if(!RPCConsole::RPCExecuteCommandLine(result, executableCommand)) + std::string wallet_id = walletID.toStdString(); + if(!RPCConsole::RPCExecuteCommandLine(result, executableCommand, nullptr, &wallet_id)) { Q_EMIT reply(RPCConsole::CMD_ERROR, QString("Parse error: unbalanced ' or \"")); return; @@ -478,6 +478,10 @@ RPCConsole::RPCConsole(const PlatformStyle *_platformStyle, QWidget *parent) : connect(ui->fontSmallerButton, SIGNAL(clicked()), this, SLOT(fontSmaller())); connect(ui->btnClearTrafficGraph, SIGNAL(clicked()), ui->trafficGraph, SLOT(clear())); + // disable the wallet selector by default + ui->WalletSelector->setVisible(false); + ui->WalletSelectorLabel->setVisible(false); + // set library version labels #ifdef ENABLE_WALLET ui->berkeleyDBVersion->setText(DbEnv::version(0, 0, 0)); @@ -687,6 +691,23 @@ void RPCConsole::setClientModel(ClientModel *model) } } +#ifdef ENABLE_WALLET +void RPCConsole::addWallet(WalletModel * const walletModel) +{ + const QString name = walletModel->getWalletName(); + // use name for text and internal data object (to allow to move to a wallet id later) + ui->WalletSelector->addItem(name, name); + if (ui->WalletSelector->count() == 2 && !isVisible()) { + // First wallet added, set to default so long as the window isn't presently visible (and potentially in use) + ui->WalletSelector->setCurrentIndex(1); + } + if (ui->WalletSelector->count() > 2) { + ui->WalletSelector->setVisible(true); + ui->WalletSelectorLabel->setVisible(true); + } +} +#endif + static QString categoryClass(int category) { switch(category) @@ -874,8 +895,25 @@ void RPCConsole::on_lineEdit_returnPressed() cmdBeforeBrowsing = QString(); + QString walletID; +#ifdef ENABLE_WALLET + const int wallet_index = ui->WalletSelector->currentIndex(); + if (wallet_index > 0) { + walletID = (QString)ui->WalletSelector->itemData(wallet_index).value<QString>(); + } + + if (m_last_wallet_id != walletID) { + if (walletID.isEmpty()) { + message(CMD_REQUEST, tr("Executing command without any wallet")); + } else { + message(CMD_REQUEST, tr("Executing command using \"%1\" wallet").arg(walletID)); + } + m_last_wallet_id = walletID; + } +#endif + message(CMD_REQUEST, QString::fromStdString(strFilteredCmd)); - Q_EMIT cmdRequest(cmd); + Q_EMIT cmdRequest(cmd, walletID); cmd = QString::fromStdString(strFilteredCmd); @@ -923,7 +961,7 @@ void RPCConsole::startExecutor() // Replies from executor object must go to this object connect(executor, SIGNAL(reply(int,QString)), this, SLOT(message(int,QString))); // Requests from this object must go to executor - connect(this, SIGNAL(cmdRequest(QString)), executor, SLOT(request(QString))); + connect(this, SIGNAL(cmdRequest(QString, QString)), executor, SLOT(request(QString, QString))); // On stopExecutor signal // - quit the Qt event loop in the execution thread diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h index c41cbb0933..c97260b2c3 100644 --- a/src/qt/rpcconsole.h +++ b/src/qt/rpcconsole.h @@ -17,6 +17,7 @@ class ClientModel; class PlatformStyle; class RPCTimerInterface; +class WalletModel; namespace Ui { class RPCConsole; @@ -36,12 +37,13 @@ public: explicit RPCConsole(const PlatformStyle *platformStyle, QWidget *parent); ~RPCConsole(); - static bool RPCParseCommandLine(std::string &strResult, const std::string &strCommand, bool fExecute, std::string * const pstrFilteredOut = nullptr); - static bool RPCExecuteCommandLine(std::string &strResult, const std::string &strCommand, std::string * const pstrFilteredOut = nullptr) { - return RPCParseCommandLine(strResult, strCommand, true, pstrFilteredOut); + static bool RPCParseCommandLine(std::string &strResult, const std::string &strCommand, bool fExecute, std::string * const pstrFilteredOut = nullptr, const std::string *walletID = nullptr); + static bool RPCExecuteCommandLine(std::string &strResult, const std::string &strCommand, std::string * const pstrFilteredOut = nullptr, const std::string *walletID = nullptr) { + return RPCParseCommandLine(strResult, strCommand, true, pstrFilteredOut, walletID); } void setClientModel(ClientModel *model); + void addWallet(WalletModel * const walletModel); enum MessageClass { MC_ERROR, @@ -120,7 +122,7 @@ public Q_SLOTS: Q_SIGNALS: // For RPC command executor void stopExecutor(); - void cmdRequest(const QString &command); + void cmdRequest(const QString &command, const QString &walletID); private: void startExecutor(); @@ -151,6 +153,7 @@ private: int consoleFontSize; QCompleter *autoCompleter; QThread thread; + QString m_last_wallet_id; /** Update UI with latest network info from model. */ void updateNetworkState(); diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index ec7edd48cd..8a52aadbb0 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -277,8 +277,11 @@ void SendCoinsDialog::on_sendButton_clicked() QStringList formatted; for (const SendCoinsRecipient &rcp : currentTransaction.getRecipients()) { - // generate bold amount string + // generate bold amount string with wallet name in case of multiwallet QString amount = "<b>" + BitcoinUnits::formatHtmlWithUnit(model->getOptionsModel()->getDisplayUnit(), rcp.amount); + if (model->isMultiwallet()) { + amount.append(" <u>"+tr("from wallet %1").arg(GUIUtil::HtmlEscape(model->getWalletName()))+"</u> "); + } amount.append("</b>"); // generate monospace address string QString address = "<span style='font-family: monospace;'>" + rcp.address; diff --git a/src/qt/walletframe.cpp b/src/qt/walletframe.cpp index c0b9d04269..5b13353d7b 100644 --- a/src/qt/walletframe.cpp +++ b/src/qt/walletframe.cpp @@ -3,6 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <qt/walletframe.h> +#include <qt/walletmodel.h> #include <qt/bitcoingui.h> #include <qt/walletview.h> @@ -39,10 +40,16 @@ void WalletFrame::setClientModel(ClientModel *_clientModel) this->clientModel = _clientModel; } -bool WalletFrame::addWallet(const QString& name, WalletModel *walletModel) +bool WalletFrame::addWallet(WalletModel *walletModel) { - if (!gui || !clientModel || !walletModel || mapWalletViews.count(name) > 0) + if (!gui || !clientModel || !walletModel) { return false; + } + + const QString name = walletModel->getWalletName(); + if (mapWalletViews.count(name) > 0) { + return false; + } WalletView *walletView = new WalletView(platformStyle, this); walletView->setBitcoinGUI(gui); diff --git a/src/qt/walletframe.h b/src/qt/walletframe.h index 42ce69fea1..6eedcf370c 100644 --- a/src/qt/walletframe.h +++ b/src/qt/walletframe.h @@ -36,7 +36,7 @@ public: void setClientModel(ClientModel *clientModel); - bool addWallet(const QString& name, WalletModel *walletModel); + bool addWallet(WalletModel *walletModel); bool setCurrentWallet(const QString& name); bool removeWallet(const QString &name); void removeAllWallets(); @@ -59,6 +59,7 @@ private: const PlatformStyle *platformStyle; +public: WalletView *currentWalletView(); public Q_SLOTS: diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index d092ebedfb..555a21e8c5 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -110,8 +110,9 @@ void WalletModel::updateStatus() { EncryptionStatus newEncryptionStatus = getEncryptionStatus(); - if(cachedEncryptionStatus != newEncryptionStatus) - Q_EMIT encryptionStatusChanged(newEncryptionStatus); + if(cachedEncryptionStatus != newEncryptionStatus) { + Q_EMIT encryptionStatusChanged(); + } } void WalletModel::pollBalanceChanged() @@ -743,3 +744,18 @@ int WalletModel::getDefaultConfirmTarget() const { return nTxConfirmTarget; } + +QString WalletModel::getWalletName() const +{ + LOCK(wallet->cs_wallet); + QString walletName = QString::fromStdString(wallet->GetName()); + if (walletName.endsWith(".dat")) { + walletName.truncate(walletName.size() - 4); + } + return walletName; +} + +bool WalletModel::isMultiwallet() +{ + return gArgs.GetArgs("-wallet").size() > 1; +} diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h index 64813e0f5a..ff4b38a804 100644 --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -136,6 +136,8 @@ public: TransactionTableModel *getTransactionTableModel(); RecentRequestsTableModel *getRecentRequestsTableModel(); + CWallet *getWallet() const { return wallet; }; + CAmount getBalance(const CCoinControl *coinControl = nullptr) const; CAmount getUnconfirmedBalance() const; CAmount getImmatureBalance() const; @@ -225,6 +227,9 @@ public: int getDefaultConfirmTarget() const; + QString getWalletName() const; + + static bool isMultiwallet(); private: CWallet *wallet; bool fHaveWatchOnly; @@ -260,7 +265,7 @@ Q_SIGNALS: const CAmount& watchOnlyBalance, const CAmount& watchUnconfBalance, const CAmount& watchImmatureBalance); // Encryption status of wallet changed - void encryptionStatusChanged(int status); + void encryptionStatusChanged(); // Signal emitted when wallet needs to be unlocked // It is valid behaviour for listeners to keep the wallet locked after this signal; diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp index 64497a3431..cc4300a7a1 100644 --- a/src/qt/walletview.cpp +++ b/src/qt/walletview.cpp @@ -101,13 +101,13 @@ void WalletView::setBitcoinGUI(BitcoinGUI *gui) connect(this, SIGNAL(message(QString,QString,unsigned int)), gui, SLOT(message(QString,QString,unsigned int))); // Pass through encryption status changed signals - connect(this, SIGNAL(encryptionStatusChanged(int)), gui, SLOT(setEncryptionStatus(int))); + connect(this, SIGNAL(encryptionStatusChanged()), gui, SLOT(updateWalletStatus())); // Pass through transaction notifications - connect(this, SIGNAL(incomingTransaction(QString,int,CAmount,QString,QString,QString)), gui, SLOT(incomingTransaction(QString,int,CAmount,QString,QString,QString))); + connect(this, SIGNAL(incomingTransaction(QString,int,CAmount,QString,QString,QString,QString)), gui, SLOT(incomingTransaction(QString,int,CAmount,QString,QString,QString,QString))); // Connect HD enabled state signal - connect(this, SIGNAL(hdEnabledStatusChanged(int)), gui, SLOT(setHDStatus(int))); + connect(this, SIGNAL(hdEnabledStatusChanged()), gui, SLOT(updateWalletStatus())); } } @@ -137,11 +137,11 @@ void WalletView::setWalletModel(WalletModel *_walletModel) connect(_walletModel, SIGNAL(message(QString,QString,unsigned int)), this, SIGNAL(message(QString,QString,unsigned int))); // Handle changes in encryption status - connect(_walletModel, SIGNAL(encryptionStatusChanged(int)), this, SIGNAL(encryptionStatusChanged(int))); + connect(_walletModel, SIGNAL(encryptionStatusChanged()), this, SIGNAL(encryptionStatusChanged())); updateEncryptionStatus(); // update HD status - Q_EMIT hdEnabledStatusChanged(_walletModel->hdEnabled()); + Q_EMIT hdEnabledStatusChanged(); // Balloon pop-up for new transaction connect(_walletModel->getTransactionTableModel(), SIGNAL(rowsInserted(QModelIndex,int,int)), @@ -172,7 +172,7 @@ void WalletView::processNewTransaction(const QModelIndex& parent, int start, int QString address = ttm->data(index, TransactionTableModel::AddressRole).toString(); QString label = ttm->data(index, TransactionTableModel::LabelRole).toString(); - Q_EMIT incomingTransaction(date, walletModel->getOptionsModel()->getDisplayUnit(), amount, type, address, label); + Q_EMIT incomingTransaction(date, walletModel->getOptionsModel()->getDisplayUnit(), amount, type, address, label, walletModel->getWalletName()); } void WalletView::gotoOverviewPage() @@ -234,7 +234,7 @@ void WalletView::showOutOfSyncWarning(bool fShow) void WalletView::updateEncryptionStatus() { - Q_EMIT encryptionStatusChanged(walletModel->getEncryptionStatus()); + Q_EMIT encryptionStatusChanged(); } void WalletView::encryptWallet(bool status) diff --git a/src/qt/walletview.h b/src/qt/walletview.h index 30d68e4eff..878a5966d6 100644 --- a/src/qt/walletview.h +++ b/src/qt/walletview.h @@ -44,6 +44,7 @@ public: The client model represents the part of the core that communicates with the P2P network, and is wallet-agnostic. */ void setClientModel(ClientModel *clientModel); + WalletModel *getWalletModel() { return walletModel; } /** Set the wallet model. The wallet model represents a bitcoin wallet, and offers access to the list of transactions, address book and sending functionality. @@ -119,11 +120,11 @@ Q_SIGNALS: /** Fired when a message should be reported to the user */ void message(const QString &title, const QString &message, unsigned int style); /** Encryption status of wallet changed */ - void encryptionStatusChanged(int status); + void encryptionStatusChanged(); /** HD-Enabled status of wallet changed (only possible during startup) */ - void hdEnabledStatusChanged(int hdEnabled); + void hdEnabledStatusChanged(); /** Notify that a new transaction appeared */ - void incomingTransaction(const QString& date, int unit, const CAmount& amount, const QString& type, const QString& address, const QString& label); + void incomingTransaction(const QString& date, int unit, const CAmount& amount, const QString& type, const QString& address, const QString& label, const QString& walletName); /** Notify that the out of sync warning icon has been pressed */ void outOfSyncWarningClicked(); }; diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index b37a411ef4..a80875e7ed 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2890,20 +2890,11 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CTransac nChangePosInOut = -1; } - // Fill vin + // Dummy fill vin for maximum size estimation // - // Note how the sequence number is set to non-maxint so that - // the nLockTime set above actually works. - // - // BIP125 defines opt-in RBF as any nSequence < maxint-1, so - // we use the highest possible value in that range (maxint-2) - // to avoid conflicting with other possible uses of nSequence, - // and in the spirit of "smallest possible change from prior - // behavior." - const uint32_t nSequence = coin_control.signalRbf ? MAX_BIP125_RBF_SEQUENCE : (CTxIn::SEQUENCE_FINAL - 1); - for (const auto& coin : setCoins) - txNew.vin.push_back(CTxIn(coin.outpoint,CScript(), - nSequence)); + for (const auto& coin : setCoins) { + txNew.vin.push_back(CTxIn(coin.outpoint,CScript())); + } nBytes = CalculateMaximumSignedTxSize(txNew, this); if (nBytes < 0) { @@ -2993,11 +2984,29 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CTransac if (nChangePosInOut == -1) reservekey.ReturnKey(); // Return any reserved key if we don't have change + // Shuffle selected coins and fill in final vin + txNew.vin.clear(); + std::vector<CInputCoin> selected_coins(setCoins.begin(), setCoins.end()); + std::shuffle(selected_coins.begin(), selected_coins.end(), FastRandomContext()); + + // Note how the sequence number is set to non-maxint so that + // the nLockTime set above actually works. + // + // BIP125 defines opt-in RBF as any nSequence < maxint-1, so + // we use the highest possible value in that range (maxint-2) + // to avoid conflicting with other possible uses of nSequence, + // and in the spirit of "smallest possible change from prior + // behavior." + const uint32_t nSequence = coin_control.signalRbf ? MAX_BIP125_RBF_SEQUENCE : (CTxIn::SEQUENCE_FINAL - 1); + for (const auto& coin : selected_coins) { + txNew.vin.push_back(CTxIn(coin.outpoint, CScript(), nSequence)); + } + if (sign) { CTransaction txNewConst(txNew); int nIn = 0; - for (const auto& coin : setCoins) + for (const auto& coin : selected_coins) { const CScript& scriptPubKey = coin.txout.scriptPubKey; SignatureData sigdata; |