aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am2
-rw-r--r--src/Makefile.bench.include1
-rw-r--r--src/bench/block_assemble.cpp116
-rw-r--r--src/crypto/sha256.cpp21
-rw-r--r--src/interfaces/wallet.cpp4
-rw-r--r--src/interfaces/wallet.h4
-rw-r--r--src/miner.cpp4
-rw-r--r--src/qt/README.md8
-rw-r--r--src/qt/addressbookpage.cpp5
-rw-r--r--src/qt/bantablemodel.cpp2
-rw-r--r--src/qt/bitcoin.cpp54
-rw-r--r--src/qt/bitcoingui.cpp92
-rw-r--r--src/qt/bitcoingui.h101
-rw-r--r--src/qt/coincontroldialog.cpp10
-rw-r--r--src/qt/guiutil.cpp32
-rw-r--r--src/qt/guiutil.h2
-rw-r--r--src/qt/macdockiconhandler.mm8
-rw-r--r--src/qt/networkstyle.cpp4
-rw-r--r--src/qt/openuridialog.cpp2
-rw-r--r--src/qt/optionsdialog.cpp12
-rw-r--r--src/qt/paymentrequestplus.cpp2
-rw-r--r--src/qt/paymentserver.cpp15
-rw-r--r--src/qt/peertablemodel.cpp2
-rw-r--r--src/qt/platformstyle.cpp2
-rw-r--r--src/qt/receiverequestdialog.cpp3
-rw-r--r--src/qt/rpcconsole.cpp14
-rw-r--r--src/qt/rpcconsole.h1
-rw-r--r--src/qt/sendcoinsentry.cpp2
-rw-r--r--src/qt/signverifymessagedialog.cpp2
-rw-r--r--src/qt/test/test_main.cpp7
-rw-r--r--src/qt/test/wallettests.cpp13
-rw-r--r--src/qt/transactionview.cpp4
-rw-r--r--src/qt/walletframe.cpp1
-rw-r--r--src/qt/walletmodel.cpp8
-rw-r--r--src/qt/walletmodel.h4
-rw-r--r--src/qt/winshutdownmonitor.cpp2
-rw-r--r--src/qt/winshutdownmonitor.h2
-rw-r--r--src/rpc/blockchain.cpp2
-rw-r--r--src/txmempool.cpp4
-rw-r--r--src/validation.cpp4
-rw-r--r--src/wallet/db.cpp5
-rw-r--r--src/wallet/init.cpp2
-rw-r--r--src/wallet/rpcdump.cpp2
-rw-r--r--src/wallet/rpcwallet.cpp74
-rw-r--r--src/wallet/wallet.cpp17
-rw-r--r--src/wallet/wallet.h3
46 files changed, 371 insertions, 310 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index e03c21f16e..a2599d33e1 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -235,6 +235,7 @@ libbitcoin_server_a_SOURCES = \
rpc/net.cpp \
rpc/rawtransaction.cpp \
rpc/server.cpp \
+ rpc/util.cpp \
script/sigcache.cpp \
timedata.cpp \
torcontrol.cpp \
@@ -392,7 +393,6 @@ libbitcoin_util_a_SOURCES = \
logging.cpp \
random.cpp \
rpc/protocol.cpp \
- rpc/util.cpp \
support/cleanse.cpp \
sync.cpp \
threadinterrupt.cpp \
diff --git a/src/Makefile.bench.include b/src/Makefile.bench.include
index bc2c46f228..d70df3c9e8 100644
--- a/src/Makefile.bench.include
+++ b/src/Makefile.bench.include
@@ -15,6 +15,7 @@ bench_bench_bitcoin_SOURCES = \
bench/bench_bitcoin.cpp \
bench/bench.cpp \
bench/bench.h \
+ bench/block_assemble.cpp \
bench/checkblock.cpp \
bench/checkqueue.cpp \
bench/examples.cpp \
diff --git a/src/bench/block_assemble.cpp b/src/bench/block_assemble.cpp
new file mode 100644
index 0000000000..36fa175a76
--- /dev/null
+++ b/src/bench/block_assemble.cpp
@@ -0,0 +1,116 @@
+// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <bench/bench.h>
+#include <chainparams.h>
+#include <coins.h>
+#include <consensus/merkle.h>
+#include <consensus/validation.h>
+#include <miner.h>
+#include <policy/policy.h>
+#include <pow.h>
+#include <scheduler.h>
+#include <txdb.h>
+#include <txmempool.h>
+#include <utiltime.h>
+#include <validation.h>
+#include <validationinterface.h>
+
+#include <boost/thread.hpp>
+
+#include <list>
+#include <vector>
+
+static std::shared_ptr<CBlock> PrepareBlock(const CScript& coinbase_scriptPubKey)
+{
+ auto block = std::make_shared<CBlock>(
+ BlockAssembler{Params()}
+ .CreateNewBlock(coinbase_scriptPubKey, /* fMineWitnessTx */ true)
+ ->block);
+
+ block->nTime = ::chainActive.Tip()->GetMedianTimePast() + 1;
+ block->hashMerkleRoot = BlockMerkleRoot(*block);
+
+ return block;
+}
+
+
+static CTxIn MineBlock(const CScript& coinbase_scriptPubKey)
+{
+ auto block = PrepareBlock(coinbase_scriptPubKey);
+
+ while (!CheckProofOfWork(block->GetHash(), block->nBits, Params().GetConsensus())) {
+ assert(++block->nNonce);
+ }
+
+ bool processed{ProcessNewBlock(Params(), block, true, nullptr)};
+ assert(processed);
+
+ return CTxIn{block->vtx[0]->GetHash(), 0};
+}
+
+
+static void AssembleBlock(benchmark::State& state)
+{
+ const std::vector<unsigned char> op_true{OP_TRUE};
+ CScriptWitness witness;
+ witness.stack.push_back(op_true);
+
+ uint256 witness_program;
+ CSHA256().Write(&op_true[0], op_true.size()).Finalize(witness_program.begin());
+
+ const CScript SCRIPT_PUB{CScript(OP_0) << std::vector<unsigned char>{witness_program.begin(), witness_program.end()}};
+
+ // Switch to regtest so we can mine faster
+ // Also segwit is active, so we can include witness transactions
+ SelectParams(CBaseChainParams::REGTEST);
+
+ InitScriptExecutionCache();
+
+ boost::thread_group thread_group;
+ CScheduler scheduler;
+ {
+ ::pblocktree.reset(new CBlockTreeDB(1 << 20, true));
+ ::pcoinsdbview.reset(new CCoinsViewDB(1 << 23, true));
+ ::pcoinsTip.reset(new CCoinsViewCache(pcoinsdbview.get()));
+
+ const CChainParams& chainparams = Params();
+ thread_group.create_thread(boost::bind(&CScheduler::serviceQueue, &scheduler));
+ GetMainSignals().RegisterBackgroundSignalScheduler(scheduler);
+ LoadGenesisBlock(chainparams);
+ CValidationState state;
+ ActivateBestChain(state, chainparams);
+ assert(::chainActive.Tip() != nullptr);
+ const bool witness_enabled{IsWitnessEnabled(::chainActive.Tip(), chainparams.GetConsensus())};
+ assert(witness_enabled);
+ }
+
+ // Collect some loose transactions that spend the coinbases of our mined blocks
+ constexpr size_t NUM_BLOCKS{200};
+ std::array<CTransactionRef, NUM_BLOCKS - COINBASE_MATURITY + 1> txs;
+ for (size_t b{0}; b < NUM_BLOCKS; ++b) {
+ CMutableTransaction tx;
+ tx.vin.push_back(MineBlock(SCRIPT_PUB));
+ tx.vin.back().scriptWitness = witness;
+ tx.vout.emplace_back(1337, SCRIPT_PUB);
+ if (NUM_BLOCKS - b >= COINBASE_MATURITY)
+ txs.at(b) = MakeTransactionRef(tx);
+ }
+ for (const auto& txr : txs) {
+ CValidationState state;
+ bool ret{::AcceptToMemoryPool(::mempool, state, txr, nullptr /* pfMissingInputs */, nullptr /* plTxnReplaced */, false /* bypass_limits */, /* nAbsurdFee */ 0)};
+ assert(ret);
+ }
+
+ while (state.KeepRunning()) {
+ PrepareBlock(SCRIPT_PUB);
+ }
+
+ thread_group.interrupt_all();
+ thread_group.join_all();
+ GetMainSignals().FlushBackgroundCallbacks();
+ GetMainSignals().UnregisterBackgroundSignalScheduler();
+}
+
+BENCHMARK(AssembleBlock, 700);
diff --git a/src/crypto/sha256.cpp b/src/crypto/sha256.cpp
index 100d0d1fac..e62ddc125e 100644
--- a/src/crypto/sha256.cpp
+++ b/src/crypto/sha256.cpp
@@ -536,6 +536,14 @@ void inline cpuid(uint32_t leaf, uint32_t subleaf, uint32_t& a, uint32_t& b, uin
{
__asm__ ("cpuid" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(leaf), "2"(subleaf));
}
+
+/** Check whether the OS has enabled AVX registers. */
+bool AVXEnabled()
+{
+ uint32_t a, d;
+ __asm__("xgetbv" : "=a"(a), "=d"(d) : "c"(0));
+ return (a & 6) == 6;
+}
#endif
} // namespace
@@ -544,6 +552,7 @@ std::string SHA256AutoDetect()
{
std::string ret = "standard";
#if defined(USE_ASM) && (defined(__x86_64__) || defined(__amd64__) || defined(__i386__))
+ (void)AVXEnabled; // Silence unused warning (in case ENABLE_AVX2 is not defined)
uint32_t eax, ebx, ecx, edx;
cpuid(1, 0, eax, ebx, ecx, edx);
if ((ecx >> 19) & 1) {
@@ -555,10 +564,14 @@ std::string SHA256AutoDetect()
TransformD64_4way = sha256d64_sse41::Transform_4way;
ret = "sse4(1way+4way)";
#if defined(ENABLE_AVX2) && !defined(BUILD_BITCOIN_INTERNAL)
- cpuid(7, 0, eax, ebx, ecx, edx);
- if ((ebx >> 5) & 1) {
- TransformD64_8way = sha256d64_avx2::Transform_8way;
- ret += ",avx2(8way)";
+ if (((ecx >> 27) & 1) && ((ecx >> 28) & 1)) { // XSAVE and AVX
+ cpuid(7, 0, eax, ebx, ecx, edx);
+ if ((ebx >> 5) & 1) { // AVX2 flag
+ if (AVXEnabled()) { // OS has enabled AVX registers
+ TransformD64_8way = sha256d64_avx2::Transform_8way;
+ ret += ",avx2(8way)";
+ }
+ }
}
#endif
#else
diff --git a/src/interfaces/wallet.cpp b/src/interfaces/wallet.cpp
index 3029dbe8e3..e98acba0df 100644
--- a/src/interfaces/wallet.cpp
+++ b/src/interfaces/wallet.cpp
@@ -429,6 +429,10 @@ public:
bool hdEnabled() override { return m_wallet.IsHDEnabled(); }
OutputType getDefaultAddressType() override { return m_wallet.m_default_address_type; }
OutputType getDefaultChangeType() override { return m_wallet.m_default_change_type; }
+ std::unique_ptr<Handler> handleUnload(UnloadFn fn) override
+ {
+ return MakeHandler(m_wallet.NotifyUnload.connect(fn));
+ }
std::unique_ptr<Handler> handleShowProgress(ShowProgressFn fn) override
{
return MakeHandler(m_wallet.ShowProgress.connect(fn));
diff --git a/src/interfaces/wallet.h b/src/interfaces/wallet.h
index 82ae0b14b5..ce42e14eea 100644
--- a/src/interfaces/wallet.h
+++ b/src/interfaces/wallet.h
@@ -242,6 +242,10 @@ public:
// Get default change type.
virtual OutputType getDefaultChangeType() = 0;
+ //! Register handler for unload message.
+ using UnloadFn = std::function<void()>;
+ virtual std::unique_ptr<Handler> handleUnload(UnloadFn fn) = 0;
+
//! Register handler for show progress messages.
using ShowProgressFn = std::function<void(const std::string& title, int progress)>;
virtual std::unique_ptr<Handler> handleShowProgress(ShowProgressFn fn) = 0;
diff --git a/src/miner.cpp b/src/miner.cpp
index d4527a1d67..738ccad1b9 100644
--- a/src/miner.cpp
+++ b/src/miner.cpp
@@ -209,7 +209,7 @@ bool BlockAssembler::TestPackage(uint64_t packageSize, int64_t packageSigOpsCost
// segwit activation)
bool BlockAssembler::TestPackageTransactions(const CTxMemPool::setEntries& package)
{
- for (const CTxMemPool::txiter it : package) {
+ for (CTxMemPool::txiter it : package) {
if (!IsFinalTx(it->GetTx(), nHeight, nLockTimeCutoff))
return false;
if (!fIncludeWitness && it->GetTx().HasWitness())
@@ -241,7 +241,7 @@ int BlockAssembler::UpdatePackagesForAdded(const CTxMemPool::setEntries& already
indexed_modified_transaction_set &mapModifiedTx)
{
int nDescendantsUpdated = 0;
- for (const CTxMemPool::txiter it : alreadyAdded) {
+ for (CTxMemPool::txiter it : alreadyAdded) {
CTxMemPool::setEntries descendants;
mempool.CalculateDescendants(it, descendants);
// Insert all descendants (not yet in block) into the modified set
diff --git a/src/qt/README.md b/src/qt/README.md
index bf8139666c..3ec538b4f4 100644
--- a/src/qt/README.md
+++ b/src/qt/README.md
@@ -1,6 +1,6 @@
This directory contains the BitcoinQT graphical user interface (GUI). It uses the cross-platform framework [Qt](https://www1.qt.io/developers/).
-The current precise version for Qt 5 is specified in [qt.mk](/depends/packages/qt.mk). Qt 4 is also supported (see [#8263](https://github.com/bitcoin/bitcoin/issues/8263)).
+The current precise version for Qt 5 is specified in [qt.mk](/depends/packages/qt.mk).
## Compile and run
@@ -16,7 +16,7 @@ To run:
### forms
-Contains [Designer UI](http://doc.qt.io/qt-5.9/designer-using-a-ui-file.html) files. They are created with [Qt Creator](#using-qt-creator-as-ide), but can be edited using any text editor.
+Contains [Designer UI](https://doc.qt.io/qt-5.9/designer-using-a-ui-file.html) files. They are created with [Qt Creator](#using-qt-creator-as-ide), but can be edited using any text editor.
### locale
@@ -36,7 +36,7 @@ Represents the main window of the Bitcoin UI.
### \*model.(h/cpp)
-The model. When it has a corresponding controller, it generally inherits from [QAbstractTableModel](http://doc.qt.io/qt-5/qabstracttablemodel.html). Models that are used by controllers as helpers inherit from other Qt classes like [QValidator](http://doc.qt.io/qt-5/qvalidator.html).
+The model. When it has a corresponding controller, it generally inherits from [QAbstractTableModel](https://doc.qt.io/qt-5/qabstracttablemodel.html). Models that are used by controllers as helpers inherit from other Qt classes like [QValidator](https://doc.qt.io/qt-5/qvalidator.html).
ClientModel is used by the main application `bitcoingui` and several models like `peertablemodel`.
@@ -46,7 +46,7 @@ A controller. `:NAMEpage.cpp` generally includes `:NAMEmodel.h` and `forms/:NAME
### \*dialog.(h/cpp)
-Various dialogs, e.g. to open a URL. Inherit from [QDialog](http://doc.qt.io/qt-4.8/qdialog.html).
+Various dialogs, e.g. to open a URL. Inherit from [QDialog](https://doc.qt.io/qt-5/qdialog.html).
### paymentserver.(h/cpp)
diff --git a/src/qt/addressbookpage.cpp b/src/qt/addressbookpage.cpp
index f2ddbf259b..d51069d922 100644
--- a/src/qt/addressbookpage.cpp
+++ b/src/qt/addressbookpage.cpp
@@ -160,13 +160,8 @@ void AddressBookPage::setModel(AddressTableModel *_model)
ui->tableView->sortByColumn(0, Qt::AscendingOrder);
// Set column widths
-#if QT_VERSION < 0x050000
- ui->tableView->horizontalHeader()->setResizeMode(AddressTableModel::Label, QHeaderView::Stretch);
- ui->tableView->horizontalHeader()->setResizeMode(AddressTableModel::Address, QHeaderView::ResizeToContents);
-#else
ui->tableView->horizontalHeader()->setSectionResizeMode(AddressTableModel::Label, QHeaderView::Stretch);
ui->tableView->horizontalHeader()->setSectionResizeMode(AddressTableModel::Address, QHeaderView::ResizeToContents);
-#endif
connect(ui->tableView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
this, SLOT(selectionChanged()));
diff --git a/src/qt/bantablemodel.cpp b/src/qt/bantablemodel.cpp
index 26cb03c2c7..aa0d4a31d3 100644
--- a/src/qt/bantablemodel.cpp
+++ b/src/qt/bantablemodel.cpp
@@ -52,9 +52,7 @@ public:
node.getBanned(banMap);
cachedBanlist.clear();
-#if QT_VERSION >= 0x040700
cachedBanlist.reserve(banMap.size());
-#endif
for (const auto& entry : banMap)
{
CCombinedBan banEntry;
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp
index 31d9f936e7..e3d1c746b1 100644
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -55,13 +55,6 @@
#if defined(QT_STATICPLUGIN)
#include <QtPlugin>
-#if QT_VERSION < 0x050000
-Q_IMPORT_PLUGIN(qcncodecs)
-Q_IMPORT_PLUGIN(qjpcodecs)
-Q_IMPORT_PLUGIN(qtwcodecs)
-Q_IMPORT_PLUGIN(qkrcodecs)
-Q_IMPORT_PLUGIN(qtaccessiblewidgets)
-#else
#if QT_VERSION < 0x050400
Q_IMPORT_PLUGIN(AccessibleFactory)
#endif
@@ -73,11 +66,6 @@ Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin);
Q_IMPORT_PLUGIN(QCocoaIntegrationPlugin);
#endif
#endif
-#endif
-
-#if QT_VERSION < 0x050000
-#include <QTextCodec>
-#endif
// Declare meta types used for QMetaObject::invokeMethod
Q_DECLARE_METATYPE(bool*)
@@ -151,16 +139,6 @@ static void initTranslations(QTranslator &qtTranslatorBase, QTranslator &qtTrans
}
/* qDebug() message handler --> debug.log */
-#if QT_VERSION < 0x050000
-void DebugMessageHandler(QtMsgType type, const char *msg)
-{
- if (type == QtDebugMsg) {
- LogPrint(BCLog::QT, "GUI: %s\n", msg);
- } else {
- LogPrintf("GUI: %s\n", msg);
- }
-}
-#else
void DebugMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString &msg)
{
Q_UNUSED(context);
@@ -170,7 +148,6 @@ void DebugMessageHandler(QtMsgType type, const QMessageLogContext& context, cons
LogPrintf("GUI: %s\n", msg.toStdString());
}
}
-#endif
/** Class encapsulating Bitcoin Core startup and shutdown.
* Allows running startup and shutdown in a different thread from the UI thread.
@@ -238,6 +215,7 @@ public Q_SLOTS:
/// Handle runaway exceptions. Shows a message box with the problem and quits the program.
void handleRunawayException(const QString &message);
void addWallet(WalletModel* walletModel);
+ void removeWallet();
Q_SIGNALS:
void requestedInitialize();
@@ -467,11 +445,22 @@ void BitcoinApplication::addWallet(WalletModel* walletModel)
connect(walletModel, SIGNAL(coinsSent(WalletModel*, SendCoinsRecipient, QByteArray)),
paymentServer, SLOT(fetchPaymentACK(WalletModel*, const SendCoinsRecipient&, QByteArray)));
+ connect(walletModel, SIGNAL(unload()), this, SLOT(removeWallet()));
m_wallet_models.push_back(walletModel);
#endif
}
+void BitcoinApplication::removeWallet()
+{
+#ifdef ENABLE_WALLET
+ WalletModel* walletModel = static_cast<WalletModel*>(sender());
+ m_wallet_models.erase(std::find(m_wallet_models.begin(), m_wallet_models.end(), walletModel));
+ window->removeWallet(walletModel);
+ walletModel->deleteLater();
+#endif
+}
+
void BitcoinApplication::initializeResult(bool success)
{
qDebug() << __func__ << ": Initialization result: " << success;
@@ -491,8 +480,10 @@ void BitcoinApplication::initializeResult(bool success)
#ifdef ENABLE_WALLET
m_handler_load_wallet = m_node.handleLoadWallet([this](std::unique_ptr<interfaces::Wallet> wallet) {
- QMetaObject::invokeMethod(this, "addWallet", Qt::QueuedConnection,
- Q_ARG(WalletModel*, new WalletModel(std::move(wallet), m_node, platformStyle, optionsModel)));
+ WalletModel* wallet_model = new WalletModel(std::move(wallet), m_node, platformStyle, optionsModel, nullptr);
+ // Fix wallet model thread affinity.
+ wallet_model->moveToThread(thread());
+ QMetaObject::invokeMethod(this, "addWallet", Qt::QueuedConnection, Q_ARG(WalletModel*, wallet_model));
});
for (auto& wallet : m_node.getWallets()) {
@@ -572,12 +563,6 @@ int main(int argc, char *argv[])
// Do not refer to data directory yet, this can be overridden by Intro::pickDataDirectory
/// 1. Basic Qt initialization (not dependent on parameters or configuration)
-#if QT_VERSION < 0x050000
- // Internal string conversion is all UTF-8
- QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
- QTextCodec::setCodecForCStrings(QTextCodec::codecForTr());
-#endif
-
Q_INIT_RESOURCE(bitcoin);
Q_INIT_RESOURCE(bitcoin_locale);
@@ -708,17 +693,12 @@ int main(int argc, char *argv[])
/// 9. Main GUI initialization
// Install global event filter that makes sure that long tooltips can be word-wrapped
app.installEventFilter(new GUIUtil::ToolTipToRichTextFilter(TOOLTIP_WRAP_THRESHOLD, &app));
-#if QT_VERSION < 0x050000
- // Install qDebug() message handler to route to debug.log
- qInstallMsgHandler(DebugMessageHandler);
-#else
#if defined(Q_OS_WIN)
// Install global event filter for processing Windows session related Windows messages (WM_QUERYENDSESSION and WM_ENDSESSION)
qApp->installNativeEventFilter(new WinShutdownMonitor());
#endif
// Install qDebug() message handler to route to debug.log
qInstallMessageHandler(DebugMessageHandler);
-#endif
// Allow parameter interaction before we create the options model
app.parameterSetup();
// Load GUI settings from QSettings
@@ -739,7 +719,7 @@ int main(int argc, char *argv[])
// so the GUI thread won't be held up.
if (node->baseInitialize()) {
app.requestInitialize();
-#if defined(Q_OS_WIN) && QT_VERSION >= 0x050000
+#if defined(Q_OS_WIN)
WinShutdownMonitor::registerShutdownBlockReason(QObject::tr("%1 didn't yet exit safely...").arg(QObject::tr(PACKAGE_NAME)), (HWND)app.getMainWinId());
#endif
app.exec();
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index 9f5ea02e14..df78652376 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -55,14 +55,8 @@
#include <QStyle>
#include <QTimer>
#include <QToolBar>
-#include <QVBoxLayout>
-
-#if QT_VERSION < 0x050000
-#include <QTextDocument>
-#include <QUrl>
-#else
#include <QUrlQuery>
-#endif
+#include <QVBoxLayout>
const std::string BitcoinGUI::DEFAULT_UIPLATFORM =
#if defined(Q_OS_MAC)
@@ -76,50 +70,7 @@ const std::string BitcoinGUI::DEFAULT_UIPLATFORM =
BitcoinGUI::BitcoinGUI(interfaces::Node& node, const PlatformStyle *_platformStyle, const NetworkStyle *networkStyle, QWidget *parent) :
QMainWindow(parent),
- enableWallet(false),
m_node(node),
- clientModel(0),
- walletFrame(0),
- unitDisplayControl(0),
- labelWalletEncryptionIcon(0),
- labelWalletHDStatusIcon(0),
- labelProxyIcon(0),
- connectionsControl(0),
- labelBlocksIcon(0),
- progressBarLabel(0),
- progressBar(0),
- progressDialog(0),
- appMenuBar(0),
- appToolBar(0),
- overviewAction(0),
- historyAction(0),
- quitAction(0),
- sendCoinsAction(0),
- sendCoinsMenuAction(0),
- usedSendingAddressesAction(0),
- usedReceivingAddressesAction(0),
- signMessageAction(0),
- verifyMessageAction(0),
- aboutAction(0),
- receiveCoinsAction(0),
- receiveCoinsMenuAction(0),
- optionsAction(0),
- toggleHideAction(0),
- encryptWalletAction(0),
- backupWalletAction(0),
- changePassphraseAction(0),
- aboutQtAction(0),
- openRPCConsoleAction(0),
- openAction(0),
- showHelpMessageAction(0),
- trayIcon(0),
- trayIconMenu(0),
- notificator(0),
- rpcConsole(0),
- helpMessageDialog(0),
- modalOverlay(0),
- prevBlocks(0),
- spinnerFrame(0),
platformStyle(_platformStyle)
{
QSettings settings;
@@ -147,12 +98,6 @@ BitcoinGUI::BitcoinGUI(interfaces::Node& node, const PlatformStyle *_platformSty
#endif
setWindowTitle(windowTitle);
-#if defined(Q_OS_MAC) && QT_VERSION < 0x050000
- // This property is not implemented in Qt 5. Setting it has no effect.
- // A replacement API (QtMacUnifiedToolBar) is available in QtMacExtras.
- setUnifiedTitleAndToolBarOnMac(true);
-#endif
-
rpcConsole = new RPCConsole(node, _platformStyle, 0);
helpMessageDialog = new HelpMessageDialog(node, this, false);
#ifdef ENABLE_WALLET
@@ -229,7 +174,7 @@ BitcoinGUI::BitcoinGUI(interfaces::Node& node, const PlatformStyle *_platformSty
// Override style sheet for progress bar for styles that have a segmented progress bar,
// as they make the text unreadable (workaround for issue #1071)
- // See https://qt-project.org/doc/qt-4.8/gallery.html
+ // See https://doc.qt.io/qt-5/gallery.html
QString curStyle = QApplication::style()->metaObject()->className();
if(curStyle == "QWindowsStyle" || curStyle == "QWindowsXPStyle")
{
@@ -477,6 +422,16 @@ void BitcoinGUI::createToolBars()
m_wallet_selector = new QComboBox();
connect(m_wallet_selector, SIGNAL(currentIndexChanged(int)), this, SLOT(setCurrentWalletBySelectorIndex(int)));
+
+ m_wallet_selector_label = new QLabel();
+ m_wallet_selector_label->setText(tr("Wallet:") + " ");
+ m_wallet_selector_label->setBuddy(m_wallet_selector);
+
+ m_wallet_selector_label_action = appToolBar->addWidget(m_wallet_selector_label);
+ m_wallet_selector_action = appToolBar->addWidget(m_wallet_selector);
+
+ m_wallet_selector_label_action->setVisible(false);
+ m_wallet_selector_action->setVisible(false);
#endif
}
}
@@ -556,16 +511,29 @@ bool BitcoinGUI::addWallet(WalletModel *walletModel)
setWalletActionsEnabled(true);
m_wallet_selector->addItem(display_name, 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);
+ m_wallet_selector_label_action->setVisible(true);
+ m_wallet_selector_action->setVisible(true);
}
rpcConsole->addWallet(walletModel);
return walletFrame->addWallet(walletModel);
}
+bool BitcoinGUI::removeWallet(WalletModel* walletModel)
+{
+ if (!walletFrame) return false;
+ QString name = walletModel->getWalletName();
+ int index = m_wallet_selector->findData(name);
+ m_wallet_selector->removeItem(index);
+ if (m_wallet_selector->count() == 0) {
+ setWalletActionsEnabled(false);
+ } else if (m_wallet_selector->count() == 1) {
+ m_wallet_selector_label_action->setVisible(false);
+ m_wallet_selector_action->setVisible(false);
+ }
+ rpcConsole->removeWallet(walletModel);
+ return walletFrame->removeWallet(name);
+}
+
bool BitcoinGUI::setCurrentWallet(const QString& name)
{
if(!walletFrame)
diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h
index 89c1c73a79..964e04f848 100644
--- a/src/qt/bitcoingui.h
+++ b/src/qt/bitcoingui.h
@@ -70,9 +70,10 @@ public:
functionality.
*/
bool addWallet(WalletModel *walletModel);
+ bool removeWallet(WalletModel* walletModel);
void removeAllWallets();
#endif // ENABLE_WALLET
- bool enableWallet;
+ bool enableWallet = false;
protected:
void changeEvent(QEvent *e);
@@ -86,56 +87,58 @@ private:
interfaces::Node& m_node;
std::unique_ptr<interfaces::Handler> m_handler_message_box;
std::unique_ptr<interfaces::Handler> m_handler_question;
- ClientModel *clientModel;
- WalletFrame *walletFrame;
-
- UnitDisplayStatusBarControl *unitDisplayControl;
- QLabel *labelWalletEncryptionIcon;
- QLabel *labelWalletHDStatusIcon;
- QLabel *labelProxyIcon;
- QLabel *connectionsControl;
- QLabel *labelBlocksIcon;
- QLabel *progressBarLabel;
- QProgressBar *progressBar;
- QProgressDialog *progressDialog;
-
- QMenuBar *appMenuBar;
- QToolBar *appToolBar;
- QAction *overviewAction;
- QAction *historyAction;
- QAction *quitAction;
- QAction *sendCoinsAction;
- QAction *sendCoinsMenuAction;
- QAction *usedSendingAddressesAction;
- QAction *usedReceivingAddressesAction;
- QAction *signMessageAction;
- QAction *verifyMessageAction;
- QAction *aboutAction;
- QAction *receiveCoinsAction;
- QAction *receiveCoinsMenuAction;
- QAction *optionsAction;
- QAction *toggleHideAction;
- QAction *encryptWalletAction;
- QAction *backupWalletAction;
- QAction *changePassphraseAction;
- QAction *aboutQtAction;
- QAction *openRPCConsoleAction;
- QAction *openAction;
- QAction *showHelpMessageAction;
-
- QLabel *m_wallet_selector_label;
- QComboBox *m_wallet_selector;
-
- QSystemTrayIcon *trayIcon;
- QMenu *trayIconMenu;
- Notificator *notificator;
- RPCConsole *rpcConsole;
- HelpMessageDialog *helpMessageDialog;
- ModalOverlay *modalOverlay;
+ ClientModel* clientModel = nullptr;
+ WalletFrame* walletFrame = nullptr;
+
+ UnitDisplayStatusBarControl* unitDisplayControl = nullptr;
+ QLabel* labelWalletEncryptionIcon = nullptr;
+ QLabel* labelWalletHDStatusIcon = nullptr;
+ QLabel* labelProxyIcon = nullptr;
+ QLabel* connectionsControl = nullptr;
+ QLabel* labelBlocksIcon = nullptr;
+ QLabel* progressBarLabel = nullptr;
+ QProgressBar* progressBar = nullptr;
+ QProgressDialog* progressDialog = nullptr;
+
+ QMenuBar* appMenuBar = nullptr;
+ QToolBar* appToolBar = nullptr;
+ QAction* overviewAction = nullptr;
+ QAction* historyAction = nullptr;
+ QAction* quitAction = nullptr;
+ QAction* sendCoinsAction = nullptr;
+ QAction* sendCoinsMenuAction = nullptr;
+ QAction* usedSendingAddressesAction = nullptr;
+ QAction* usedReceivingAddressesAction = nullptr;
+ QAction* signMessageAction = nullptr;
+ QAction* verifyMessageAction = nullptr;
+ QAction* aboutAction = nullptr;
+ QAction* receiveCoinsAction = nullptr;
+ QAction* receiveCoinsMenuAction = nullptr;
+ QAction* optionsAction = nullptr;
+ QAction* toggleHideAction = nullptr;
+ QAction* encryptWalletAction = nullptr;
+ QAction* backupWalletAction = nullptr;
+ QAction* changePassphraseAction = nullptr;
+ QAction* aboutQtAction = nullptr;
+ QAction* openRPCConsoleAction = nullptr;
+ QAction* openAction = nullptr;
+ QAction* showHelpMessageAction = nullptr;
+ QAction* m_wallet_selector_label_action = nullptr;
+ QAction* m_wallet_selector_action = nullptr;
+
+ QLabel *m_wallet_selector_label = nullptr;
+ QComboBox* m_wallet_selector = nullptr;
+
+ QSystemTrayIcon* trayIcon = nullptr;
+ QMenu* trayIconMenu = nullptr;
+ Notificator* notificator = nullptr;
+ RPCConsole* rpcConsole = nullptr;
+ HelpMessageDialog* helpMessageDialog = nullptr;
+ ModalOverlay* modalOverlay = nullptr;
/** Keep track of previous number of blocks, to detect progress */
- int prevBlocks;
- int spinnerFrame;
+ int prevBlocks = 0;
+ int spinnerFrame = 0;
const PlatformStyle *platformStyle;
diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp
index b08de27041..9b6480a915 100644
--- a/src/qt/coincontroldialog.cpp
+++ b/src/qt/coincontroldialog.cpp
@@ -109,11 +109,7 @@ CoinControlDialog::CoinControlDialog(const PlatformStyle *_platformStyle, QWidge
connect(ui->treeWidget, SIGNAL(itemChanged(QTreeWidgetItem*, int)), this, SLOT(viewItemChanged(QTreeWidgetItem*, int)));
// click on header
-#if QT_VERSION < 0x050000
- ui->treeWidget->header()->setClickable(true);
-#else
ui->treeWidget->header()->setSectionsClickable(true);
-#endif
connect(ui->treeWidget->header(), SIGNAL(sectionClicked(int)), this, SLOT(headerSectionClicked(int)));
// ok button
@@ -122,10 +118,6 @@ CoinControlDialog::CoinControlDialog(const PlatformStyle *_platformStyle, QWidge
// (un)select all
connect(ui->pushButtonSelectAll, SIGNAL(clicked()), this, SLOT(buttonSelectAllClicked()));
- // change coin control first column label due Qt4 bug.
- // see https://github.com/bitcoin/bitcoin/issues/5716
- ui->treeWidget->headerItem()->setText(COLUMN_CHECKBOX, QString());
-
ui->treeWidget->setColumnWidth(COLUMN_CHECKBOX, 84);
ui->treeWidget->setColumnWidth(COLUMN_AMOUNT, 110);
ui->treeWidget->setColumnWidth(COLUMN_LABEL, 190);
@@ -392,13 +384,11 @@ void CoinControlDialog::viewItemChanged(QTreeWidgetItem* item, int column)
// TODO: Remove this temporary qt5 fix after Qt5.3 and Qt5.4 are no longer used.
// Fixed in Qt5.5 and above: https://bugreports.qt.io/browse/QTBUG-43473
-#if QT_VERSION >= 0x050000
else if (column == COLUMN_CHECKBOX && item->childCount() > 0)
{
if (item->checkState(COLUMN_CHECKBOX) == Qt::PartiallyChecked && item->child(0)->checkState(COLUMN_CHECKBOX) == Qt::PartiallyChecked)
item->setCheckState(COLUMN_CHECKBOX, Qt::Checked);
}
-#endif
}
// shows count of locked unspent outputs
diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp
index 563f930dec..acd9f7b35c 100644
--- a/src/qt/guiutil.cpp
+++ b/src/qt/guiutil.cpp
@@ -53,13 +53,9 @@
#include <QSettings>
#include <QTextDocument> // for Qt::mightBeRichText
#include <QThread>
+#include <QUrlQuery>
#include <QMouseEvent>
-#if QT_VERSION < 0x050000
-#include <QUrl>
-#else
-#include <QUrlQuery>
-#endif
#if QT_VERSION >= 0x50200
#include <QFontDatabase>
@@ -95,11 +91,7 @@ QFont fixedPitchFont()
return QFontDatabase::systemFont(QFontDatabase::FixedFont);
#else
QFont font("Monospace");
-#if QT_VERSION >= 0x040800
font.setStyleHint(QFont::Monospace);
-#else
- font.setStyleHint(QFont::TypeWriter);
-#endif
return font;
#endif
}
@@ -127,12 +119,10 @@ void setupAddressWidget(QValidatedLineEdit *widget, QWidget *parent)
parent->setFocusProxy(widget);
widget->setFont(fixedPitchFont());
-#if QT_VERSION >= 0x040700
// We don't want translators to use own addresses in translations
// and this is the only place, where this address is supplied.
widget->setPlaceholderText(QObject::tr("Enter a Bitcoin address (e.g. %1)").arg(
QString::fromStdString(DummyAddress(Params()))));
-#endif
widget->setValidator(new BitcoinAddressEntryValidator(parent));
widget->setCheckValidator(new BitcoinAddressCheckValidator(parent));
}
@@ -151,12 +141,8 @@ bool parseBitcoinURI(const QUrl &uri, SendCoinsRecipient *out)
}
rv.amount = 0;
-#if QT_VERSION < 0x050000
- QList<QPair<QString, QString> > items = uri.queryItems();
-#else
QUrlQuery uriQuery(uri);
QList<QPair<QString, QString> > items = uriQuery.queryItems();
-#endif
for (QList<QPair<QString, QString> >::iterator i = items.begin(); i != items.end(); i++)
{
bool fShouldReturnFalse = false;
@@ -242,11 +228,7 @@ bool isDust(interfaces::Node& node, const QString& address, const CAmount& amoun
QString HtmlEscape(const QString& str, bool fMultiLine)
{
-#if QT_VERSION < 0x050000
- QString escaped = Qt::escape(str);
-#else
QString escaped = str.toHtmlEscaped();
-#endif
if(fMultiLine)
{
escaped = escaped.replace("\n", "<br>\n");
@@ -287,11 +269,7 @@ QString getSaveFileName(QWidget *parent, const QString &caption, const QString &
QString myDir;
if(dir.isEmpty()) // Default to user documents location
{
-#if QT_VERSION < 0x050000
- myDir = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation);
-#else
myDir = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
-#endif
}
else
{
@@ -337,11 +315,7 @@ QString getOpenFileName(QWidget *parent, const QString &caption, const QString &
QString myDir;
if(dir.isEmpty()) // Default to user documents location
{
-#if QT_VERSION < 0x050000
- myDir = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation);
-#else
myDir = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
-#endif
}
else
{
@@ -495,11 +469,7 @@ void TableViewLastColumnResizingFixer::disconnectViewHeadersSignals()
// Refactored here for readability.
void TableViewLastColumnResizingFixer::setViewHeaderResizeMode(int logicalIndex, QHeaderView::ResizeMode resizeMode)
{
-#if QT_VERSION < 0x050000
- tableView->horizontalHeader()->setResizeMode(logicalIndex, resizeMode);
-#else
tableView->horizontalHeader()->setSectionResizeMode(logicalIndex, resizeMode);
-#endif
}
void TableViewLastColumnResizingFixer::resizeColumn(int nColumnIndex, int width)
diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h
index 4a26964098..e965a91d18 100644
--- a/src/qt/guiutil.h
+++ b/src/qt/guiutil.h
@@ -233,7 +233,7 @@ namespace GUIUtil
void mouseReleaseEvent(QMouseEvent *event);
};
-#if defined(Q_OS_MAC) && QT_VERSION >= 0x050000
+#if defined(Q_OS_MAC)
// workaround for Qt OSX Bug:
// https://bugreports.qt-project.org/browse/QTBUG-15631
// QProgressBar uses around 10% CPU even when app is in background
diff --git a/src/qt/macdockiconhandler.mm b/src/qt/macdockiconhandler.mm
index 9e7de0f98f..a0b62ae000 100644
--- a/src/qt/macdockiconhandler.mm
+++ b/src/qt/macdockiconhandler.mm
@@ -14,10 +14,6 @@
#include <objc/objc.h>
#include <objc/message.h>
-#if QT_VERSION < 0x050000
-extern void qt_mac_set_dock_menu(QMenu *);
-#endif
-
static MacDockIconHandler *s_instance = nullptr;
bool dockClickHandler(id self,SEL _cmd,...) {
@@ -54,9 +50,7 @@ MacDockIconHandler::MacDockIconHandler() : QObject()
this->m_dummyWidget = new QWidget();
this->m_dockMenu = new QMenu(this->m_dummyWidget);
this->setMainWindow(nullptr);
-#if QT_VERSION < 0x050000
- qt_mac_set_dock_menu(this->m_dockMenu);
-#elif QT_VERSION >= 0x050200
+#if QT_VERSION >= 0x050200
this->m_dockMenu->setAsDockMenu();
#endif
[pool release];
diff --git a/src/qt/networkstyle.cpp b/src/qt/networkstyle.cpp
index 2816633b0f..c4b732e3e0 100644
--- a/src/qt/networkstyle.cpp
+++ b/src/qt/networkstyle.cpp
@@ -68,11 +68,7 @@ NetworkStyle::NetworkStyle(const QString &_appName, const int iconColorHueShift,
}
//convert back to QPixmap
-#if QT_VERSION >= 0x040700
pixmap.convertFromImage(img);
-#else
- pixmap = QPixmap::fromImage(img);
-#endif
}
appIcon = QIcon(pixmap);
diff --git a/src/qt/openuridialog.cpp b/src/qt/openuridialog.cpp
index 751cfa8b43..d211f908c8 100644
--- a/src/qt/openuridialog.cpp
+++ b/src/qt/openuridialog.cpp
@@ -15,9 +15,7 @@ OpenURIDialog::OpenURIDialog(QWidget *parent) :
ui(new Ui::OpenURIDialog)
{
ui->setupUi(this);
-#if QT_VERSION >= 0x040700
ui->uriEdit->setPlaceholderText("bitcoin:");
-#endif
}
OpenURIDialog::~OpenURIDialog()
diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp
index 108aa4f99c..3ff6f59c25 100644
--- a/src/qt/optionsdialog.cpp
+++ b/src/qt/optionsdialog.cpp
@@ -97,28 +97,16 @@ OptionsDialog::OptionsDialog(QWidget *parent, bool enableWallet) :
/** check if the locale name consists of 2 parts (language_country) */
if(langStr.contains("_"))
{
-#if QT_VERSION >= 0x040800
/** display language strings as "native language - native country (locale name)", e.g. "Deutsch - Deutschland (de)" */
ui->lang->addItem(locale.nativeLanguageName() + QString(" - ") + locale.nativeCountryName() + QString(" (") + langStr + QString(")"), QVariant(langStr));
-#else
- /** display language strings as "language - country (locale name)", e.g. "German - Germany (de)" */
- ui->lang->addItem(QLocale::languageToString(locale.language()) + QString(" - ") + QLocale::countryToString(locale.country()) + QString(" (") + langStr + QString(")"), QVariant(langStr));
-#endif
}
else
{
-#if QT_VERSION >= 0x040800
/** display language strings as "native language (locale name)", e.g. "Deutsch (de)" */
ui->lang->addItem(locale.nativeLanguageName() + QString(" (") + langStr + QString(")"), QVariant(langStr));
-#else
- /** display language strings as "language (locale name)", e.g. "German (de)" */
- ui->lang->addItem(QLocale::languageToString(locale.language()) + QString(" (") + langStr + QString(")"), QVariant(langStr));
-#endif
}
}
-#if QT_VERSION >= 0x040700
ui->thirdPartyTxUrls->setPlaceholderText("https://example.com/tx/%s");
-#endif
ui->unit->setModel(new BitcoinUnits(this));
diff --git a/src/qt/paymentrequestplus.cpp b/src/qt/paymentrequestplus.cpp
index b0ef475b35..dfeb70d669 100644
--- a/src/qt/paymentrequestplus.cpp
+++ b/src/qt/paymentrequestplus.cpp
@@ -97,12 +97,10 @@ bool PaymentRequestPlus::getMerchant(X509_STORE* certStore, QString& merchant) c
qWarning() << "PaymentRequestPlus::getMerchant: Payment request: certificate expired or not yet active: " << qCert;
return false;
}
-#if QT_VERSION >= 0x050000
if (qCert.isBlacklisted()) {
qWarning() << "PaymentRequestPlus::getMerchant: Payment request: certificate blacklisted: " << qCert;
return false;
}
-#endif
const unsigned char *data = (const unsigned char *)certChain.certificate(i).data();
X509 *cert = d2i_X509(nullptr, &data, certChain.certificate(i).size());
if (cert)
diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp
index 59bb5d5bb6..e5e6430959 100644
--- a/src/qt/paymentserver.cpp
+++ b/src/qt/paymentserver.cpp
@@ -41,12 +41,7 @@
#include <QSslSocket>
#include <QStringList>
#include <QTextDocument>
-
-#if QT_VERSION < 0x050000
-#include <QUrl>
-#else
#include <QUrlQuery>
-#endif
const int BITCOIN_IPC_CONNECT_TIMEOUT = 1000; // milliseconds
const QString BITCOIN_IPC_PREFIX("bitcoin:");
@@ -100,11 +95,7 @@ static QList<QString> savedPaymentRequests;
static void ReportInvalidCertificate(const QSslCertificate& cert)
{
-#if QT_VERSION < 0x050000
- qDebug() << QString("%1: Payment server found an invalid certificate: ").arg(__func__) << cert.serialNumber() << cert.subjectInfo(QSslCertificate::CommonName) << cert.subjectInfo(QSslCertificate::OrganizationalUnitName);
-#else
qDebug() << QString("%1: Payment server found an invalid certificate: ").arg(__func__) << cert.serialNumber() << cert.subjectInfo(QSslCertificate::CommonName) << cert.subjectInfo(QSslCertificate::DistinguishedNameQualifier) << cert.subjectInfo(QSslCertificate::OrganizationalUnitName);
-#endif
}
//
@@ -157,13 +148,11 @@ void PaymentServer::LoadRootCAs(X509_STORE* _store)
continue;
}
-#if QT_VERSION >= 0x050000
// Blacklisted certificate
if (cert.isBlacklisted()) {
ReportInvalidCertificate(cert);
continue;
}
-#endif
QByteArray certData = cert.toDer();
const unsigned char *data = (const unsigned char *)certData.data();
@@ -413,11 +402,7 @@ void PaymentServer::handleURIOrFile(const QString& s)
}
else if (s.startsWith(BITCOIN_IPC_PREFIX, Qt::CaseInsensitive)) // bitcoin: URI
{
-#if QT_VERSION < 0x050000
- QUrl uri(s);
-#else
QUrlQuery uri((QUrl(s)));
-#endif
if (uri.hasQueryItem("r")) // payment request URI
{
QByteArray temp;
diff --git a/src/qt/peertablemodel.cpp b/src/qt/peertablemodel.cpp
index 7e318e3035..0ca9d48bf6 100644
--- a/src/qt/peertablemodel.cpp
+++ b/src/qt/peertablemodel.cpp
@@ -64,9 +64,7 @@ public:
interfaces::Node::NodesStats nodes_stats;
node.getNodesStats(nodes_stats);
-#if QT_VERSION >= 0x040700
cachedNodeStats.reserve(nodes_stats.size());
-#endif
for (auto& node_stats : nodes_stats)
{
CNodeCombinedStats stats;
diff --git a/src/qt/platformstyle.cpp b/src/qt/platformstyle.cpp
index fce71f661a..a3a10aac18 100644
--- a/src/qt/platformstyle.cpp
+++ b/src/qt/platformstyle.cpp
@@ -46,7 +46,7 @@ void MakeSingleColorImage(QImage& img, const QColor& colorbase)
QIcon ColorizeIcon(const QIcon& ico, const QColor& colorbase)
{
QIcon new_ico;
- for (const QSize sz : ico.availableSizes())
+ for (const QSize& sz : ico.availableSizes())
{
QImage img(ico.pixmap(sz).toImage());
MakeSingleColorImage(img, colorbase);
diff --git a/src/qt/receiverequestdialog.cpp b/src/qt/receiverequestdialog.cpp
index 75146e2214..f9610f2d3b 100644
--- a/src/qt/receiverequestdialog.cpp
+++ b/src/qt/receiverequestdialog.cpp
@@ -16,9 +16,6 @@
#include <QMimeData>
#include <QMouseEvent>
#include <QPixmap>
-#if QT_VERSION < 0x050000
-#include <QUrl>
-#endif
#if defined(HAVE_CONFIG_H)
#include <config/bitcoin-config.h> /* for USE_QRCODE */
diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp
index 4550ae9396..f222357f27 100644
--- a/src/qt/rpcconsole.cpp
+++ b/src/qt/rpcconsole.cpp
@@ -40,10 +40,6 @@
#include <QTimer>
#include <QStringList>
-#if QT_VERSION < 0x050000
-#include <QUrl>
-#endif
-
// TODO: add a scrollback limit, as there is currently none
// TODO: make it possible to filter out categories (esp debug messages when implemented)
// TODO: receive errors and debug messages through ClientModel
@@ -713,6 +709,16 @@ void RPCConsole::addWallet(WalletModel * const walletModel)
ui->WalletSelectorLabel->setVisible(true);
}
}
+
+void RPCConsole::removeWallet(WalletModel * const walletModel)
+{
+ const QString name = walletModel->getWalletName();
+ ui->WalletSelector->removeItem(ui->WalletSelector->findData(name));
+ if (ui->WalletSelector->count() == 2) {
+ ui->WalletSelector->setVisible(false);
+ ui->WalletSelectorLabel->setVisible(false);
+ }
+}
#endif
static QString categoryClass(int category)
diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h
index a53c4c24f9..0a1a469934 100644
--- a/src/qt/rpcconsole.h
+++ b/src/qt/rpcconsole.h
@@ -48,6 +48,7 @@ public:
void setClientModel(ClientModel *model);
void addWallet(WalletModel * const walletModel);
+ void removeWallet(WalletModel* const walletModel);
enum MessageClass {
MC_ERROR,
diff --git a/src/qt/sendcoinsentry.cpp b/src/qt/sendcoinsentry.cpp
index 977425f7e3..e8c85bc2a1 100644
--- a/src/qt/sendcoinsentry.cpp
+++ b/src/qt/sendcoinsentry.cpp
@@ -32,9 +32,7 @@ SendCoinsEntry::SendCoinsEntry(const PlatformStyle *_platformStyle, QWidget *par
if (platformStyle->getUseExtraSpacing())
ui->payToLayout->setSpacing(4);
-#if QT_VERSION >= 0x040700
ui->addAsLabel->setPlaceholderText(tr("Enter a label for this address to add it to your address book"));
-#endif
// normal bitcoin address field
GUIUtil::setupAddressWidget(ui->payTo, this);
diff --git a/src/qt/signverifymessagedialog.cpp b/src/qt/signverifymessagedialog.cpp
index 94a3ad7987..c8e694e658 100644
--- a/src/qt/signverifymessagedialog.cpp
+++ b/src/qt/signverifymessagedialog.cpp
@@ -37,9 +37,7 @@ SignVerifyMessageDialog::SignVerifyMessageDialog(const PlatformStyle *_platformS
ui->verifyMessageButton_VM->setIcon(platformStyle->SingleColorIcon(":/icons/transaction_0"));
ui->clearButton_VM->setIcon(platformStyle->SingleColorIcon(":/icons/remove"));
-#if QT_VERSION >= 0x040700
ui->signatureOut_SM->setPlaceholderText(tr("Click \"Sign Message\" to generate signature"));
-#endif
GUIUtil::setupAddressWidget(ui->addressIn_SM, this);
GUIUtil::setupAddressWidget(ui->addressIn_VM, this);
diff --git a/src/qt/test/test_main.cpp b/src/qt/test/test_main.cpp
index 56d4d3e457..f0ac43a58c 100644
--- a/src/qt/test/test_main.cpp
+++ b/src/qt/test/test_main.cpp
@@ -26,12 +26,6 @@
#if defined(QT_STATICPLUGIN)
#include <QtPlugin>
-#if QT_VERSION < 0x050000
-Q_IMPORT_PLUGIN(qcncodecs)
-Q_IMPORT_PLUGIN(qjpcodecs)
-Q_IMPORT_PLUGIN(qtwcodecs)
-Q_IMPORT_PLUGIN(qkrcodecs)
-#else
#if defined(QT_QPA_PLATFORM_MINIMAL)
Q_IMPORT_PLUGIN(QMinimalIntegrationPlugin);
#endif
@@ -43,7 +37,6 @@ Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin);
Q_IMPORT_PLUGIN(QCocoaIntegrationPlugin);
#endif
#endif
-#endif
extern void noui_connect();
diff --git a/src/qt/test/wallettests.cpp b/src/qt/test/wallettests.cpp
index 33c49dc7cb..c314dadde4 100644
--- a/src/qt/test/wallettests.cpp
+++ b/src/qt/test/wallettests.cpp
@@ -87,17 +87,6 @@ QModelIndex FindTx(const QAbstractItemModel& model, const uint256& txid)
return {};
}
-//! Request context menu (call method that is public in qt5, but protected in qt4).
-void RequestContextMenu(QWidget* widget)
-{
- class Qt4Hack : public QWidget
- {
- public:
- using QWidget::customContextMenuRequested;
- };
- static_cast<Qt4Hack*>(widget)->customContextMenuRequested({});
-}
-
//! Invoke bumpfee on txid and check results.
void BumpFee(TransactionView& view, const uint256& txid, bool expectDisabled, std::string expectError, bool cancel)
{
@@ -110,7 +99,7 @@ void BumpFee(TransactionView& view, const uint256& txid, bool expectDisabled, st
QAction* action = view.findChild<QAction*>("bumpFeeAction");
table->selectionModel()->select(index, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
action->setEnabled(expectDisabled);
- RequestContextMenu(table);
+ table->customContextMenuRequested({});
QCOMPARE(action->isEnabled(), !expectDisabled);
action->setEnabled(true);
diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp
index aa6444245a..e60a387934 100644
--- a/src/qt/transactionview.cpp
+++ b/src/qt/transactionview.cpp
@@ -95,15 +95,11 @@ TransactionView::TransactionView(const PlatformStyle *platformStyle, QWidget *pa
hlayout->addWidget(typeWidget);
search_widget = new QLineEdit(this);
-#if QT_VERSION >= 0x040700
search_widget->setPlaceholderText(tr("Enter address, transaction id, or label to search"));
-#endif
hlayout->addWidget(search_widget);
amountWidget = new QLineEdit(this);
-#if QT_VERSION >= 0x040700
amountWidget->setPlaceholderText(tr("Min amount"));
-#endif
if (platformStyle->getUseExtraSpacing()) {
amountWidget->setFixedWidth(97);
} else {
diff --git a/src/qt/walletframe.cpp b/src/qt/walletframe.cpp
index eb0eba21ef..c5a13f61f4 100644
--- a/src/qt/walletframe.cpp
+++ b/src/qt/walletframe.cpp
@@ -94,6 +94,7 @@ bool WalletFrame::removeWallet(const QString &name)
WalletView *walletView = mapWalletViews.take(name);
walletStack->removeWidget(walletView);
+ delete walletView;
return true;
}
diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp
index 3418b1f1a9..389acf0a95 100644
--- a/src/qt/walletmodel.cpp
+++ b/src/qt/walletmodel.cpp
@@ -364,6 +364,12 @@ bool WalletModel::changePassphrase(const SecureString &oldPass, const SecureStri
}
// Handlers for core signals
+static void NotifyUnload(WalletModel* walletModel)
+{
+ qDebug() << "NotifyUnload";
+ QMetaObject::invokeMethod(walletModel, "unload", Qt::QueuedConnection);
+}
+
static void NotifyKeyStoreStatusChanged(WalletModel *walletmodel)
{
qDebug() << "NotifyKeyStoreStatusChanged";
@@ -411,6 +417,7 @@ static void NotifyWatchonlyChanged(WalletModel *walletmodel, bool fHaveWatchonly
void WalletModel::subscribeToCoreSignals()
{
// Connect signals to wallet
+ m_handler_unload = m_wallet->handleUnload(boost::bind(&NotifyUnload, this));
m_handler_status_changed = m_wallet->handleStatusChanged(boost::bind(&NotifyKeyStoreStatusChanged, this));
m_handler_address_book_changed = m_wallet->handleAddressBookChanged(boost::bind(NotifyAddressBookChanged, this, _1, _2, _3, _4, _5));
m_handler_transaction_changed = m_wallet->handleTransactionChanged(boost::bind(NotifyTransactionChanged, this, _1, _2));
@@ -421,6 +428,7 @@ void WalletModel::subscribeToCoreSignals()
void WalletModel::unsubscribeFromCoreSignals()
{
// Disconnect signals from wallet
+ m_handler_unload->disconnect();
m_handler_status_changed->disconnect();
m_handler_address_book_changed->disconnect();
m_handler_transaction_changed->disconnect();
diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h
index 9173fcae52..35ededb121 100644
--- a/src/qt/walletmodel.h
+++ b/src/qt/walletmodel.h
@@ -208,6 +208,7 @@ public:
AddressTableModel* getAddressTableModel() const { return addressTableModel; }
private:
std::unique_ptr<interfaces::Wallet> m_wallet;
+ std::unique_ptr<interfaces::Handler> m_handler_unload;
std::unique_ptr<interfaces::Handler> m_handler_status_changed;
std::unique_ptr<interfaces::Handler> m_handler_address_book_changed;
std::unique_ptr<interfaces::Handler> m_handler_transaction_changed;
@@ -261,6 +262,9 @@ Q_SIGNALS:
// Watch-only address added
void notifyWatchonlyChanged(bool fHaveWatchonly);
+ // Signal that wallet is about to be removed
+ void unload();
+
public Q_SLOTS:
/* Wallet status might have changed */
void updateStatus();
diff --git a/src/qt/winshutdownmonitor.cpp b/src/qt/winshutdownmonitor.cpp
index 1e7a76efc0..6190a74598 100644
--- a/src/qt/winshutdownmonitor.cpp
+++ b/src/qt/winshutdownmonitor.cpp
@@ -4,7 +4,7 @@
#include <qt/winshutdownmonitor.h>
-#if defined(Q_OS_WIN) && QT_VERSION >= 0x050000
+#if defined(Q_OS_WIN)
#include <init.h>
#include <util.h>
diff --git a/src/qt/winshutdownmonitor.h b/src/qt/winshutdownmonitor.h
index 0bed55a2c6..c8a523a538 100644
--- a/src/qt/winshutdownmonitor.h
+++ b/src/qt/winshutdownmonitor.h
@@ -9,7 +9,6 @@
#include <QByteArray>
#include <QString>
-#if QT_VERSION >= 0x050000
#include <windef.h> // for HWND
#include <QAbstractNativeEventFilter>
@@ -24,6 +23,5 @@ public:
static void registerShutdownBlockReason(const QString& strReason, const HWND& mainWinId);
};
#endif
-#endif
#endif // BITCOIN_QT_WINSHUTDOWNMONITOR_H
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index 68279d7ffd..d9d803ac7d 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -853,7 +853,7 @@ static void ApplyStats(CCoinsStats &stats, CHashWriter& ss, const uint256& hash,
ss << hash;
ss << VARINT(outputs.begin()->second.nHeight * 2 + outputs.begin()->second.fCoinBase ? 1u : 0u);
stats.nTransactions++;
- for (const auto output : outputs) {
+ for (const auto& output : outputs) {
ss << VARINT(output.first + 1);
ss << output.second.out.scriptPubKey;
ss << VARINT(output.second.out.nValue, VarIntMode::NONNEGATIVE_SIGNED);
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index 1c6dba0c9c..8090172e3f 100644
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -69,12 +69,12 @@ void CTxMemPool::UpdateForDescendants(txiter updateIt, cacheMap &cachedDescendan
setAllDescendants.insert(cit);
stageEntries.erase(cit);
const setEntries &setChildren = GetMemPoolChildren(cit);
- for (const txiter childEntry : setChildren) {
+ for (txiter childEntry : setChildren) {
cacheMap::iterator cacheIt = cachedDescendants.find(childEntry);
if (cacheIt != cachedDescendants.end()) {
// We've already calculated this one, just add the entries for this set
// but don't traverse again.
- for (const txiter cacheEntry : cacheIt->second) {
+ for (txiter cacheEntry : cacheIt->second) {
setAllDescendants.insert(cacheEntry);
}
} else if (!setAllDescendants.count(childEntry)) {
diff --git a/src/validation.cpp b/src/validation.cpp
index baf083b153..3b8118b036 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -651,7 +651,7 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
view.SetBackend(viewMemPool);
// do all inputs exist?
- for (const CTxIn txin : tx.vin) {
+ for (const CTxIn& txin : tx.vin) {
if (!pcoinsTip->HaveCoinInCache(txin.prevout)) {
coins_to_uncache.push_back(txin.prevout);
}
@@ -957,7 +957,7 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
}
// Remove conflicting transactions from the mempool
- for (const CTxMemPool::txiter it : allConflicting)
+ for (CTxMemPool::txiter it : allConflicting)
{
LogPrint(BCLog::MEMPOOL, "replacing tx %s with %s for %s BTC additional fees, %d delta bytes\n",
it->GetTx().GetHash().ToString(),
diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp
index 410dd5009f..01b8eacccb 100644
--- a/src/wallet/db.cpp
+++ b/src/wallet/db.cpp
@@ -694,8 +694,10 @@ void BerkeleyEnvironment::Flush(bool fShutdown)
if (mapFileUseCount.empty()) {
dbenv->log_archive(&listp, DB_ARCH_REMOVE);
Close();
- if (!fMockDb)
+ if (!fMockDb) {
fs::remove_all(fs::path(strPath) / "database");
+ }
+ g_dbenvs.erase(strPath);
}
}
}
@@ -794,5 +796,6 @@ void BerkeleyDatabase::Flush(bool shutdown)
{
if (!IsDummy()) {
env->Flush(shutdown);
+ if (shutdown) env = nullptr;
}
}
diff --git a/src/wallet/init.cpp b/src/wallet/init.cpp
index daeff1d0e8..74312b7124 100644
--- a/src/wallet/init.cpp
+++ b/src/wallet/init.cpp
@@ -200,7 +200,7 @@ bool WalletInit::Verify() const
// Keep track of each wallet absolute path to detect duplicates.
std::set<fs::path> wallet_paths;
- for (const auto wallet_file : wallet_files) {
+ for (const auto& wallet_file : wallet_files) {
fs::path wallet_path = fs::absolute(wallet_file, GetWalletDir());
if (!wallet_paths.insert(wallet_path).second) {
diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp
index d09af1dbd1..882ddbbe4e 100644
--- a/src/wallet/rpcdump.cpp
+++ b/src/wallet/rpcdump.cpp
@@ -441,7 +441,7 @@ UniValue importpubkey(const JSONRPCRequest& request)
return NullUniValue;
}
- if (request.fHelp || request.params.size() < 1 || request.params.size() > 4)
+ if (request.fHelp || request.params.size() < 1 || request.params.size() > 3)
throw std::runtime_error(
"importpubkey \"pubkey\" ( \"label\" rescan )\n"
"\nAdds a public key (in hex) that can be watched as if it were in your wallet but cannot be used to spend. Requires a new wallet backup.\n"
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index fd9e23cb64..3f2255d042 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -40,12 +40,21 @@
static const std::string WALLET_ENDPOINT_BASE = "/wallet/";
-std::shared_ptr<CWallet> GetWalletForJSONRPCRequest(const JSONRPCRequest& request)
+bool GetWalletNameFromJSONRPCRequest(const JSONRPCRequest& request, std::string& wallet_name)
{
if (request.URI.substr(0, WALLET_ENDPOINT_BASE.size()) == WALLET_ENDPOINT_BASE) {
// wallet endpoint was used
- std::string requestedWallet = urlDecode(request.URI.substr(WALLET_ENDPOINT_BASE.size()));
- std::shared_ptr<CWallet> pwallet = GetWallet(requestedWallet);
+ wallet_name = urlDecode(request.URI.substr(WALLET_ENDPOINT_BASE.size()));
+ return true;
+ }
+ return false;
+}
+
+std::shared_ptr<CWallet> GetWalletForJSONRPCRequest(const JSONRPCRequest& request)
+{
+ std::string wallet_name;
+ if (GetWalletNameFromJSONRPCRequest(request, wallet_name)) {
+ std::shared_ptr<CWallet> pwallet = GetWallet(wallet_name);
if (!pwallet) throw JSONRPCError(RPC_WALLET_NOT_FOUND, "Requested wallet does not exist or is not loaded");
return pwallet;
}
@@ -66,11 +75,6 @@ bool EnsureWalletIsAvailable(CWallet * const pwallet, bool avoidException)
if (pwallet) return true;
if (avoidException) return false;
if (!HasWallets()) {
- // Note: It isn't currently possible to trigger this error because
- // wallet RPC methods aren't registered unless a wallet is loaded. But
- // this error is being kept as a precaution, because it's possible in
- // the future that wallet RPC methods might get or remain registered
- // when no wallets are loaded.
throw JSONRPCError(
RPC_METHOD_NOT_FOUND, "Method not found (wallet method is disabled because no wallet is loaded)");
}
@@ -3053,7 +3057,7 @@ static UniValue listwallets(const JSONRPCRequest& request)
return obj;
}
-UniValue loadwallet(const JSONRPCRequest& request)
+static UniValue loadwallet(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 1)
throw std::runtime_error(
@@ -3100,7 +3104,7 @@ UniValue loadwallet(const JSONRPCRequest& request)
return obj;
}
-UniValue createwallet(const JSONRPCRequest& request)
+static UniValue createwallet(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 1) {
throw std::runtime_error(
@@ -3147,6 +3151,55 @@ UniValue createwallet(const JSONRPCRequest& request)
return obj;
}
+static UniValue unloadwallet(const JSONRPCRequest& request)
+{
+ if (request.fHelp || request.params.size() > 1) {
+ throw std::runtime_error(
+ "unloadwallet ( \"wallet_name\" )\n"
+ "Unloads the wallet referenced by the request endpoint otherwise unloads the wallet specified in the argument.\n"
+ "Specifying the wallet name on a wallet endpoint is invalid."
+ "\nArguments:\n"
+ "1. \"wallet_name\" (string, optional) The name of the wallet to unload.\n"
+ "\nExamples:\n"
+ + HelpExampleCli("unloadwallet", "wallet_name")
+ + HelpExampleRpc("unloadwallet", "wallet_name")
+ );
+ }
+
+ std::string wallet_name;
+ if (GetWalletNameFromJSONRPCRequest(request, wallet_name)) {
+ if (!request.params[0].isNull()) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot unload the requested wallet");
+ }
+ } else {
+ wallet_name = request.params[0].get_str();
+ }
+
+ std::shared_ptr<CWallet> wallet = GetWallet(wallet_name);
+ if (!wallet) {
+ throw JSONRPCError(RPC_WALLET_NOT_FOUND, "Requested wallet does not exist or is not loaded");
+ }
+
+ // Release the "main" shared pointer and prevent further notifications.
+ // Note that any attempt to load the same wallet would fail until the wallet
+ // is destroyed (see CheckUniqueFileid).
+ if (!RemoveWallet(wallet)) {
+ throw JSONRPCError(RPC_MISC_ERROR, "Requested wallet already unloaded");
+ }
+ UnregisterValidationInterface(wallet.get());
+
+ // The wallet can be in use so it's not possible to explicitly unload here.
+ // Just notify the unload intent so that all shared pointers are released.
+ // The wallet will be destroyed once the last shared pointer is released.
+ wallet->NotifyUnload();
+
+ // There's no point in waiting for the wallet to unload.
+ // At this point this method should never fail. The unloading could only
+ // fail due to an unexpected error which would cause a process termination.
+
+ return NullUniValue;
+}
+
static UniValue resendwallettransactions(const JSONRPCRequest& request)
{
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
@@ -4382,6 +4435,7 @@ static const CRPCCommand commands[] =
{ "wallet", "settxfee", &settxfee, {"amount"} },
{ "wallet", "signmessage", &signmessage, {"address","message"} },
{ "wallet", "signrawtransactionwithwallet", &signrawtransactionwithwallet, {"hexstring","prevtxs","sighashtype"} },
+ { "wallet", "unloadwallet", &unloadwallet, {"wallet_name"} },
{ "wallet", "walletlock", &walletlock, {} },
{ "wallet", "walletpassphrasechange", &walletpassphrasechange, {"oldpassphrase","newpassphrase"} },
{ "wallet", "walletpassphrase", &walletpassphrase, {"passphrase","timeout"} },
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index ca785298fd..842516bb0e 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -79,6 +79,15 @@ std::shared_ptr<CWallet> GetWallet(const std::string& name)
return nullptr;
}
+// Custom deleter for shared_ptr<CWallet>.
+static void ReleaseWallet(CWallet* wallet)
+{
+ LogPrintf("Releasing wallet %s\n", wallet->GetName());
+ wallet->BlockUntilSyncedToCurrentChain();
+ wallet->Flush();
+ delete wallet;
+}
+
const uint32_t BIP32_HARDENED_KEY_LIMIT = 0x80000000;
const uint256 CMerkleTx::ABANDON_HASH(uint256S("0000000000000000000000000000000000000000000000000000000000000001"));
@@ -600,6 +609,8 @@ void CWallet::AddToSpends(const COutPoint& outpoint, const uint256& wtxid)
{
mapTxSpends.insert(std::make_pair(outpoint, wtxid));
+ setLockedCoins.erase(outpoint);
+
std::pair<TxSpends::iterator, TxSpends::iterator> range;
range = mapTxSpends.equal_range(outpoint);
SyncMetaData(range);
@@ -1296,7 +1307,7 @@ void CWallet::BlockUntilSyncedToCurrentChain() {
LOCK(cs_main);
const CBlockIndex* initialChainTip = chainActive.Tip();
- if (m_last_block_processed->GetAncestor(initialChainTip->nHeight) == initialChainTip) {
+ if (m_last_block_processed && m_last_block_processed->GetAncestor(initialChainTip->nHeight) == initialChainTip) {
return;
}
}
@@ -4066,7 +4077,9 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(const std::string& name,
int64_t nStart = GetTimeMillis();
bool fFirstRun = true;
- std::shared_ptr<CWallet> walletInstance = std::make_shared<CWallet>(name, WalletDatabase::Create(path));
+ // TODO: Can't use std::make_shared because we need a custom deleter but
+ // should be possible to use std::allocate_shared.
+ std::shared_ptr<CWallet> walletInstance(new CWallet(name, WalletDatabase::Create(path)), ReleaseWallet);
DBErrors nLoadWalletRet = walletInstance->LoadWallet(fFirstRun);
if (nLoadWalletRet != DBErrors::LOAD_OK)
{
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index aacbdf81d6..b829394847 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -1100,6 +1100,9 @@ public:
//! Flush wallet (bitdb flush)
void Flush(bool shutdown=false);
+ /** Wallet is about to be unloaded */
+ boost::signals2::signal<void ()> NotifyUnload;
+
/**
* Address book entry changed.
* @note called with lock cs_wallet held.