aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Makefile.qt.include12
-rw-r--r--src/Makefile.qttest.include3
-rw-r--r--src/addrman.h30
-rw-r--r--src/chainparams.cpp6
-rw-r--r--src/httpserver.cpp1
-rw-r--r--src/index/base.cpp6
-rw-r--r--src/index/txindex.cpp3
-rw-r--r--src/init.cpp8
-rw-r--r--src/net.cpp14
-rw-r--r--src/net.h16
-rw-r--r--src/protocol.h1
-rw-r--r--src/qt/bantablemodel.cpp6
-rw-r--r--src/qt/bitcoin.cpp127
-rw-r--r--src/qt/bitcoin.h127
-rw-r--r--src/qt/bitcoingui.cpp11
-rw-r--r--src/qt/bitcoingui.h2
-rw-r--r--src/qt/main.cpp17
-rw-r--r--src/qt/peertablemodel.cpp6
-rw-r--r--src/qt/recentrequeststablemodel.cpp2
-rw-r--r--src/qt/recentrequeststablemodel.h2
-rw-r--r--src/qt/rpcconsole.cpp3
-rw-r--r--src/qt/test/apptests.cpp117
-rw-r--r--src/qt/test/apptests.h50
-rw-r--r--src/qt/test/rpcnestedtests.cpp2
-rw-r--r--src/qt/test/test_main.cpp12
-rw-r--r--src/qt/walletmodel.cpp2
-rw-r--r--src/qt/walletmodel.h2
-rw-r--r--src/rpc/blockchain.cpp13
-rw-r--r--src/support/allocators/secure.h6
-rw-r--r--src/support/lockedpool.cpp3
-rw-r--r--src/support/lockedpool.h2
-rw-r--r--src/test/addrman_tests.cpp4
-rw-r--r--src/test/getarg_tests.cpp3
-rw-r--r--src/test/net_tests.cpp89
-rw-r--r--src/test/txindex_tests.cpp7
-rw-r--r--src/uint256.cpp2
-rw-r--r--src/util/moneystr.cpp6
-rw-r--r--src/util/system.cpp4
-rw-r--r--src/wallet/rpcwallet.cpp9
-rw-r--r--src/wallet/wallet.h8
-rw-r--r--src/wallet/walletdb.cpp20
-rwxr-xr-xtest/functional/feature_block.py30
-rwxr-xr-xtest/functional/feature_config_args.py8
-rw-r--r--test/functional/test_framework/blocktools.py3
-rwxr-xr-xtest/lint/lint-locale-dependence.sh13
45 files changed, 572 insertions, 246 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/init.cpp b/src/init.cpp
index 18c145a023..f4f00ea691 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -1631,8 +1631,14 @@ bool AppInitMain(InitInterfaces& interfaces)
// ********************************************************* Step 11: import blocks
- if (!CheckDiskSpace() && !CheckDiskSpace(0, true))
+ if (!CheckDiskSpace(/* additional_bytes */ 0, /* blocks_dir */ false)) {
+ InitError(strprintf(_("Error: Disk space is low for %s"), GetDataDir()));
return false;
+ }
+ if (!CheckDiskSpace(/* additional_bytes */ 0, /* blocks_dir */ true)) {
+ InitError(strprintf(_("Error: Disk space is low for %s"), GetBlocksDir()));
+ return false;
+ }
// Either install a handler to notify us when genesis activates, or set fHaveGenesis directly.
// No locking, as this happens before any background thread is started.
diff --git a/src/net.cpp b/src/net.cpp
index 902830f79c..86e5225839 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -295,15 +295,13 @@ bool IsLocal(const CService& addr)
/** check whether a given network is one we can probably connect to */
bool IsReachable(enum Network net)
{
- LOCK(cs_mapLocalHost);
- return !vfLimited[net];
+ return !IsLimited(net);
}
/** check whether a given address is in a network we can probably connect to */
bool IsReachable(const CNetAddr& addr)
{
- enum Network net = addr.GetNetwork();
- return IsReachable(net);
+ return IsReachable(addr.GetNetwork());
}
@@ -2316,14 +2314,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;
diff --git a/src/net.h b/src/net.h
index 4af3318656..478f2958af 100644
--- a/src/net.h
+++ b/src/net.h
@@ -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/rpcconsole.cpp b/src/qt/rpcconsole.cpp
index a6187685a9..d062ea49bd 100644
--- a/src/qt/rpcconsole.cpp
+++ b/src/qt/rpcconsole.cpp
@@ -18,6 +18,7 @@
#include <netbase.h>
#include <rpc/server.h>
#include <rpc/client.h>
+#include <util/strencodings.h>
#include <util/system.h>
#include <openssl/crypto.h>
@@ -226,7 +227,7 @@ bool RPCConsole::RPCParseCommandLine(interfaces::Node* node, std::string &strRes
if (lastResult.isArray())
{
for(char argch: curarg)
- if (!std::isdigit(argch))
+ if (!IsDigit(argch))
throw std::runtime_error("Invalid result query");
subelement = lastResult[atoi(curarg.c_str())];
}
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/support/allocators/secure.h b/src/support/allocators/secure.h
index 7cd0df135d..57f5b1f733 100644
--- a/src/support/allocators/secure.h
+++ b/src/support/allocators/secure.h
@@ -40,7 +40,11 @@ struct secure_allocator : public std::allocator<T> {
T* allocate(std::size_t n, const void* hint = 0)
{
- return static_cast<T*>(LockedPoolManager::Instance().alloc(sizeof(T) * n));
+ T* allocation = static_cast<T*>(LockedPoolManager::Instance().alloc(sizeof(T) * n));
+ if (!allocation) {
+ throw std::bad_alloc();
+ }
+ return allocation;
}
void deallocate(T* p, std::size_t n)
diff --git a/src/support/lockedpool.cpp b/src/support/lockedpool.cpp
index 8d577cf521..627018083e 100644
--- a/src/support/lockedpool.cpp
+++ b/src/support/lockedpool.cpp
@@ -248,6 +248,9 @@ void *PosixLockedPageAllocator::AllocateLocked(size_t len, bool *lockingSuccess)
void *addr;
len = align_up(len, page_size);
addr = mmap(nullptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+ if (addr == MAP_FAILED) {
+ return nullptr;
+ }
if (addr) {
*lockingSuccess = mlock(addr, len) == 0;
}
diff --git a/src/support/lockedpool.h b/src/support/lockedpool.h
index 48ffd7b307..b420c909fc 100644
--- a/src/support/lockedpool.h
+++ b/src/support/lockedpool.h
@@ -22,7 +22,7 @@ public:
virtual ~LockedPageAllocator() {}
/** Allocate and lock memory pages.
* If len is not a multiple of the system page size, it is rounded up.
- * Returns 0 in case of allocation failure.
+ * Returns nullptr in case of allocation failure.
*
* If locking the memory pages could not be accomplished it will still
* return the memory, however the lockingSuccess flag will be false.
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/getarg_tests.cpp b/src/test/getarg_tests.cpp
index 14ddf4d10e..8048238028 100644
--- a/src/test/getarg_tests.cpp
+++ b/src/test/getarg_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 <util/strencodings.h>
#include <util/system.h>
#include <test/test_bitcoin.h>
@@ -17,7 +18,7 @@ static void ResetArgs(const std::string& strArg)
{
std::vector<std::string> vecArg;
if (strArg.size())
- boost::split(vecArg, strArg, boost::is_space(), boost::token_compress_on);
+ boost::split(vecArg, strArg, IsSpace, boost::token_compress_on);
// Insert dummy executable name:
vecArg.insert(vecArg.begin(), "testbitcoin");
diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp
index e7a3c96343..4dc394b86d 100644
--- a/src/test/net_tests.cpp
+++ b/src/test/net_tests.cpp
@@ -227,4 +227,93 @@ BOOST_AUTO_TEST_CASE(ipv4_peer_with_ipv6_addrMe_test)
BOOST_CHECK(1);
}
+
+BOOST_AUTO_TEST_CASE(LimitedAndReachable_Network)
+{
+ SetLimited(NET_IPV4, true);
+ SetLimited(NET_IPV6, true);
+ SetLimited(NET_ONION, true);
+
+ BOOST_CHECK_EQUAL(IsLimited(NET_IPV4), true);
+ BOOST_CHECK_EQUAL(IsLimited(NET_IPV6), true);
+ BOOST_CHECK_EQUAL(IsLimited(NET_ONION), true);
+
+ BOOST_CHECK_EQUAL(IsReachable(NET_IPV4), false);
+ BOOST_CHECK_EQUAL(IsReachable(NET_IPV6), false);
+ BOOST_CHECK_EQUAL(IsReachable(NET_ONION), false);
+
+
+ SetLimited(NET_IPV4, false);
+ SetLimited(NET_IPV6, false);
+ SetLimited(NET_ONION, false);
+
+ BOOST_CHECK_EQUAL(IsLimited(NET_IPV4), false);
+ BOOST_CHECK_EQUAL(IsLimited(NET_IPV6), false);
+ BOOST_CHECK_EQUAL(IsLimited(NET_ONION), false);
+
+ BOOST_CHECK_EQUAL(IsReachable(NET_IPV4), true);
+ BOOST_CHECK_EQUAL(IsReachable(NET_IPV6), true);
+ BOOST_CHECK_EQUAL(IsReachable(NET_ONION), true);
+}
+
+BOOST_AUTO_TEST_CASE(LimitedAndReachable_NetworkCaseUnroutableAndInternal)
+{
+ BOOST_CHECK_EQUAL(IsLimited(NET_UNROUTABLE), false);
+ BOOST_CHECK_EQUAL(IsLimited(NET_INTERNAL), false);
+
+ BOOST_CHECK_EQUAL(IsReachable(NET_UNROUTABLE), true);
+ BOOST_CHECK_EQUAL(IsReachable(NET_INTERNAL), true);
+
+ SetLimited(NET_UNROUTABLE, true);
+ SetLimited(NET_INTERNAL, true);
+
+ BOOST_CHECK_EQUAL(IsLimited(NET_UNROUTABLE), false); // Ignored for both networks
+ BOOST_CHECK_EQUAL(IsLimited(NET_INTERNAL), false);
+
+ BOOST_CHECK_EQUAL(IsReachable(NET_UNROUTABLE), true);
+ BOOST_CHECK_EQUAL(IsReachable(NET_INTERNAL), true);
+}
+
+CNetAddr UtilBuildAddress(unsigned char p1, unsigned char p2, unsigned char p3, unsigned char p4)
+{
+ unsigned char ip[] = {p1, p2, p3, p4};
+
+ struct sockaddr_in sa;
+ memset(&sa, 0, sizeof(sockaddr_in)); // initialize the memory block
+ memcpy(&(sa.sin_addr), &ip, sizeof(ip));
+ return CNetAddr(sa.sin_addr);
+}
+
+
+BOOST_AUTO_TEST_CASE(LimitedAndReachable_CNetAddr)
+{
+ CNetAddr addr = UtilBuildAddress(0x001, 0x001, 0x001, 0x001); // 1.1.1.1
+
+ SetLimited(NET_IPV4, false);
+ BOOST_CHECK_EQUAL(IsLimited(addr), false);
+ BOOST_CHECK_EQUAL(IsReachable(addr), true);
+
+ SetLimited(NET_IPV4, true);
+ BOOST_CHECK_EQUAL(IsLimited(addr), true);
+ BOOST_CHECK_EQUAL(IsReachable(addr), false);
+
+ SetLimited(NET_IPV4, false); // have to reset this, because this is stateful.
+}
+
+
+BOOST_AUTO_TEST_CASE(LocalAddress_BasicLifecycle)
+{
+ CService addr = CService(UtilBuildAddress(0x002, 0x001, 0x001, 0x001), 1000); // 2.1.1.1:1000
+
+ SetLimited(NET_IPV4, false);
+
+ BOOST_CHECK_EQUAL(IsLocal(addr), false);
+ BOOST_CHECK_EQUAL(AddLocal(addr, 1000), true);
+ BOOST_CHECK_EQUAL(IsLocal(addr), true);
+
+ RemoveLocal(addr);
+ BOOST_CHECK_EQUAL(IsLocal(addr), false);
+}
+
+
BOOST_AUTO_TEST_SUITE_END()
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/uint256.cpp b/src/uint256.cpp
index d9da668036..b723f9ee54 100644
--- a/src/uint256.cpp
+++ b/src/uint256.cpp
@@ -33,7 +33,7 @@ void base_blob<BITS>::SetHex(const char* psz)
psz++;
// skip 0x
- if (psz[0] == '0' && tolower(psz[1]) == 'x')
+ if (psz[0] == '0' && ToLower((unsigned char)psz[1]) == 'x')
psz += 2;
// hex string to uint
diff --git a/src/util/moneystr.cpp b/src/util/moneystr.cpp
index 4c4de7b729..f4e41eea4f 100644
--- a/src/util/moneystr.cpp
+++ b/src/util/moneystr.cpp
@@ -20,7 +20,7 @@ std::string FormatMoney(const CAmount& n)
// Right-trim excess zeros before the decimal point:
int nTrim = 0;
- for (int i = str.size()-1; (str[i] == '0' && isdigit(str[i-2])); --i)
+ for (int i = str.size()-1; (str[i] == '0' && IsDigit(str[i-2])); --i)
++nTrim;
if (nTrim)
str.erase(str.size()-nTrim, nTrim);
@@ -49,7 +49,7 @@ bool ParseMoney(const char* pszIn, CAmount& nRet)
{
p++;
int64_t nMult = COIN / 10;
- while (isdigit(*p) && (nMult > 0))
+ while (IsDigit(*p) && (nMult > 0))
{
nUnits += nMult * (*p++ - '0');
nMult /= 10;
@@ -58,7 +58,7 @@ bool ParseMoney(const char* pszIn, CAmount& nRet)
}
if (IsSpace(*p))
break;
- if (!isdigit(*p))
+ if (!IsDigit(*p))
return false;
strWhole.insert(strWhole.end(), *p);
}
diff --git a/src/util/system.cpp b/src/util/system.cpp
index 8e201ec590..a4bf126900 100644
--- a/src/util/system.cpp
+++ b/src/util/system.cpp
@@ -443,7 +443,7 @@ bool ArgsManager::ParseParameters(int argc, const char* const argv[], std::strin
key.erase(is_index);
}
#ifdef WIN32
- std::transform(key.begin(), key.end(), key.begin(), ::tolower);
+ std::transform(key.begin(), key.end(), key.begin(), ToLower);
if (key[0] == '/')
key[0] = '-';
#endif
@@ -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;
}
};
diff --git a/test/functional/feature_block.py b/test/functional/feature_block.py
index 244cde044e..5253ff7aaa 100755
--- a/test/functional/feature_block.py
+++ b/test/functional/feature_block.py
@@ -925,7 +925,7 @@ class FullBlockTest(BitcoinTestFramework):
# \-> b67 (20)
#
#
- self.log.info("Reject a block with a transaction double spending a transaction creted in the same block")
+ self.log.info("Reject a block with a transaction double spending a transaction created in the same block")
self.move_tip(65)
b67 = self.next_block(67)
tx1 = self.create_and_sign_transaction(out[20], out[20].vout[0].nValue)
@@ -1220,7 +1220,7 @@ class FullBlockTest(BitcoinTestFramework):
blocks = []
spend = out[32]
for i in range(89, LARGE_REORG_SIZE + 89):
- b = self.next_block(i, spend)
+ b = self.next_block(i, spend, version=4)
tx = CTransaction()
script_length = MAX_BLOCK_BASE_SIZE - len(b.serialize()) - 69
script_output = CScript([b'\x00' * script_length])
@@ -1239,20 +1239,32 @@ class FullBlockTest(BitcoinTestFramework):
self.move_tip(88)
blocks2 = []
for i in range(89, LARGE_REORG_SIZE + 89):
- blocks2.append(self.next_block("alt" + str(i)))
+ blocks2.append(self.next_block("alt" + str(i), version=4))
self.sync_blocks(blocks2, False, force_send=True)
# extend alt chain to trigger re-org
- block = self.next_block("alt" + str(chain1_tip + 1))
+ block = self.next_block("alt" + str(chain1_tip + 1), version=4)
self.sync_blocks([block], True, timeout=480)
# ... and re-org back to the first chain
self.move_tip(chain1_tip)
- block = self.next_block(chain1_tip + 1)
+ block = self.next_block(chain1_tip + 1, version=4)
self.sync_blocks([block], False, force_send=True)
- block = self.next_block(chain1_tip + 2)
+ block = self.next_block(chain1_tip + 2, version=4)
self.sync_blocks([block], True, timeout=480)
+ self.log.info("Reject a block with an invalid block header version")
+ b_v1 = self.next_block('b_v1', version=1)
+ self.sync_blocks([b_v1], success=False, force_send=True, reject_reason='bad-version(0x00000001)')
+
+ self.move_tip(chain1_tip + 2)
+ b_cb34 = self.next_block('b_cb34', version=4)
+ b_cb34.vtx[0].vin[0].scriptSig = b_cb34.vtx[0].vin[0].scriptSig[:-1]
+ b_cb34.vtx[0].rehash()
+ b_cb34.hashMerkleRoot = b_cb34.calc_merkle_root()
+ b_cb34.solve()
+ self.sync_blocks([b_cb34], success=False, reject_reason='bad-cb-height', reconnect=True)
+
# Helper methods
################
@@ -1280,7 +1292,7 @@ class FullBlockTest(BitcoinTestFramework):
tx.rehash()
return tx
- def next_block(self, number, spend=None, additional_coinbase_value=0, script=CScript([OP_TRUE]), solve=True):
+ def next_block(self, number, spend=None, additional_coinbase_value=0, script=CScript([OP_TRUE]), solve=True, *, version=1):
if self.tip is None:
base_block_hash = self.genesis_hash
block_time = int(time.time()) + 1
@@ -1293,11 +1305,11 @@ class FullBlockTest(BitcoinTestFramework):
coinbase.vout[0].nValue += additional_coinbase_value
coinbase.rehash()
if spend is None:
- block = create_block(base_block_hash, coinbase, block_time)
+ block = create_block(base_block_hash, coinbase, block_time, version=version)
else:
coinbase.vout[0].nValue += spend.vout[0].nValue - 1 # all but one satoshi to fees
coinbase.rehash()
- block = create_block(base_block_hash, coinbase, block_time)
+ block = create_block(base_block_hash, coinbase, block_time, version=version)
tx = self.create_tx(spend, 0, 1, script) # spend 1 satoshi
self.sign_tx(tx, spend)
self.add_transactions_to_block(block, [tx])
diff --git a/test/functional/feature_config_args.py b/test/functional/feature_config_args.py
index d87eabaa6d..4b3f6603a2 100755
--- a/test/functional/feature_config_args.py
+++ b/test/functional/feature_config_args.py
@@ -34,6 +34,14 @@ class ConfArgsTest(BitcoinTestFramework):
self.nodes[0].assert_start_raises_init_error(expected_msg='Error reading configuration file: parse error on line 3, using # in rpcpassword can be ambiguous and should be avoided')
with open(inc_conf_file_path, 'w', encoding='utf-8') as conf:
+ conf.write('server=1\nrpcuser=someuser\nmain.rpcpassword=some#pass')
+ self.nodes[0].assert_start_raises_init_error(expected_msg='Error reading configuration file: parse error on line 3, using # in rpcpassword can be ambiguous and should be avoided')
+
+ with open(inc_conf_file_path, 'w', encoding='utf-8') as conf:
+ conf.write('server=1\nrpcuser=someuser\n[main]\nrpcpassword=some#pass')
+ self.nodes[0].assert_start_raises_init_error(expected_msg='Error reading configuration file: parse error on line 4, using # in rpcpassword can be ambiguous and should be avoided')
+
+ with open(inc_conf_file_path, 'w', encoding='utf-8') as conf:
conf.write('testnot.datadir=1\n[testnet]\n')
self.restart_node(0)
self.nodes[0].stop_node(expected_stderr='Warning: Section [testnet] is not recognized.' + os.linesep + 'Warning: Section [testnot] is not recognized.')
diff --git a/test/functional/test_framework/blocktools.py b/test/functional/test_framework/blocktools.py
index 7679ea5398..6b47cae4c3 100644
--- a/test/functional/test_framework/blocktools.py
+++ b/test/functional/test_framework/blocktools.py
@@ -46,9 +46,10 @@ MAX_BLOCK_SIGOPS = 20000
# From BIP141
WITNESS_COMMITMENT_HEADER = b"\xaa\x21\xa9\xed"
-def create_block(hashprev, coinbase, ntime=None):
+def create_block(hashprev, coinbase, ntime=None, *, version=1):
"""Create a block (with regtest difficulty)."""
block = CBlock()
+ block.nVersion = version
if ntime is None:
import time
block.nTime = int(time.time() + 600)
diff --git a/test/lint/lint-locale-dependence.sh b/test/lint/lint-locale-dependence.sh
index 44170a6b5a..1534d5ef68 100755
--- a/test/lint/lint-locale-dependence.sh
+++ b/test/lint/lint-locale-dependence.sh
@@ -4,30 +4,21 @@ export LC_ALL=C
KNOWN_VIOLATIONS=(
"src/bitcoin-tx.cpp.*stoul"
"src/bitcoin-tx.cpp.*trim_right"
- "src/bitcoin-tx.cpp:.*atoi"
- "src/core_read.cpp.*is_digit"
"src/dbwrapper.cpp.*stoul"
"src/dbwrapper.cpp:.*vsnprintf"
"src/httprpc.cpp.*trim"
"src/init.cpp:.*atoi"
"src/qt/rpcconsole.cpp:.*atoi"
- "src/qt/rpcconsole.cpp:.*isdigit"
"src/rest.cpp:.*strtol"
"src/test/dbwrapper_tests.cpp:.*snprintf"
- "src/test/getarg_tests.cpp.*split"
"src/torcontrol.cpp:.*atoi"
"src/torcontrol.cpp:.*strtol"
- "src/uint256.cpp:.*tolower"
- "src/util/system.cpp:.*atoi"
- "src/util/system.cpp:.*fprintf"
- "src/util/system.cpp:.*tolower"
- "src/util/moneystr.cpp:.*isdigit"
"src/util/strencodings.cpp:.*atoi"
"src/util/strencodings.cpp:.*strtol"
- "src/util/strencodings.cpp:.*strtoll"
"src/util/strencodings.cpp:.*strtoul"
- "src/util/strencodings.cpp:.*strtoull"
"src/util/strencodings.h:.*atoi"
+ "src/util/system.cpp:.*atoi"
+ "src/util/system.cpp:.*fprintf"
)
REGEXP_IGNORE_EXTERNAL_DEPENDENCIES="^src/(crypto/ctaes/|leveldb/|secp256k1/|tinyformat.h|univalue/)"