diff options
Diffstat (limited to 'src')
32 files changed, 423 insertions, 211 deletions
diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index 445849e3d8..f4f84e2a99 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -120,6 +120,7 @@ QT_MOC_CPP = \ qt/moc_bantablemodel.cpp \ qt/moc_bitcoinaddressvalidator.cpp \ qt/moc_bitcoinamountfield.cpp \ + qt/moc_bitcoin.cpp \ qt/moc_bitcoingui.cpp \ qt/moc_bitcoinunits.cpp \ qt/moc_clientmodel.cpp \ @@ -166,7 +167,6 @@ BITCOIN_MM = \ qt/macos_appnap.mm QT_MOC = \ - qt/bitcoin.moc \ qt/bitcoinamountfield.moc \ qt/intro.moc \ qt/overviewpage.moc \ @@ -194,6 +194,7 @@ BITCOIN_QT_H = \ qt/bantablemodel.h \ qt/bitcoinaddressvalidator.h \ qt/bitcoinamountfield.h \ + qt/bitcoin.h \ qt/bitcoingui.h \ qt/bitcoinunits.h \ qt/clientmodel.h \ @@ -302,6 +303,7 @@ RES_ICONS = \ BITCOIN_QT_BASE_CPP = \ qt/bantablemodel.cpp \ + qt/bitcoin.cpp \ qt/bitcoinaddressvalidator.cpp \ qt/bitcoinamountfield.cpp \ qt/bitcoingui.cpp \ @@ -382,6 +384,9 @@ qt_libbitcoinqt_a_OBJCXXFLAGS = $(AM_OBJCXXFLAGS) $(QT_PIE_FLAGS) qt_libbitcoinqt_a_SOURCES = $(BITCOIN_QT_CPP) $(BITCOIN_QT_H) $(QT_FORMS_UI) \ $(QT_QRC) $(QT_QRC_LOCALE) $(QT_TS) $(PROTOBUF_PROTO) $(RES_ICONS) $(RES_IMAGES) $(RES_MOVIES) +if TARGET_DARWIN + qt_libbitcoinqt_a_SOURCES += $(BITCOIN_MM) +endif nodist_qt_libbitcoinqt_a_SOURCES = $(QT_MOC_CPP) $(QT_MOC) $(PROTOBUF_CC) \ $(PROTOBUF_H) $(QT_QRC_CPP) $(QT_QRC_LOCALE_CPP) @@ -404,10 +409,7 @@ qt_bitcoin_qt_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(BITCOIN_QT_INCLUDE $(QT_INCLUDES) $(PROTOBUF_CFLAGS) $(QR_CFLAGS) qt_bitcoin_qt_CXXFLAGS = $(AM_CXXFLAGS) $(QT_PIE_FLAGS) -qt_bitcoin_qt_SOURCES = qt/bitcoin.cpp -if TARGET_DARWIN - qt_bitcoin_qt_SOURCES += $(BITCOIN_MM) -endif +qt_bitcoin_qt_SOURCES = qt/main.cpp if TARGET_WINDOWS qt_bitcoin_qt_SOURCES += $(BITCOIN_RC) endif diff --git a/src/Makefile.qttest.include b/src/Makefile.qttest.include index db7873e8b7..61977b50cd 100644 --- a/src/Makefile.qttest.include +++ b/src/Makefile.qttest.include @@ -6,6 +6,7 @@ bin_PROGRAMS += qt/test/test_bitcoin-qt TESTS += qt/test/test_bitcoin-qt TEST_QT_MOC_CPP = \ + qt/test/moc_apptests.cpp \ qt/test/moc_compattests.cpp \ qt/test/moc_rpcnestedtests.cpp \ qt/test/moc_uritests.cpp @@ -22,6 +23,7 @@ endif # ENABLE_WALLET TEST_QT_H = \ qt/test/addressbooktests.h \ + qt/test/apptests.h \ qt/test/compattests.h \ qt/test/rpcnestedtests.h \ qt/test/uritests.h \ @@ -40,6 +42,7 @@ qt_test_test_bitcoin_qt_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(BITCOIN_ $(QT_INCLUDES) $(QT_TEST_INCLUDES) $(PROTOBUF_CFLAGS) qt_test_test_bitcoin_qt_SOURCES = \ + qt/test/apptests.cpp \ qt/test/compattests.cpp \ qt/test/rpcnestedtests.cpp \ qt/test/test_main.cpp \ diff --git a/src/addrman.h b/src/addrman.h index af5a1d3b23..003bd059f8 100644 --- a/src/addrman.h +++ b/src/addrman.h @@ -23,33 +23,31 @@ */ class CAddrInfo : public CAddress { - - public: //! last try whatsoever by us (memory only) - int64_t nLastTry; + int64_t nLastTry{0}; //! last counted attempt (memory only) - int64_t nLastCountAttempt; + int64_t nLastCountAttempt{0}; private: //! where knowledge about this address first came from CNetAddr source; //! last successful connection by us - int64_t nLastSuccess; + int64_t nLastSuccess{0}; //! connection attempts since last successful attempt - int nAttempts; + int nAttempts{0}; //! reference count in new sets (memory only) - int nRefCount; + int nRefCount{0}; //! in tried set? (memory only) - bool fInTried; + bool fInTried{false}; //! position in vRandom - int nRandomPos; + int nRandomPos{-1}; friend class CAddrMan; @@ -65,25 +63,12 @@ public: READWRITE(nAttempts); } - void Init() - { - nLastSuccess = 0; - nLastTry = 0; - nLastCountAttempt = 0; - nAttempts = 0; - nRefCount = 0; - fInTried = false; - nRandomPos = -1; - } - CAddrInfo(const CAddress &addrIn, const CNetAddr &addrSource) : CAddress(addrIn), source(addrSource) { - Init(); } CAddrInfo() : CAddress(), source() { - Init(); } //! Calculate in which "tried" bucket this entry belongs @@ -106,7 +91,6 @@ public: //! Calculate the relative chance this entry should be given when selecting nodes to connect to double GetChance(int64_t nNow = GetAdjustedTime()) const; - }; /** Stochastic address manager diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 4ce1b53880..d334233224 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -272,10 +272,10 @@ public: strNetworkID = "regtest"; consensus.nSubsidyHalvingInterval = 150; consensus.BIP16Exception = uint256(); - consensus.BIP34Height = 100000000; // BIP34 has not activated on regtest (far in the future so block v1 are not rejected in tests) + consensus.BIP34Height = 500; // BIP34 activated on regtest (Used in functional tests) consensus.BIP34Hash = uint256(); - consensus.BIP65Height = 1351; // BIP65 activated on regtest (Used in rpc activation tests) - consensus.BIP66Height = 1251; // BIP66 activated on regtest (Used in rpc activation tests) + consensus.BIP65Height = 1351; // BIP65 activated on regtest (Used in functional tests) + consensus.BIP66Height = 1251; // BIP66 activated on regtest (Used in functional tests) consensus.powLimit = uint256S("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); consensus.nPowTargetTimespan = 14 * 24 * 60 * 60; // two weeks consensus.nPowTargetSpacing = 10 * 60; diff --git a/src/httpserver.cpp b/src/httpserver.cpp index cb8578927a..ca60ea43a7 100644 --- a/src/httpserver.cpp +++ b/src/httpserver.cpp @@ -124,7 +124,6 @@ public: struct HTTPPathHandler { - HTTPPathHandler() {} HTTPPathHandler(std::string _prefix, bool _exactMatch, HTTPRequestHandler _handler): prefix(_prefix), exactMatch(_exactMatch), handler(_handler) { diff --git a/src/index/base.cpp b/src/index/base.cpp index 4d4a7e1502..f6f59572ce 100644 --- a/src/index/base.cpp +++ b/src/index/base.cpp @@ -60,7 +60,11 @@ bool BaseIndex::Init() } LOCK(cs_main); - m_best_block_index = FindForkInGlobalIndex(chainActive, locator); + if (locator.IsNull()) { + m_best_block_index = nullptr; + } else { + m_best_block_index = FindForkInGlobalIndex(chainActive, locator); + } m_synced = m_best_block_index.load() == chainActive.Tip(); return true; } diff --git a/src/index/txindex.cpp b/src/index/txindex.cpp index ba1c44765f..10bc8419dd 100644 --- a/src/index/txindex.cpp +++ b/src/index/txindex.cpp @@ -245,6 +245,9 @@ bool TxIndex::Init() bool TxIndex::WriteBlock(const CBlock& block, const CBlockIndex* pindex) { + // Exclude genesis block transaction because outputs are not spendable. + if (pindex->nHeight == 0) return true; + CDiskTxPos pos(pindex->GetBlockPos(), GetSizeOfCompactSize(block.vtx.size())); std::vector<std::pair<uint256, CDiskTxPos>> vPos; vPos.reserve(block.vtx.size()); diff --git a/src/net.cpp b/src/net.cpp index 902830f79c..03ee7af5e4 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2316,14 +2316,6 @@ void CConnman::SetNetworkActive(bool active) CConnman::CConnman(uint64_t nSeed0In, uint64_t nSeed1In) : nSeed0(nSeed0In), nSeed1(nSeed1In) { - fNetworkActive = true; - setBannedIsDirty = false; - fAddressesInitialized = false; - nLastNodeId = 0; - nPrevNodeCount = 0; - nSendBufferMaxSize = 0; - nReceiveFloodSize = 0; - flagInterruptMsgProc = false; SetTryNewOutboundPeer(false); Options connOptions; @@ -404,15 +404,15 @@ private: // whitelisted (as well as those connecting to whitelisted binds). std::vector<CSubNet> vWhitelistedRange; - unsigned int nSendBufferMaxSize; - unsigned int nReceiveFloodSize; + unsigned int nSendBufferMaxSize{0}; + unsigned int nReceiveFloodSize{0}; std::vector<ListenSocket> vhListenSocket; - std::atomic<bool> fNetworkActive; + std::atomic<bool> fNetworkActive{true}; banmap_t setBanned GUARDED_BY(cs_setBanned); CCriticalSection cs_setBanned; - bool setBannedIsDirty GUARDED_BY(cs_setBanned); - bool fAddressesInitialized; + bool setBannedIsDirty GUARDED_BY(cs_setBanned){false}; + bool fAddressesInitialized{false}; CAddrMan addrman; std::deque<std::string> vOneShots GUARDED_BY(cs_vOneShots); CCriticalSection cs_vOneShots; @@ -421,8 +421,8 @@ private: std::vector<CNode*> vNodes; std::list<CNode*> vNodesDisconnected; mutable CCriticalSection cs_vNodes; - std::atomic<NodeId> nLastNodeId; - unsigned int nPrevNodeCount; + std::atomic<NodeId> nLastNodeId{0}; + unsigned int nPrevNodeCount{0}; /** Services this instance offers */ ServiceFlags nLocalServices; @@ -446,7 +446,7 @@ private: std::condition_variable condMsgProc; Mutex mutexMsgProc; - std::atomic<bool> flagInterruptMsgProc; + std::atomic<bool> flagInterruptMsgProc{false}; CThreadInterrupt interruptNet; diff --git a/src/protocol.h b/src/protocol.h index 50d197415b..a790a06906 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -402,7 +402,6 @@ public: std::string GetCommand() const; std::string ToString() const; - // TODO: make private (improves encapsulation) public: int type; uint256 hash; diff --git a/src/qt/bantablemodel.cpp b/src/qt/bantablemodel.cpp index dcfe3dcc57..713db595d5 100644 --- a/src/qt/bantablemodel.cpp +++ b/src/qt/bantablemodel.cpp @@ -40,8 +40,8 @@ class BanTablePriv public: /** Local cache of peer information */ QList<CCombinedBan> cachedBanlist; - /** Column to sort nodes by */ - int sortColumn; + /** Column to sort nodes by (default to unsorted) */ + int sortColumn{-1}; /** Order (ascending or descending) to sort nodes by */ Qt::SortOrder sortOrder; @@ -87,8 +87,6 @@ BanTableModel::BanTableModel(interfaces::Node& node, ClientModel *parent) : { columns << tr("IP/Netmask") << tr("Banned Until"); priv.reset(new BanTablePriv()); - // default to unsorted - priv->sortColumn = -1; // load initial data refresh(); diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index 922987b7bc..cf1bc6450e 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -6,6 +6,7 @@ #include <config/bitcoin-config.h> #endif +#include <qt/bitcoin.h> #include <qt/bitcoingui.h> #include <chainparams.h> @@ -71,11 +72,6 @@ Q_DECLARE_METATYPE(bool*) Q_DECLARE_METATYPE(CAmount) Q_DECLARE_METATYPE(uint256) -/** Translate string to current locale using Qt. */ -const std::function<std::string(const char*)> G_TRANSLATION_FUN = [](const char* psz) { - return QCoreApplication::translate("bitcoin-core", psz).toStdString(); -}; - static QString GetLangTerritory() { QSettings settings; @@ -140,101 +136,6 @@ void DebugMessageHandler(QtMsgType type, const QMessageLogContext& context, cons } } -/** Class encapsulating Bitcoin Core startup and shutdown. - * Allows running startup and shutdown in a different thread from the UI thread. - */ -class BitcoinCore: public QObject -{ - Q_OBJECT -public: - explicit BitcoinCore(interfaces::Node& node); - -public Q_SLOTS: - void initialize(); - void shutdown(); - -Q_SIGNALS: - void initializeResult(bool success); - void shutdownResult(); - void runawayException(const QString &message); - -private: - /// Pass fatal exception message to UI thread - void handleRunawayException(const std::exception *e); - - interfaces::Node& m_node; -}; - -/** Main Bitcoin application object */ -class BitcoinApplication: public QApplication -{ - Q_OBJECT -public: - explicit BitcoinApplication(interfaces::Node& node, int &argc, char **argv); - ~BitcoinApplication(); - -#ifdef ENABLE_WALLET - /// Create payment server - void createPaymentServer(); -#endif - /// parameter interaction/setup based on rules - void parameterSetup(); - /// Create options model - void createOptionsModel(bool resetSettings); - /// Create main window - void createWindow(const NetworkStyle *networkStyle); - /// Create splash screen - void createSplashScreen(const NetworkStyle *networkStyle); - - /// Request core initialization - void requestInitialize(); - /// Request core shutdown - void requestShutdown(); - - /// Get process return value - int getReturnValue() const { return returnValue; } - - /// Get window identifier of QMainWindow (BitcoinGUI) - WId getMainWinId() const; - - /// Setup platform style - void setupPlatformStyle(); - -public Q_SLOTS: - void initializeResult(bool success); - void shutdownResult(); - /// 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(); - void requestedShutdown(); - void stopThread(); - void splashFinished(); - -private: - QThread *coreThread; - interfaces::Node& m_node; - OptionsModel *optionsModel; - ClientModel *clientModel; - BitcoinGUI *window; - QTimer *pollShutdownTimer; -#ifdef ENABLE_WALLET - PaymentServer* paymentServer; - std::vector<WalletModel*> m_wallet_models; - std::unique_ptr<interfaces::Handler> m_handler_load_wallet; -#endif - int returnValue; - const PlatformStyle *platformStyle; - std::unique_ptr<QWidget> shutdownWindow; - - void startThread(); -}; - -#include <qt/bitcoin.moc> - BitcoinCore::BitcoinCore(interfaces::Node& node) : QObject(), m_node(node) { @@ -358,6 +259,11 @@ void BitcoinApplication::createSplashScreen(const NetworkStyle *networkStyle) connect(this, &BitcoinApplication::requestedShutdown, splash, &QWidget::close); } +bool BitcoinApplication::baseInitialize() +{ + return m_node.baseInitialize(); +} + void BitcoinApplication::startThread() { if(coreThread) @@ -467,7 +373,7 @@ void BitcoinApplication::initializeResult(bool success) #ifdef ENABLE_BIP70 PaymentServer::LoadRootCAs(); #endif - paymentServer->setOptionsModel(optionsModel); + if (paymentServer) paymentServer->setOptionsModel(optionsModel); #endif clientModel = new ClientModel(m_node, optionsModel); @@ -496,16 +402,19 @@ void BitcoinApplication::initializeResult(bool success) window->show(); } Q_EMIT splashFinished(); + Q_EMIT windowShown(window); #ifdef ENABLE_WALLET // Now that initialization/startup is done, process any command-line // bitcoin: URIs or payment requests: - connect(paymentServer, &PaymentServer::receivedPaymentRequest, window, &BitcoinGUI::handlePaymentRequest); - connect(window, &BitcoinGUI::receivedURI, paymentServer, &PaymentServer::handleURIOrFile); - connect(paymentServer, &PaymentServer::message, [this](const QString& title, const QString& message, unsigned int style) { - window->message(title, message, style); - }); - QTimer::singleShot(100, paymentServer, &PaymentServer::uiReady); + if (paymentServer) { + connect(paymentServer, &PaymentServer::receivedPaymentRequest, window, &BitcoinGUI::handlePaymentRequest); + connect(window, &BitcoinGUI::receivedURI, paymentServer, &PaymentServer::handleURIOrFile); + connect(paymentServer, &PaymentServer::message, [this](const QString& title, const QString& message, unsigned int style) { + window->message(title, message, style); + }); + QTimer::singleShot(100, paymentServer, &PaymentServer::uiReady); + } #endif pollShutdownTimer->start(200); } else { @@ -548,7 +457,7 @@ static void SetupUIArgs() } #ifndef BITCOIN_QT_TEST -int main(int argc, char *argv[]) +int GuiMain(int argc, char* argv[]) { #ifdef WIN32 util::WinCmdLineArgs winArgs; @@ -706,7 +615,7 @@ int main(int argc, char *argv[]) // Perform base initialization before spinning up initialization/shutdown thread // This is acceptable because this function only contains steps that are quick to execute, // so the GUI thread won't be held up. - if (node->baseInitialize()) { + if (app.baseInitialize()) { app.requestInitialize(); #if defined(Q_OS_WIN) WinShutdownMonitor::registerShutdownBlockReason(QObject::tr("%1 didn't yet exit safely...").arg(QObject::tr(PACKAGE_NAME)), (HWND)app.getMainWinId()); diff --git a/src/qt/bitcoin.h b/src/qt/bitcoin.h new file mode 100644 index 0000000000..48b5907570 --- /dev/null +++ b/src/qt/bitcoin.h @@ -0,0 +1,127 @@ +// Copyright (c) 2011-2016 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_QT_BITCOIN_H +#define BITCOIN_QT_BITCOIN_H + +#if defined(HAVE_CONFIG_H) +#include <config/bitcoin-config.h> +#endif + +#include <QApplication> +#include <memory> +#include <vector> + +class BitcoinGUI; +class ClientModel; +class NetworkStyle; +class OptionsModel; +class PaymentServer; +class PlatformStyle; +class WalletModel; + +namespace interfaces { +class Handler; +class Node; +} // namespace interfaces + +/** Class encapsulating Bitcoin Core startup and shutdown. + * Allows running startup and shutdown in a different thread from the UI thread. + */ +class BitcoinCore: public QObject +{ + Q_OBJECT +public: + explicit BitcoinCore(interfaces::Node& node); + +public Q_SLOTS: + void initialize(); + void shutdown(); + +Q_SIGNALS: + void initializeResult(bool success); + void shutdownResult(); + void runawayException(const QString &message); + +private: + /// Pass fatal exception message to UI thread + void handleRunawayException(const std::exception *e); + + interfaces::Node& m_node; +}; + +/** Main Bitcoin application object */ +class BitcoinApplication: public QApplication +{ + Q_OBJECT +public: + explicit BitcoinApplication(interfaces::Node& node, int &argc, char **argv); + ~BitcoinApplication(); + +#ifdef ENABLE_WALLET + /// Create payment server + void createPaymentServer(); +#endif + /// parameter interaction/setup based on rules + void parameterSetup(); + /// Create options model + void createOptionsModel(bool resetSettings); + /// Create main window + void createWindow(const NetworkStyle *networkStyle); + /// Create splash screen + void createSplashScreen(const NetworkStyle *networkStyle); + /// Basic initialization, before starting initialization/shutdown thread. Return true on success. + bool baseInitialize(); + + /// Request core initialization + void requestInitialize(); + /// Request core shutdown + void requestShutdown(); + + /// Get process return value + int getReturnValue() const { return returnValue; } + + /// Get window identifier of QMainWindow (BitcoinGUI) + WId getMainWinId() const; + + /// Setup platform style + void setupPlatformStyle(); + +public Q_SLOTS: + void initializeResult(bool success); + void shutdownResult(); + /// 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(); + void requestedShutdown(); + void stopThread(); + void splashFinished(); + void windowShown(BitcoinGUI* window); + +private: + QThread *coreThread; + interfaces::Node& m_node; + OptionsModel *optionsModel; + ClientModel *clientModel; + BitcoinGUI *window; + QTimer *pollShutdownTimer; +#ifdef ENABLE_WALLET + PaymentServer* paymentServer; + std::vector<WalletModel*> m_wallet_models; + std::unique_ptr<interfaces::Handler> m_handler_load_wallet; +#endif + int returnValue; + const PlatformStyle *platformStyle; + std::unique_ptr<QWidget> shutdownWindow; + + void startThread(); +}; + +int GuiMain(int argc, char* argv[]); + +#endif // BITCOIN_QT_BITCOIN_H diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 0ca5b5fcdc..155f8efe7f 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -110,6 +110,7 @@ BitcoinGUI::BitcoinGUI(interfaces::Node& node, const PlatformStyle *_platformSty * the central widget is the rpc console. */ setCentralWidget(rpcConsole); + Q_EMIT consoleShown(rpcConsole); } // Accept D&D of URIs @@ -324,6 +325,7 @@ void BitcoinGUI::createActions() openRPCConsoleAction->setStatusTip(tr("Open debugging and diagnostic console")); // initially disable the debug window menu item openRPCConsoleAction->setEnabled(false); + openRPCConsoleAction->setObjectName("openRPCConsoleAction"); usedSendingAddressesAction = new QAction(platformStyle->TextColorIcon(":/icons/address-book"), tr("&Sending addresses"), this); usedSendingAddressesAction->setStatusTip(tr("Show the list of used sending addresses and labels")); @@ -640,9 +642,11 @@ void BitcoinGUI::createTrayIcon(const NetworkStyle *networkStyle) assert(QSystemTrayIcon::isSystemTrayAvailable()); #ifndef Q_OS_MAC - trayIcon = new QSystemTrayIcon(networkStyle->getTrayAndWindowIcon(), this); - QString toolTip = tr("%1 client").arg(tr(PACKAGE_NAME)) + " " + networkStyle->getTitleAddText(); - trayIcon->setToolTip(toolTip); + if (QSystemTrayIcon::isSystemTrayAvailable()) { + trayIcon = new QSystemTrayIcon(networkStyle->getTrayAndWindowIcon(), this); + QString toolTip = tr("%1 client").arg(tr(PACKAGE_NAME)) + " " + networkStyle->getTitleAddText(); + trayIcon->setToolTip(toolTip); + } #endif } @@ -722,6 +726,7 @@ void BitcoinGUI::aboutClicked() void BitcoinGUI::showDebugWindow() { GUIUtil::bringToFront(rpcConsole); + Q_EMIT consoleShown(rpcConsole); } void BitcoinGUI::showDebugWindowActivateConsole() diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index 1324dd6625..e6c62d43bd 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -187,6 +187,8 @@ private: Q_SIGNALS: /** Signal raised when a URI was entered or dragged to the GUI */ void receivedURI(const QString &uri); + /** Signal raised when RPC console shown */ + void consoleShown(RPCConsole* console); public Q_SLOTS: /** Set number of connections shown in the UI */ diff --git a/src/qt/main.cpp b/src/qt/main.cpp new file mode 100644 index 0000000000..6a3c2249d1 --- /dev/null +++ b/src/qt/main.cpp @@ -0,0 +1,17 @@ +// Copyright (c) 2018 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 <qt/bitcoin.h> + +#include <QCoreApplication> + +#include <functional> +#include <string> + +/** Translate string to current locale using Qt. */ +extern const std::function<std::string(const char*)> G_TRANSLATION_FUN = [](const char* psz) { + return QCoreApplication::translate("bitcoin-core", psz).toStdString(); +}; + +int main(int argc, char* argv[]) { return GuiMain(argc, argv); } diff --git a/src/qt/peertablemodel.cpp b/src/qt/peertablemodel.cpp index 8cfedca57f..e2e78fe81b 100644 --- a/src/qt/peertablemodel.cpp +++ b/src/qt/peertablemodel.cpp @@ -49,8 +49,8 @@ class PeerTablePriv public: /** Local cache of peer information */ QList<CNodeCombinedStats> cachedNodeStats; - /** Column to sort nodes by */ - int sortColumn; + /** Column to sort nodes by (default to unsorted) */ + int sortColumn{-1}; /** Order (ascending or descending) to sort nodes by */ Qt::SortOrder sortOrder; /** Index of rows by node ID */ @@ -108,8 +108,6 @@ PeerTableModel::PeerTableModel(interfaces::Node& node, ClientModel *parent) : { columns << tr("NodeId") << tr("Node/Service") << tr("Ping") << tr("Sent") << tr("Received") << tr("User Agent"); priv.reset(new PeerTablePriv()); - // default to unsorted - priv->sortColumn = -1; // set up timer for auto refresh timer = new QTimer(this); diff --git a/src/qt/recentrequeststablemodel.cpp b/src/qt/recentrequeststablemodel.cpp index 82ab48ac20..aa746017f3 100644 --- a/src/qt/recentrequeststablemodel.cpp +++ b/src/qt/recentrequeststablemodel.cpp @@ -15,8 +15,6 @@ RecentRequestsTableModel::RecentRequestsTableModel(WalletModel *parent) : QAbstractTableModel(parent), walletModel(parent) { - nReceiveRequestsMaxId = 0; - // Load entries from wallet std::vector<std::string> vReceiveRequests; parent->loadReceiveRequests(vReceiveRequests); diff --git a/src/qt/recentrequeststablemodel.h b/src/qt/recentrequeststablemodel.h index ff2c0c8098..8a1140e952 100644 --- a/src/qt/recentrequeststablemodel.h +++ b/src/qt/recentrequeststablemodel.h @@ -94,7 +94,7 @@ private: WalletModel *walletModel; QStringList columns; QList<RecentRequestEntry> list; - int64_t nReceiveRequestsMaxId; + int64_t nReceiveRequestsMaxId{0}; /** Updates the column title to "Amount (DisplayUnit)" and emits headerDataChanged() signal for table headers to react. */ void updateAmountColumnTitle(); diff --git a/src/qt/test/apptests.cpp b/src/qt/test/apptests.cpp new file mode 100644 index 0000000000..2c477a2e98 --- /dev/null +++ b/src/qt/test/apptests.cpp @@ -0,0 +1,117 @@ +// Copyright (c) 2018 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 <qt/test/apptests.h> + +#include <chainparams.h> +#include <init.h> +#include <qt/bitcoin.h> +#include <qt/bitcoingui.h> +#include <qt/networkstyle.h> +#include <qt/rpcconsole.h> +#include <shutdown.h> +#include <validation.h> + +#if defined(HAVE_CONFIG_H) +#include <config/bitcoin-config.h> +#endif +#ifdef ENABLE_WALLET +#include <wallet/db.h> +#endif + +#include <QAction> +#include <QEventLoop> +#include <QLineEdit> +#include <QScopedPointer> +#include <QTest> +#include <QTextEdit> +#include <QtGlobal> +#if QT_VERSION >= 0x050000 +#include <QtTest/QtTestWidgets> +#endif +#include <QtTest/QtTestGui> +#include <new> +#include <string> +#include <univalue.h> + +namespace { +//! Call getblockchaininfo RPC and check first field of JSON output. +void TestRpcCommand(RPCConsole* console) +{ + QEventLoop loop; + QTextEdit* messagesWidget = console->findChild<QTextEdit*>("messagesWidget"); + QObject::connect(messagesWidget, &QTextEdit::textChanged, &loop, &QEventLoop::quit); + QLineEdit* lineEdit = console->findChild<QLineEdit*>("lineEdit"); + QTest::keyClicks(lineEdit, "getblockchaininfo"); + QTest::keyClick(lineEdit, Qt::Key_Return); + loop.exec(); + QString output = messagesWidget->toPlainText(); + UniValue value; + value.read(output.right(output.size() - output.lastIndexOf(QChar::ObjectReplacementCharacter) - 1).toStdString()); + QCOMPARE(value["chain"].get_str(), std::string("regtest")); +} +} // namespace + +//! Entry point for BitcoinApplication tests. +void AppTests::appTests() +{ +#ifdef Q_OS_MAC + if (QApplication::platformName() == "minimal") { + // Disable for mac on "minimal" platform to avoid crashes inside the Qt + // framework when it tries to look up unimplemented cocoa functions, + // and fails to handle returned nulls + // (https://bugreports.qt.io/browse/QTBUG-49686). + QWARN("Skipping AppTests on mac build with 'minimal' platform set due to Qt bugs. To run AppTests, invoke " + "with 'test_bitcoin-qt -platform cocoa' on mac, or else use a linux or windows build."); + return; + } +#endif + + m_app.parameterSetup(); + m_app.createOptionsModel(true /* reset settings */); + QScopedPointer<const NetworkStyle> style( + NetworkStyle::instantiate(QString::fromStdString(Params().NetworkIDString()))); + m_app.setupPlatformStyle(); + m_app.createWindow(style.data()); + connect(&m_app, &BitcoinApplication::windowShown, this, &AppTests::guiTests); + expectCallback("guiTests"); + m_app.baseInitialize(); + m_app.requestInitialize(); + m_app.exec(); + m_app.requestShutdown(); + m_app.exec(); + + // Reset global state to avoid interfering with later tests. + AbortShutdown(); + UnloadBlockIndex(); +} + +//! Entry point for BitcoinGUI tests. +void AppTests::guiTests(BitcoinGUI* window) +{ + HandleCallback callback{"guiTests", *this}; + connect(window, &BitcoinGUI::consoleShown, this, &AppTests::consoleTests); + expectCallback("consoleTests"); + QAction* action = window->findChild<QAction*>("openRPCConsoleAction"); + action->activate(QAction::Trigger); +} + +//! Entry point for RPCConsole tests. +void AppTests::consoleTests(RPCConsole* console) +{ + HandleCallback callback{"consoleTests", *this}; + TestRpcCommand(console); +} + +//! Destructor to shut down after the last expected callback completes. +AppTests::HandleCallback::~HandleCallback() +{ + auto& callbacks = m_app_tests.m_callbacks; + auto it = callbacks.find(m_callback); + assert(it != callbacks.end()); + callbacks.erase(it); + if (callbacks.empty()) { + m_app_tests.m_app.quit(); + } +} diff --git a/src/qt/test/apptests.h b/src/qt/test/apptests.h new file mode 100644 index 0000000000..83bf56f1e4 --- /dev/null +++ b/src/qt/test/apptests.h @@ -0,0 +1,50 @@ +// Copyright (c) 2018 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_QT_TEST_APPTESTS_H +#define BITCOIN_QT_TEST_APPTESTS_H + +#include <QObject> +#include <set> +#include <string> +#include <utility> + +class BitcoinApplication; +class BitcoinGUI; +class RPCConsole; + +class AppTests : public QObject +{ + Q_OBJECT +public: + explicit AppTests(BitcoinApplication& app) : m_app(app) {} + +private Q_SLOTS: + void appTests(); + void guiTests(BitcoinGUI* window); + void consoleTests(RPCConsole* console); + +private: + //! Add expected callback name to list of pending callbacks. + void expectCallback(std::string callback) { m_callbacks.emplace(std::move(callback)); } + + //! RAII helper to remove no-longer-pending callback. + struct HandleCallback + { + std::string m_callback; + AppTests& m_app_tests; + ~HandleCallback(); + }; + + //! Bitcoin application. + BitcoinApplication& m_app; + + //! Set of pending callback names. Used to track expected callbacks and shut + //! down the app after the last callback has been handled and all tests have + //! either run or thrown exceptions. This could be a simple int counter + //! instead of a set of names, but the names might be useful for debugging. + std::multiset<std::string> m_callbacks; +}; + +#endif // BITCOIN_QT_TEST_APPTESTS_H diff --git a/src/qt/test/rpcnestedtests.cpp b/src/qt/test/rpcnestedtests.cpp index ed453336da..173c814f1e 100644 --- a/src/qt/test/rpcnestedtests.cpp +++ b/src/qt/test/rpcnestedtests.cpp @@ -41,7 +41,7 @@ void RPCNestedTests::rpcNestedTests() TestingSetup test; - SetRPCWarmupFinished(); + if (RPCIsInWarmup(nullptr)) SetRPCWarmupFinished(); std::string result; std::string result2; diff --git a/src/qt/test/test_main.cpp b/src/qt/test/test_main.cpp index b6523604fd..a2bf53973b 100644 --- a/src/qt/test/test_main.cpp +++ b/src/qt/test/test_main.cpp @@ -7,6 +7,9 @@ #endif #include <chainparams.h> +#include <interfaces/node.h> +#include <qt/bitcoin.h> +#include <qt/test/apptests.h> #include <qt/test/rpcnestedtests.h> #include <util/system.h> #include <qt/test/uritests.h> @@ -47,12 +50,13 @@ int main(int argc, char *argv[]) { SetupEnvironment(); SetupNetworking(); - SelectParams(CBaseChainParams::MAIN); + SelectParams(CBaseChainParams::REGTEST); noui_connect(); ClearDatadirCache(); fs::path pathTemp = fs::temp_directory_path() / strprintf("test_bitcoin-qt_%lu_%i", (unsigned long)GetTime(), (int)GetRand(100000)); fs::create_directories(pathTemp); gArgs.ForceSetArg("-datadir", pathTemp.string()); + auto node = interfaces::MakeNode(); bool fInvalid = false; @@ -67,11 +71,15 @@ int main(int argc, char *argv[]) // Don't remove this, it's needed to access // QApplication:: and QCoreApplication:: in the tests - QApplication app(argc, argv); + BitcoinApplication app(*node, argc, argv); app.setApplicationName("Bitcoin-Qt-test"); SSL_library_init(); + AppTests app_tests(app); + if (QTest::qExec(&app_tests) != 0) { + fInvalid = true; + } URITests test1; if (QTest::qExec(&test1) != 0) { fInvalid = true; diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index b7fa636494..0a5b21f997 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -40,8 +40,6 @@ WalletModel::WalletModel(std::unique_ptr<interfaces::Wallet> wallet, interfaces: cachedNumBlocks(0) { fHaveWatchOnly = m_wallet->haveWatchOnly(); - fForceCheckBalanceChanged = false; - addressTableModel = new AddressTableModel(this); transactionTableModel = new TransactionTableModel(platformStyle, this); recentRequestsTableModel = new RecentRequestsTableModel(this); diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h index 2988682533..6a6c538157 100644 --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -235,7 +235,7 @@ private: interfaces::Node& m_node; bool fHaveWatchOnly; - bool fForceCheckBalanceChanged; + bool fForceCheckBalanceChanged{false}; // Wallet has an options model for wallet-specific options // (transaction fee, for example) diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 4846d7cc95..315f69d46b 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -747,15 +747,20 @@ static UniValue getblockheader(const JSONRPCRequest& request) + HelpExampleRpc("getblockheader", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"") ); - LOCK(cs_main); - uint256 hash(ParseHashV(request.params[0], "hash")); bool fVerbose = true; if (!request.params[1].isNull()) fVerbose = request.params[1].get_bool(); - const CBlockIndex* pblockindex = LookupBlockIndex(hash); + const CBlockIndex* pblockindex; + const CBlockIndex* tip; + { + LOCK(cs_main); + pblockindex = LookupBlockIndex(hash); + tip = chainActive.Tip(); + } + if (!pblockindex) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); } @@ -768,7 +773,7 @@ static UniValue getblockheader(const JSONRPCRequest& request) return strHex; } - return blockheaderToJSON(chainActive.Tip(), pblockindex); + return blockheaderToJSON(tip, pblockindex); } static CBlock GetBlockChecked(const CBlockIndex* pblockindex) diff --git a/src/test/addrman_tests.cpp b/src/test/addrman_tests.cpp index 234da5ae4d..22347fbc57 100644 --- a/src/test/addrman_tests.cpp +++ b/src/test/addrman_tests.cpp @@ -12,13 +12,9 @@ class CAddrManTest : public CAddrMan { - uint64_t state; - public: explicit CAddrManTest(bool makeDeterministic = true) { - state = 1; - if (makeDeterministic) { // Set addrman addr placement to be deterministic. MakeDeterministic(); diff --git a/src/test/txindex_tests.cpp b/src/test/txindex_tests.cpp index 43e025c58f..0301901bf0 100644 --- a/src/test/txindex_tests.cpp +++ b/src/test/txindex_tests.cpp @@ -2,6 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include <chainparams.h> #include <index/txindex.h> #include <script/standard.h> #include <test/test_bitcoin.h> @@ -38,6 +39,12 @@ BOOST_FIXTURE_TEST_CASE(txindex_initial_sync, TestChain100Setup) MilliSleep(100); } + // Check that txindex excludes genesis block transactions. + const CBlock& genesis_block = Params().GenesisBlock(); + for (const auto& txn : genesis_block.vtx) { + BOOST_CHECK(!txindex.FindTx(txn->GetHash(), block_hash, tx_disk)); + } + // Check that txindex has all txs that were in the chain before it started. for (const auto& txn : m_coinbase_txns) { if (!txindex.FindTx(txn->GetHash(), block_hash, tx_disk)) { diff --git a/src/util/system.cpp b/src/util/system.cpp index 8e201ec590..ffe4d21ee3 100644 --- a/src/util/system.cpp +++ b/src/util/system.cpp @@ -865,7 +865,7 @@ static bool GetConfigOptions(std::istream& stream, std::string& error, std::vect } else if ((pos = str.find('=')) != std::string::npos) { std::string name = prefix + TrimString(str.substr(0, pos), pattern); std::string value = TrimString(str.substr(pos + 1), pattern); - if (used_hash && name == "rpcpassword") { + if (used_hash && name.find("rpcpassword") != std::string::npos) { error = strprintf("parse error on line %i, using # in rpcpassword can be ambiguous and should be avoided", linenr); return false; } diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index c1cdd0b2ee..38397a3940 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -1020,15 +1020,12 @@ static UniValue addmultisigaddress(const JSONRPCRequest& request) struct tallyitem { - CAmount nAmount; - int nConf; + CAmount nAmount{0}; + int nConf{std::numeric_limits<int>::max()}; std::vector<uint256> txids; - bool fIsWatchonly; + bool fIsWatchonly{false}; tallyitem() { - nAmount = 0; - nConf = std::numeric_limits<int>::max(); - fIsWatchonly = false; } }; diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 95a2c833f8..3a3ec43c9b 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -1178,18 +1178,16 @@ class CReserveKey final : public CReserveScript { protected: CWallet* pwallet; - int64_t nIndex; + int64_t nIndex{-1}; CPubKey vchPubKey; - bool fInternal; + bool fInternal{false}; + public: explicit CReserveKey(CWallet* pwalletIn) { - nIndex = -1; pwallet = pwalletIn; - fInternal = false; } - CReserveKey() = default; CReserveKey(const CReserveKey&) = delete; CReserveKey& operator=(const CReserveKey&) = delete; diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 09a33f252c..6e037808e3 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -153,21 +153,17 @@ bool WalletBatch::WriteMinVersion(int nVersion) class CWalletScanState { public: - unsigned int nKeys; - unsigned int nCKeys; - unsigned int nWatchKeys; - unsigned int nKeyMeta; - unsigned int m_unknown_records; - bool fIsEncrypted; - bool fAnyUnordered; - int nFileVersion; + unsigned int nKeys{0}; + unsigned int nCKeys{0}; + unsigned int nWatchKeys{0}; + unsigned int nKeyMeta{0}; + unsigned int m_unknown_records{0}; + bool fIsEncrypted{false}; + bool fAnyUnordered{false}; + int nFileVersion{0}; std::vector<uint256> vWalletUpgrade; CWalletScanState() { - nKeys = nCKeys = nWatchKeys = nKeyMeta = m_unknown_records = 0; - fIsEncrypted = false; - fAnyUnordered = false; - nFileVersion = 0; } }; |