aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.qt.include12
-rw-r--r--src/Makefile.qttest.include3
-rw-r--r--src/addrman.h30
-rw-r--r--src/bench/mempool_eviction.cpp4
-rw-r--r--src/chain.h12
-rw-r--r--src/chainparams.cpp12
-rw-r--r--src/chainparams.h6
-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.cpp22
-rw-r--r--src/interfaces/node.cpp2
-rw-r--r--src/interfaces/node.h6
-rw-r--r--src/interfaces/wallet.cpp4
-rw-r--r--src/interfaces/wallet.h3
-rw-r--r--src/merkleblock.cpp4
-rw-r--r--src/net.cpp97
-rw-r--r--src/net.h122
-rw-r--r--src/protocol.h1
-rw-r--r--src/qt/addressbookpage.cpp2
-rw-r--r--src/qt/addressbookpage.h2
-rw-r--r--src/qt/addresstablemodel.cpp6
-rw-r--r--src/qt/addresstablemodel.h2
-rw-r--r--src/qt/askpassphrasedialog.cpp2
-rw-r--r--src/qt/bantablemodel.cpp11
-rw-r--r--src/qt/bantablemodel.h2
-rw-r--r--src/qt/bitcoin.cpp182
-rw-r--r--src/qt/bitcoin.h127
-rw-r--r--src/qt/bitcoinamountfield.cpp8
-rw-r--r--src/qt/bitcoinamountfield.h4
-rw-r--r--src/qt/bitcoingui.cpp97
-rw-r--r--src/qt/bitcoingui.h25
-rw-r--r--src/qt/clientmodel.cpp6
-rw-r--r--src/qt/clientmodel.h2
-rw-r--r--src/qt/coincontroldialog.cpp2
-rw-r--r--src/qt/coincontroldialog.h2
-rw-r--r--src/qt/coincontroltreewidget.h2
-rw-r--r--src/qt/csvmodelwriter.cpp2
-rw-r--r--src/qt/csvmodelwriter.h2
-rw-r--r--src/qt/editaddressdialog.cpp4
-rw-r--r--src/qt/editaddressdialog.h2
-rw-r--r--src/qt/forms/debugwindow.ui1147
-rw-r--r--src/qt/guiutil.h2
-rw-r--r--src/qt/intro.cpp31
-rw-r--r--src/qt/intro.h5
-rw-r--r--src/qt/main.cpp17
-rw-r--r--src/qt/networkstyle.cpp2
-rw-r--r--src/qt/optionsdialog.cpp4
-rw-r--r--src/qt/optionsmodel.h2
-rw-r--r--src/qt/overviewpage.cpp4
-rw-r--r--src/qt/overviewpage.h2
-rw-r--r--src/qt/paymentserver.cpp8
-rw-r--r--src/qt/peertablemodel.cpp13
-rw-r--r--src/qt/peertablemodel.h2
-rw-r--r--src/qt/platformstyle.cpp2
-rw-r--r--src/qt/qvalidatedlineedit.cpp2
-rw-r--r--src/qt/qvaluecombobox.h2
-rw-r--r--src/qt/receivecoinsdialog.cpp4
-rw-r--r--src/qt/receivecoinsdialog.h2
-rw-r--r--src/qt/receiverequestdialog.cpp4
-rw-r--r--src/qt/receiverequestdialog.h4
-rw-r--r--src/qt/recentrequeststablemodel.cpp2
-rw-r--r--src/qt/recentrequeststablemodel.h2
-rw-r--r--src/qt/rpcconsole.cpp10
-rw-r--r--src/qt/sendcoinsdialog.cpp10
-rw-r--r--src/qt/sendcoinsdialog.h4
-rw-r--r--src/qt/sendcoinsentry.cpp4
-rw-r--r--src/qt/sendcoinsentry.h2
-rw-r--r--src/qt/signverifymessagedialog.cpp2
-rw-r--r--src/qt/splashscreen.cpp2
-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/trafficgraphwidget.cpp4
-rw-r--r--src/qt/trafficgraphwidget.h2
-rw-r--r--src/qt/transactiondescdialog.h2
-rw-r--r--src/qt/transactionfilterproxy.h2
-rw-r--r--src/qt/transactionrecord.cpp11
-rw-r--r--src/qt/transactionrecord.h2
-rw-r--r--src/qt/transactiontablemodel.cpp7
-rw-r--r--src/qt/transactiontablemodel.h2
-rw-r--r--src/qt/transactionview.cpp4
-rw-r--r--src/qt/transactionview.h2
-rw-r--r--src/qt/utilitydialog.h2
-rw-r--r--src/qt/walletframe.cpp8
-rw-r--r--src/qt/walletframe.h5
-rw-r--r--src/qt/walletmodel.cpp14
-rw-r--r--src/qt/walletmodel.h4
-rw-r--r--src/qt/walletview.cpp4
-rw-r--r--src/rpc/blockchain.cpp15
-rw-r--r--src/rpc/net.cpp16
-rw-r--r--src/rpc/server.cpp59
-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/sync.h3
-rw-r--r--src/test/addrman_tests.cpp4
-rw-r--r--src/test/allocator_tests.cpp6
-rw-r--r--src/test/blockencodings_tests.cpp6
-rw-r--r--src/test/getarg_tests.cpp3
-rw-r--r--src/test/mempool_tests.cpp10
-rw-r--r--src/test/merkle_tests.cpp4
-rw-r--r--src/test/miner_tests.cpp2
-rw-r--r--src/test/net_tests.cpp76
-rw-r--r--src/test/policyestimator_tests.cpp2
-rw-r--r--src/test/txindex_tests.cpp7
-rw-r--r--src/test/util_tests.cpp4
-rw-r--r--src/torcontrol.cpp2
-rw-r--r--src/txmempool.h46
-rw-r--r--src/uint256.cpp2
-rw-r--r--src/util/moneystr.cpp6
-rw-r--r--src/util/strencodings.cpp2
-rw-r--r--src/util/strencodings.h8
-rw-r--r--src/util/system.cpp13
-rw-r--r--src/util/system.h3
-rw-r--r--src/validation.cpp16
-rw-r--r--src/wallet/db.cpp2
-rw-r--r--src/wallet/init.cpp8
-rw-r--r--src/wallet/rpcwallet.cpp19
-rw-r--r--src/wallet/test/wallet_tests.cpp4
-rw-r--r--src/wallet/wallet.cpp129
-rw-r--r--src/wallet/wallet.h17
-rw-r--r--src/wallet/walletdb.cpp20
124 files changed, 1713 insertions, 1209 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/bench/mempool_eviction.cpp b/src/bench/mempool_eviction.cpp
index 49ea6e88b5..ac8a182358 100644
--- a/src/bench/mempool_eviction.cpp
+++ b/src/bench/mempool_eviction.cpp
@@ -9,7 +9,7 @@
#include <list>
#include <vector>
-static void AddTx(const CTransactionRef& tx, const CAmount& nFee, CTxMemPool& pool) EXCLUSIVE_LOCKS_REQUIRED(pool.cs)
+static void AddTx(const CTransactionRef& tx, const CAmount& nFee, CTxMemPool& pool) EXCLUSIVE_LOCKS_REQUIRED(cs_main, pool.cs)
{
int64_t nTime = 0;
unsigned int nHeight = 1;
@@ -108,7 +108,7 @@ static void MempoolEviction(benchmark::State& state)
tx7.vout[1].nValue = 10 * COIN;
CTxMemPool pool;
- LOCK(pool.cs);
+ LOCK2(cs_main, pool.cs);
// Create transaction references outside the "hot loop"
const CTransactionRef tx1_r{MakeTransactionRef(tx1)};
const CTransactionRef tx2_r{MakeTransactionRef(tx2)};
diff --git a/src/chain.h b/src/chain.h
index 3b786664af..5a6f10b84f 100644
--- a/src/chain.h
+++ b/src/chain.h
@@ -18,7 +18,7 @@
* Maximum amount of time that a block timestamp is allowed to exceed the
* current network-adjusted time before the block will be accepted.
*/
-static const int64_t MAX_FUTURE_BLOCK_TIME = 2 * 60 * 60;
+static constexpr int64_t MAX_FUTURE_BLOCK_TIME = 2 * 60 * 60;
/**
* Timestamp window used as a grace period by code that compares external
@@ -26,7 +26,15 @@ static const int64_t MAX_FUTURE_BLOCK_TIME = 2 * 60 * 60;
* to block timestamps. This should be set at least as high as
* MAX_FUTURE_BLOCK_TIME.
*/
-static const int64_t TIMESTAMP_WINDOW = MAX_FUTURE_BLOCK_TIME;
+static constexpr int64_t TIMESTAMP_WINDOW = MAX_FUTURE_BLOCK_TIME;
+
+/**
+ * Maximum gap between node time and block time used
+ * for the "Catching up..." mode in GUI.
+ *
+ * Ref: https://github.com/bitcoin/bitcoin/pull/1026
+ */
+static constexpr int64_t MAX_BLOCK_TIME_GAP = 90 * 60;
class CBlockFileInfo
{
diff --git a/src/chainparams.cpp b/src/chainparams.cpp
index 4ce1b53880..da4832dff8 100644
--- a/src/chainparams.cpp
+++ b/src/chainparams.cpp
@@ -107,6 +107,8 @@ public:
pchMessageStart[3] = 0xd9;
nDefaultPort = 8333;
nPruneAfterHeight = 100000;
+ m_assumed_blockchain_size = 200;
+ m_assumed_chain_state_size = 3;
genesis = CreateGenesisBlock(1231006505, 2083236893, 0x1d00ffff, 1, 50 * COIN);
consensus.hashGenesisBlock = genesis.GetHash();
@@ -216,6 +218,8 @@ public:
pchMessageStart[3] = 0x07;
nDefaultPort = 18333;
nPruneAfterHeight = 1000;
+ m_assumed_blockchain_size = 20;
+ m_assumed_chain_state_size = 2;
genesis = CreateGenesisBlock(1296688602, 414098458, 0x1d00ffff, 1, 50 * COIN);
consensus.hashGenesisBlock = genesis.GetHash();
@@ -272,10 +276,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;
@@ -305,6 +309,8 @@ public:
pchMessageStart[3] = 0xda;
nDefaultPort = 18444;
nPruneAfterHeight = 1000;
+ m_assumed_blockchain_size = 0;
+ m_assumed_chain_state_size = 0;
UpdateVersionBitsParametersFromArgs(args);
diff --git a/src/chainparams.h b/src/chainparams.h
index 19818b40af..6ff3dbb7e5 100644
--- a/src/chainparams.h
+++ b/src/chainparams.h
@@ -67,6 +67,10 @@ public:
/** Policy: Filter transactions that do not match well-defined patterns */
bool RequireStandard() const { return fRequireStandard; }
uint64_t PruneAfterHeight() const { return nPruneAfterHeight; }
+ /** Minimum free space (in GB) needed for data directory */
+ uint64_t AssumedBlockchainSize() const { return m_assumed_blockchain_size; }
+ /** Minimum free space (in GB) needed for data directory when pruned; Does not include prune target*/
+ uint64_t AssumedChainStateSize() const { return m_assumed_chain_state_size; }
/** Make miner stop after a block is found. In RPC, don't return until nGenProcLimit blocks are generated */
bool MineBlocksOnDemand() const { return fMineBlocksOnDemand; }
/** Return the BIP70 network string (main, test or regtest) */
@@ -87,6 +91,8 @@ protected:
CMessageHeader::MessageStartChars pchMessageStart;
int nDefaultPort;
uint64_t nPruneAfterHeight;
+ uint64_t m_assumed_blockchain_size;
+ uint64_t m_assumed_chain_state_size;
std::vector<std::string> vSeeds;
std::vector<unsigned char> base58Prefixes[MAX_BASE58_TYPES];
std::string bech32_hrp;
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..e495a68d55 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -261,10 +261,10 @@ void Shutdown(InitInterfaces& interfaces)
LogPrintf("%s: Unable to remove pidfile: %s\n", __func__, e.what());
}
#endif
+ interfaces.chain_clients.clear();
UnregisterAllValidationInterfaces();
GetMainSignals().UnregisterBackgroundSignalScheduler();
GetMainSignals().UnregisterWithMempoolSignals(mempool);
- interfaces.chain_clients.clear();
globalVerifyHandle.reset();
ECC_Stop();
LogPrintf("%s: done\n", __func__);
@@ -930,7 +930,7 @@ bool AppInitParameterInteraction()
// also see: InitParameterInteraction()
- if (!fs::is_directory(GetBlocksDir(false))) {
+ if (!fs::is_directory(GetBlocksDir())) {
return InitError(strprintf(_("Specified blocks directory \"%s\" does not exist."), gArgs.GetArg("-blocksdir", "").c_str()));
}
@@ -1321,7 +1321,7 @@ bool AppInitMain(InitInterfaces& interfaces)
for (int n = 0; n < NET_MAX; n++) {
enum Network net = (enum Network)n;
if (!nets.count(net))
- SetLimited(net);
+ SetReachable(net, false);
}
}
@@ -1332,7 +1332,7 @@ bool AppInitMain(InitInterfaces& interfaces)
// -proxy sets a proxy for all outgoing network traffic
// -noproxy (or -proxy=0) as well as the empty string can be used to not set a proxy, this is the default
std::string proxyArg = gArgs.GetArg("-proxy", "");
- SetLimited(NET_ONION);
+ SetReachable(NET_ONION, false);
if (proxyArg != "" && proxyArg != "0") {
CService proxyAddr;
if (!Lookup(proxyArg.c_str(), proxyAddr, 9050, fNameLookup)) {
@@ -1347,7 +1347,7 @@ bool AppInitMain(InitInterfaces& interfaces)
SetProxy(NET_IPV6, addrProxy);
SetProxy(NET_ONION, addrProxy);
SetNameProxy(addrProxy);
- SetLimited(NET_ONION, false); // by default, -proxy sets onion as reachable, unless -noonion later
+ SetReachable(NET_ONION, true); // by default, -proxy sets onion as reachable, unless -noonion later
}
// -onion can be used to set only a proxy for .onion, or override normal proxy for .onion addresses
@@ -1356,7 +1356,7 @@ bool AppInitMain(InitInterfaces& interfaces)
std::string onionArg = gArgs.GetArg("-onion", "");
if (onionArg != "") {
if (onionArg == "0") { // Handle -noonion/-onion=0
- SetLimited(NET_ONION); // set onions as unreachable
+ SetReachable(NET_ONION, false);
} else {
CService onionProxy;
if (!Lookup(onionArg.c_str(), onionProxy, 9050, fNameLookup)) {
@@ -1366,7 +1366,7 @@ bool AppInitMain(InitInterfaces& interfaces)
if (!addrOnion.IsValid())
return InitError(strprintf(_("Invalid -onion address or hostname: '%s'"), onionArg));
SetProxy(NET_ONION, addrOnion);
- SetLimited(NET_ONION, false);
+ SetReachable(NET_ONION, true);
}
}
@@ -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/interfaces/node.cpp b/src/interfaces/node.cpp
index bd7e414ff3..acba05fd5e 100644
--- a/src/interfaces/node.cpp
+++ b/src/interfaces/node.cpp
@@ -60,6 +60,8 @@ public:
bool softSetArg(const std::string& arg, const std::string& value) override { return gArgs.SoftSetArg(arg, value); }
bool softSetBoolArg(const std::string& arg, bool value) override { return gArgs.SoftSetBoolArg(arg, value); }
void selectParams(const std::string& network) override { SelectParams(network); }
+ uint64_t getAssumedBlockchainSize() override { return Params().AssumedBlockchainSize(); }
+ uint64_t getAssumedChainStateSize() override { return Params().AssumedChainStateSize(); }
std::string getNetwork() override { return Params().NetworkIDString(); }
void initLogging() override { InitLogging(); }
void initParameterInteraction() override { InitParameterInteraction(); }
diff --git a/src/interfaces/node.h b/src/interfaces/node.h
index 1f8bbbff7a..7fa5958c51 100644
--- a/src/interfaces/node.h
+++ b/src/interfaces/node.h
@@ -52,6 +52,12 @@ public:
//! Choose network parameters.
virtual void selectParams(const std::string& network) = 0;
+ //! Get the (assumed) blockchain size.
+ virtual uint64_t getAssumedBlockchainSize() = 0;
+
+ //! Get the (assumed) chain state size.
+ virtual uint64_t getAssumedChainStateSize() = 0;
+
//! Get network name.
virtual std::string getNetwork() = 0;
diff --git a/src/interfaces/wallet.cpp b/src/interfaces/wallet.cpp
index 672a557d41..8db34ed759 100644
--- a/src/interfaces/wallet.cpp
+++ b/src/interfaces/wallet.cpp
@@ -318,7 +318,8 @@ public:
}
bool tryGetTxStatus(const uint256& txid,
interfaces::WalletTxStatus& tx_status,
- int& num_blocks) override
+ int& num_blocks,
+ int64_t& block_time) override
{
auto locked_chain = m_wallet.chain().lock(true /* try_lock */);
if (!locked_chain) {
@@ -333,6 +334,7 @@ public:
return false;
}
num_blocks = ::chainActive.Height();
+ block_time = ::chainActive.Tip()->GetBlockTime();
tx_status = MakeWalletTxStatus(*locked_chain, mi->second);
return true;
}
diff --git a/src/interfaces/wallet.h b/src/interfaces/wallet.h
index c79b9afce3..da60684a4f 100644
--- a/src/interfaces/wallet.h
+++ b/src/interfaces/wallet.h
@@ -178,7 +178,8 @@ public:
//! Try to get updated status for a particular transaction, if possible without blocking.
virtual bool tryGetTxStatus(const uint256& txid,
WalletTxStatus& tx_status,
- int& num_blocks) = 0;
+ int& num_blocks,
+ int64_t& block_time) = 0;
//! Get transaction details.
virtual WalletTx getWalletTxDetails(const uint256& txid,
diff --git a/src/merkleblock.cpp b/src/merkleblock.cpp
index 0c37bab1f8..a54268d655 100644
--- a/src/merkleblock.cpp
+++ b/src/merkleblock.cpp
@@ -53,7 +53,7 @@ uint256 CPartialMerkleTree::CalcHash(int height, unsigned int pos, const std::ve
else
right = left;
// combine subhashes
- return Hash(BEGIN(left), END(left), BEGIN(right), END(right));
+ return Hash(left.begin(), left.end(), right.begin(), right.end());
}
}
@@ -109,7 +109,7 @@ uint256 CPartialMerkleTree::TraverseAndExtract(int height, unsigned int pos, uns
right = left;
}
// and combine them before returning
- return Hash(BEGIN(left), END(left), BEGIN(right), END(right));
+ return Hash(left.begin(), left.end(), right.begin(), right.end());
}
}
diff --git a/src/net.cpp b/src/net.cpp
index a288c6e81e..98bd518ecc 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2018 The Bitcoin Core developers
+// Copyright (c) 2009-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -80,7 +80,7 @@ enum BindFlags {
// The sleep time needs to be small to avoid new sockets stalling
static const uint64_t SELECT_TIMEOUT_MILLISECONDS = 50;
-const static std::string NET_MESSAGE_COMMAND_OTHER = "*other*";
+const std::string NET_MESSAGE_COMMAND_OTHER = "*other*";
static const uint64_t RANDOMIZER_ID_NETGROUP = 0x6c0edd8036ef4036ULL; // SHA256("netgroup")[0:8]
static const uint64_t RANDOMIZER_ID_LOCALHOSTNONCE = 0xd93e69e2bbfa5735ULL; // SHA256("localhostnonce")[0:8]
@@ -183,7 +183,7 @@ bool IsPeerAddrLocalGood(CNode *pnode)
{
CService addrLocal = pnode->GetAddrLocal();
return fDiscover && pnode->addr.IsRoutable() && addrLocal.IsRoutable() &&
- !IsLimited(addrLocal.GetNetwork());
+ IsReachable(addrLocal.GetNetwork());
}
// pushes our own address to a peer
@@ -222,7 +222,7 @@ bool AddLocal(const CService& addr, int nScore)
if (!fDiscover && nScore < LOCAL_MANUAL)
return false;
- if (IsLimited(addr))
+ if (!IsReachable(addr))
return false;
LogPrintf("AddLocal(%s,%i)\n", addr.ToString(), nScore);
@@ -252,24 +252,23 @@ void RemoveLocal(const CService& addr)
mapLocalHost.erase(addr);
}
-/** Make a particular network entirely off-limits (no automatic connects to it) */
-void SetLimited(enum Network net, bool fLimited)
+void SetReachable(enum Network net, bool reachable)
{
if (net == NET_UNROUTABLE || net == NET_INTERNAL)
return;
LOCK(cs_mapLocalHost);
- vfLimited[net] = fLimited;
+ vfLimited[net] = !reachable;
}
-bool IsLimited(enum Network net)
+bool IsReachable(enum Network net)
{
LOCK(cs_mapLocalHost);
- return vfLimited[net];
+ return !vfLimited[net];
}
-bool IsLimited(const CNetAddr &addr)
+bool IsReachable(const CNetAddr &addr)
{
- return IsLimited(addr.GetNetwork());
+ return IsReachable(addr.GetNetwork());
}
/** vote for a local address */
@@ -292,21 +291,6 @@ bool IsLocal(const CService& addr)
return mapLocalHost.count(addr) > 0;
}
-/** check whether a given network is one we can probably connect to */
-bool IsReachable(enum Network net)
-{
- LOCK(cs_mapLocalHost);
- return !vfLimited[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);
-}
-
-
CNode* CConnman::FindNode(const CNetAddr& ip)
{
LOCK(cs_vNodes);
@@ -787,7 +771,6 @@ bool CNode::ReceiveMsgBytes(const char *pch, unsigned int nBytes, bool& complete
nBytes -= handled;
if (msg.complete()) {
-
//store received bytes per message command
//to prevent a memory DOS, only allow valid commands
mapMsgCmdSize::iterator i = mapRecvBytesPerMsgCmd.find(msg.hdr.pchCommand);
@@ -1968,7 +1951,7 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
if (nTries > 100)
break;
- if (IsLimited(addr))
+ if (!IsReachable(addr))
continue;
// only consider very recently tried nodes after 30 failed attempts
@@ -2317,14 +2300,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;
@@ -2338,7 +2313,7 @@ NodeId CConnman::GetNewNodeId()
bool CConnman::Bind(const CService &addr, unsigned int flags) {
- if (!(flags & BF_EXPLICIT) && IsLimited(addr))
+ if (!(flags & BF_EXPLICIT) && !IsReachable(addr))
return false;
std::string strError;
if (!BindListenPort(addr, strError, (flags & BF_WHITELIST) != 0)) {
@@ -2805,8 +2780,8 @@ int CConnman::GetBestHeight() const
unsigned int CConnman::GetReceiveFloodSize() const { return nReceiveFloodSize; }
-CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn, SOCKET hSocketIn, const CAddress& addrIn, uint64_t nKeyedNetGroupIn, uint64_t nLocalHostNonceIn, const CAddress &addrBindIn, const std::string& addrNameIn, bool fInboundIn) :
- nTimeConnected(GetSystemTimeInSeconds()),
+CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn, SOCKET hSocketIn, const CAddress& addrIn, uint64_t nKeyedNetGroupIn, uint64_t nLocalHostNonceIn, const CAddress& addrBindIn, const std::string& addrNameIn, bool fInboundIn)
+ : nTimeConnected(GetSystemTimeInSeconds()),
addr(addrIn),
addrBind(addrBindIn),
fInbound(fInboundIn),
@@ -2816,56 +2791,14 @@ CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn
id(idIn),
nLocalHostNonce(nLocalHostNonceIn),
nLocalServices(nLocalServicesIn),
- nMyStartingHeight(nMyStartingHeightIn),
- nSendVersion(0)
+ nMyStartingHeight(nMyStartingHeightIn)
{
- nServices = NODE_NONE;
hSocket = hSocketIn;
- nRecvVersion = INIT_PROTO_VERSION;
- nLastSend = 0;
- nLastRecv = 0;
- nSendBytes = 0;
- nRecvBytes = 0;
- nTimeOffset = 0;
addrName = addrNameIn == "" ? addr.ToStringIPPort() : addrNameIn;
- nVersion = 0;
strSubVer = "";
- fWhitelisted = false;
- fOneShot = false;
- m_manual_connection = false;
- fClient = false; // set by version message
- m_limited_node = false; // set by version message
- fFeeler = false;
- fSuccessfullyConnected = false;
- fDisconnect = false;
- nRefCount = 0;
- nSendSize = 0;
- nSendOffset = 0;
hashContinue = uint256();
- nStartingHeight = -1;
filterInventoryKnown.reset();
- fSendMempool = false;
- fGetAddr = false;
- nNextLocalAddrSend = 0;
- nNextAddrSend = 0;
- nNextInvSend = 0;
- fRelayTxes = false;
- fSentAddr = false;
pfilter = MakeUnique<CBloomFilter>();
- timeLastMempoolReq = 0;
- nLastBlockTime = 0;
- nLastTXTime = 0;
- nPingNonceSent = 0;
- nPingUsecStart = 0;
- nPingUsecTime = 0;
- fPingQueued = false;
- nMinPingUsecTime = std::numeric_limits<int64_t>::max();
- minFeeFilter = 0;
- lastSentFeeFilter = 0;
- nextSendTimeFeeFilter = 0;
- fPauseRecv = false;
- fPauseSend = false;
- nProcessQueueSize = 0;
for (const std::string &msg : getAllNetMessageTypes())
mapRecvBytesPerMsgCmd[msg] = 0;
diff --git a/src/net.h b/src/net.h
index 915a8e5b35..430e148afa 100644
--- a/src/net.h
+++ b/src/net.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2018 The Bitcoin Core developers
+// Copyright (c) 2009-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -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;
@@ -520,17 +520,23 @@ enum
bool IsPeerAddrLocalGood(CNode *pnode);
void AdvertiseLocal(CNode *pnode);
-void SetLimited(enum Network net, bool fLimited = true);
-bool IsLimited(enum Network net);
-bool IsLimited(const CNetAddr& addr);
+
+/**
+ * Mark a network as reachable or unreachable (no automatic connects to it)
+ * @note Networks are reachable by default
+ */
+void SetReachable(enum Network net, bool reachable);
+/** @returns true if the network is reachable, false otherwise */
+bool IsReachable(enum Network net);
+/** @returns true if the address is in a reachable network, false otherwise */
+bool IsReachable(const CNetAddr& addr);
+
bool AddLocal(const CService& addr, int nScore = LOCAL_NONE);
bool AddLocal(const CNetAddr& addr, int nScore = LOCAL_NONE);
void RemoveLocal(const CService& addr);
bool SeenLocal(const CService& addr);
bool IsLocal(const CService& addr);
bool GetLocal(CService &addr, const CNetAddr *paddrPeer = nullptr);
-bool IsReachable(enum Network net);
-bool IsReachable(const CNetAddr &addr);
CAddress GetLocalAddress(const CNetAddr *paddrPeer, ServiceFlags nLocalServices);
@@ -550,6 +556,8 @@ struct LocalServiceInfo {
extern CCriticalSection cs_mapLocalHost;
extern std::map<CNetAddr, LocalServiceInfo> mapLocalHost GUARDED_BY(cs_mapLocalHost);
+
+extern const std::string NET_MESSAGE_COMMAND_OTHER;
typedef std::map<std::string, uint64_t> mapMsgCmdSize; //command, total bytes
class CNodeStats
@@ -638,11 +646,11 @@ class CNode
friend class CConnman;
public:
// socket
- std::atomic<ServiceFlags> nServices;
+ std::atomic<ServiceFlags> nServices{NODE_NONE};
SOCKET hSocket GUARDED_BY(cs_hSocket);
- size_t nSendSize; // total size of all vSendMsg entries
- size_t nSendOffset; // offset inside the first vSendMsg already sent
- uint64_t nSendBytes GUARDED_BY(cs_vSend);
+ size_t nSendSize{0}; // total size of all vSendMsg entries
+ size_t nSendOffset{0}; // offset inside the first vSendMsg already sent
+ uint64_t nSendBytes GUARDED_BY(cs_vSend){0};
std::deque<std::vector<unsigned char>> vSendMsg GUARDED_BY(cs_vSend);
CCriticalSection cs_vSend;
CCriticalSection cs_hSocket;
@@ -650,68 +658,68 @@ public:
CCriticalSection cs_vProcessMsg;
std::list<CNetMessage> vProcessMsg GUARDED_BY(cs_vProcessMsg);
- size_t nProcessQueueSize;
+ size_t nProcessQueueSize{0};
CCriticalSection cs_sendProcessing;
std::deque<CInv> vRecvGetData;
- uint64_t nRecvBytes GUARDED_BY(cs_vRecv);
- std::atomic<int> nRecvVersion;
+ uint64_t nRecvBytes GUARDED_BY(cs_vRecv){0};
+ std::atomic<int> nRecvVersion{INIT_PROTO_VERSION};
- std::atomic<int64_t> nLastSend;
- std::atomic<int64_t> nLastRecv;
+ std::atomic<int64_t> nLastSend{0};
+ std::atomic<int64_t> nLastRecv{0};
const int64_t nTimeConnected;
- std::atomic<int64_t> nTimeOffset;
+ std::atomic<int64_t> nTimeOffset{0};
// Address of this peer
const CAddress addr;
// Bind address of our side of the connection
const CAddress addrBind;
- std::atomic<int> nVersion;
+ std::atomic<int> nVersion{0};
// strSubVer is whatever byte array we read from the wire. However, this field is intended
// to be printed out, displayed to humans in various forms and so on. So we sanitize it and
// store the sanitized version in cleanSubVer. The original should be used when dealing with
// the network or wire types and the cleaned string used when displayed or logged.
std::string strSubVer GUARDED_BY(cs_SubVer), cleanSubVer GUARDED_BY(cs_SubVer);
CCriticalSection cs_SubVer; // used for both cleanSubVer and strSubVer
- bool fWhitelisted; // This peer can bypass DoS banning.
- bool fFeeler; // If true this node is being used as a short lived feeler.
- bool fOneShot;
- bool m_manual_connection;
- bool fClient;
- bool m_limited_node; //after BIP159
+ bool fWhitelisted{false}; // This peer can bypass DoS banning.
+ bool fFeeler{false}; // If true this node is being used as a short lived feeler.
+ bool fOneShot{false};
+ bool m_manual_connection{false};
+ bool fClient{false}; // set by version message
+ bool m_limited_node{false}; //after BIP159, set by version message
const bool fInbound;
- std::atomic_bool fSuccessfullyConnected;
- std::atomic_bool fDisconnect;
+ std::atomic_bool fSuccessfullyConnected{false};
+ std::atomic_bool fDisconnect{false};
// We use fRelayTxes for two purposes -
// a) it allows us to not relay tx invs before receiving the peer's version message
// b) the peer may tell us in its version message that we should not relay tx invs
// unless it loads a bloom filter.
- bool fRelayTxes GUARDED_BY(cs_filter);
- bool fSentAddr;
+ bool fRelayTxes GUARDED_BY(cs_filter){false};
+ bool fSentAddr{false};
CSemaphoreGrant grantOutbound;
mutable CCriticalSection cs_filter;
std::unique_ptr<CBloomFilter> pfilter PT_GUARDED_BY(cs_filter);
- std::atomic<int> nRefCount;
+ std::atomic<int> nRefCount{0};
const uint64_t nKeyedNetGroup;
- std::atomic_bool fPauseRecv;
- std::atomic_bool fPauseSend;
-protected:
+ std::atomic_bool fPauseRecv{false};
+ std::atomic_bool fPauseSend{false};
+protected:
mapMsgCmdSize mapSendBytesPerMsgCmd;
mapMsgCmdSize mapRecvBytesPerMsgCmd GUARDED_BY(cs_vRecv);
public:
uint256 hashContinue;
- std::atomic<int> nStartingHeight;
+ std::atomic<int> nStartingHeight{-1};
// flood relay
std::vector<CAddress> vAddrToSend;
CRollingBloomFilter addrKnown;
- bool fGetAddr;
+ bool fGetAddr{false};
std::set<uint256> setKnown;
- int64_t nNextAddrSend GUARDED_BY(cs_sendProcessing);
- int64_t nNextLocalAddrSend GUARDED_BY(cs_sendProcessing);
+ int64_t nNextAddrSend GUARDED_BY(cs_sendProcessing){0};
+ int64_t nNextLocalAddrSend GUARDED_BY(cs_sendProcessing){0};
// inventory based relay
CRollingBloomFilter filterInventoryKnown GUARDED_BY(cs_inventory);
@@ -725,35 +733,35 @@ public:
CCriticalSection cs_inventory;
std::set<uint256> setAskFor;
std::multimap<int64_t, CInv> mapAskFor;
- int64_t nNextInvSend;
+ int64_t nNextInvSend{0};
// Used for headers announcements - unfiltered blocks to relay
std::vector<uint256> vBlockHashesToAnnounce GUARDED_BY(cs_inventory);
// Used for BIP35 mempool sending
- bool fSendMempool GUARDED_BY(cs_inventory);
+ bool fSendMempool GUARDED_BY(cs_inventory){false};
// Last time a "MEMPOOL" request was serviced.
- std::atomic<int64_t> timeLastMempoolReq;
+ std::atomic<int64_t> timeLastMempoolReq{0};
// Block and TXN accept times
- std::atomic<int64_t> nLastBlockTime;
- std::atomic<int64_t> nLastTXTime;
+ std::atomic<int64_t> nLastBlockTime{0};
+ std::atomic<int64_t> nLastTXTime{0};
// Ping time measurement:
// The pong reply we're expecting, or 0 if no pong expected.
- std::atomic<uint64_t> nPingNonceSent;
+ std::atomic<uint64_t> nPingNonceSent{0};
// Time (in usec) the last ping was sent, or 0 if no ping was ever sent.
- std::atomic<int64_t> nPingUsecStart;
+ std::atomic<int64_t> nPingUsecStart{0};
// Last measured round-trip time.
- std::atomic<int64_t> nPingUsecTime;
+ std::atomic<int64_t> nPingUsecTime{0};
// Best measured round-trip time.
- std::atomic<int64_t> nMinPingUsecTime;
+ std::atomic<int64_t> nMinPingUsecTime{std::numeric_limits<int64_t>::max()};
// Whether a ping is requested.
- std::atomic<bool> fPingQueued;
+ std::atomic<bool> fPingQueued{false};
// Minimum fee rate with which to filter inv's to this node
- CAmount minFeeFilter GUARDED_BY(cs_feeFilter);
+ CAmount minFeeFilter GUARDED_BY(cs_feeFilter){0};
CCriticalSection cs_feeFilter;
- CAmount lastSentFeeFilter;
- int64_t nextSendTimeFeeFilter;
+ CAmount lastSentFeeFilter{0};
+ int64_t nextSendTimeFeeFilter{0};
CNode(NodeId id, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn, SOCKET hSocketIn, const CAddress &addrIn, uint64_t nKeyedNetGroupIn, uint64_t nLocalHostNonceIn, const CAddress &addrBindIn, const std::string &addrNameIn = "", bool fInboundIn = false);
~CNode();
@@ -766,7 +774,7 @@ private:
// Services offered to this peer
const ServiceFlags nLocalServices;
const int nMyStartingHeight;
- int nSendVersion;
+ int nSendVersion{0};
std::list<CNetMessage> vRecvMsg; // Used only by SocketHandler thread
mutable CCriticalSection cs_addrName;
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/addressbookpage.cpp b/src/qt/addressbookpage.cpp
index 26bdf60d4a..726dafccb0 100644
--- a/src/qt/addressbookpage.cpp
+++ b/src/qt/addressbookpage.cpp
@@ -59,7 +59,7 @@ protected:
AddressBookPage::AddressBookPage(const PlatformStyle *platformStyle, Mode _mode, Tabs _tab, QWidget *parent) :
QDialog(parent),
ui(new Ui::AddressBookPage),
- model(0),
+ model(nullptr),
mode(_mode),
tab(_tab)
{
diff --git a/src/qt/addressbookpage.h b/src/qt/addressbookpage.h
index 32ab2dfeb5..6394d26801 100644
--- a/src/qt/addressbookpage.h
+++ b/src/qt/addressbookpage.h
@@ -38,7 +38,7 @@ public:
ForEditing /**< Open address book for editing */
};
- explicit AddressBookPage(const PlatformStyle *platformStyle, Mode mode, Tabs tab, QWidget *parent = 0);
+ explicit AddressBookPage(const PlatformStyle *platformStyle, Mode mode, Tabs tab, QWidget *parent = nullptr);
~AddressBookPage();
void setModel(AddressTableModel *model);
diff --git a/src/qt/addresstablemodel.cpp b/src/qt/addresstablemodel.cpp
index 2f88e15d21..c3143e948a 100644
--- a/src/qt/addresstablemodel.cpp
+++ b/src/qt/addresstablemodel.cpp
@@ -153,7 +153,7 @@ public:
}
else
{
- return 0;
+ return nullptr;
}
}
};
@@ -300,8 +300,8 @@ QVariant AddressTableModel::headerData(int section, Qt::Orientation orientation,
Qt::ItemFlags AddressTableModel::flags(const QModelIndex &index) const
{
- if(!index.isValid())
- return 0;
+ if (!index.isValid()) return Qt::NoItemFlags;
+
AddressTableEntry *rec = static_cast<AddressTableEntry*>(index.internalPointer());
Qt::ItemFlags retval = Qt::ItemIsSelectable | Qt::ItemIsEnabled;
diff --git a/src/qt/addresstablemodel.h b/src/qt/addresstablemodel.h
index 41bed4e290..035f3e0571 100644
--- a/src/qt/addresstablemodel.h
+++ b/src/qt/addresstablemodel.h
@@ -25,7 +25,7 @@ class AddressTableModel : public QAbstractTableModel
Q_OBJECT
public:
- explicit AddressTableModel(WalletModel *parent = 0);
+ explicit AddressTableModel(WalletModel *parent = nullptr);
~AddressTableModel();
enum ColumnIndex {
diff --git a/src/qt/askpassphrasedialog.cpp b/src/qt/askpassphrasedialog.cpp
index 821c23c467..a89a15bc9d 100644
--- a/src/qt/askpassphrasedialog.cpp
+++ b/src/qt/askpassphrasedialog.cpp
@@ -22,7 +22,7 @@ AskPassphraseDialog::AskPassphraseDialog(Mode _mode, QWidget *parent) :
QDialog(parent),
ui(new Ui::AskPassphraseDialog),
mode(_mode),
- model(0),
+ model(nullptr),
fCapsLock(false)
{
ui->setupUi(this);
diff --git a/src/qt/bantablemodel.cpp b/src/qt/bantablemodel.cpp
index dcfe3dcc57..00c446cc63 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;
@@ -76,7 +76,7 @@ public:
if (idx >= 0 && idx < cachedBanlist.size())
return &cachedBanlist[idx];
- return 0;
+ return nullptr;
}
};
@@ -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();
@@ -147,8 +145,7 @@ QVariant BanTableModel::headerData(int section, Qt::Orientation orientation, int
Qt::ItemFlags BanTableModel::flags(const QModelIndex &index) const
{
- if(!index.isValid())
- return 0;
+ if (!index.isValid()) return Qt::NoItemFlags;
Qt::ItemFlags retval = Qt::ItemIsSelectable | Qt::ItemIsEnabled;
return retval;
diff --git a/src/qt/bantablemodel.h b/src/qt/bantablemodel.h
index b8505b599f..9dec5fa6a9 100644
--- a/src/qt/bantablemodel.h
+++ b/src/qt/bantablemodel.h
@@ -45,7 +45,7 @@ class BanTableModel : public QAbstractTableModel
Q_OBJECT
public:
- explicit BanTableModel(interfaces::Node& node, ClientModel *parent = 0);
+ explicit BanTableModel(interfaces::Node& node, ClientModel *parent = nullptr);
~BanTableModel();
void startAutoRefresh();
void stopAutoRefresh();
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp
index 922987b7bc..893dda1601 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)
{
@@ -277,18 +178,18 @@ void BitcoinCore::shutdown()
BitcoinApplication::BitcoinApplication(interfaces::Node& node, int &argc, char **argv):
QApplication(argc, argv),
- coreThread(0),
+ coreThread(nullptr),
m_node(node),
- optionsModel(0),
- clientModel(0),
- window(0),
- pollShutdownTimer(0),
+ optionsModel(nullptr),
+ clientModel(nullptr),
+ window(nullptr),
+ pollShutdownTimer(nullptr),
#ifdef ENABLE_WALLET
- paymentServer(0),
+ paymentServer(nullptr),
m_wallet_models(),
#endif
returnValue(0),
- platformStyle(0)
+ platformStyle(nullptr)
{
setQuitOnLastWindowClosed(false);
}
@@ -317,15 +218,15 @@ BitcoinApplication::~BitcoinApplication()
}
delete window;
- window = 0;
+ window = nullptr;
#ifdef ENABLE_WALLET
delete paymentServer;
- paymentServer = 0;
+ paymentServer = nullptr;
#endif
delete optionsModel;
- optionsModel = 0;
+ optionsModel = nullptr;
delete platformStyle;
- platformStyle = 0;
+ platformStyle = nullptr;
}
#ifdef ENABLE_WALLET
@@ -342,7 +243,7 @@ void BitcoinApplication::createOptionsModel(bool resetSettings)
void BitcoinApplication::createWindow(const NetworkStyle *networkStyle)
{
- window = new BitcoinGUI(m_node, platformStyle, networkStyle, 0);
+ window = new BitcoinGUI(m_node, platformStyle, networkStyle, nullptr);
pollShutdownTimer = new QTimer(window);
connect(pollShutdownTimer, &QTimer::timeout, window, &BitcoinGUI::detectShutdown);
@@ -350,7 +251,7 @@ void BitcoinApplication::createWindow(const NetworkStyle *networkStyle)
void BitcoinApplication::createSplashScreen(const NetworkStyle *networkStyle)
{
- SplashScreen *splash = new SplashScreen(m_node, 0, networkStyle);
+ SplashScreen *splash = new SplashScreen(m_node, nullptr, networkStyle);
// We don't hold a direct pointer to the splash screen after creation, but the splash
// screen will take care of deleting itself when finish() happens.
splash->show();
@@ -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)
@@ -406,7 +312,7 @@ void BitcoinApplication::requestShutdown()
qDebug() << __func__ << ": Requesting shutdown";
startThread();
window->hide();
- window->setClientModel(0);
+ window->setClientModel(nullptr);
pollShutdownTimer->stop();
#ifdef ENABLE_WALLET
@@ -417,7 +323,7 @@ void BitcoinApplication::requestShutdown()
m_wallet_models.clear();
#endif
delete clientModel;
- clientModel = 0;
+ clientModel = nullptr;
m_node.startShutdown();
@@ -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);
@@ -486,26 +392,28 @@ void BitcoinApplication::initializeResult(bool success)
}
#endif
- // If -min option passed, start window minimized.
- if(gArgs.GetBoolArg("-min", false))
- {
- window->showMinimized();
- }
- else
- {
+ // If -min option passed, start window minimized (iconified) or minimized to tray
+ if (!gArgs.GetBoolArg("-min", false)) {
window->show();
+ } else if (clientModel->getOptionsModel()->getMinimizeToTray() && window->hasTrayIcon()) {
+ // do nothing as the window is managed by the tray icon
+ } else {
+ window->showMinimized();
}
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 {
@@ -521,7 +429,7 @@ void BitcoinApplication::shutdownResult()
void BitcoinApplication::handleRunawayException(const QString &message)
{
- QMessageBox::critical(0, "Runaway exception", BitcoinGUI::tr("A fatal error occurred. Bitcoin can no longer continue safely and will quit.") + QString("\n\n") + message);
+ QMessageBox::critical(nullptr, "Runaway exception", BitcoinGUI::tr("A fatal error occurred. Bitcoin can no longer continue safely and will quit.") + QString("\n\n") + message);
::exit(EXIT_FAILURE);
}
@@ -548,7 +456,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;
@@ -595,7 +503,7 @@ int main(int argc, char *argv[])
SetupUIArgs();
std::string error;
if (!node->parseParameters(argc, argv, error)) {
- QMessageBox::critical(0, QObject::tr(PACKAGE_NAME),
+ QMessageBox::critical(nullptr, QObject::tr(PACKAGE_NAME),
QObject::tr("Error parsing command line arguments: %1.").arg(QString::fromStdString(error)));
return EXIT_FAILURE;
}
@@ -632,12 +540,12 @@ int main(int argc, char *argv[])
/// - Do not call GetDataDir(true) before this step finishes
if (!fs::is_directory(GetDataDir(false)))
{
- QMessageBox::critical(0, QObject::tr(PACKAGE_NAME),
- QObject::tr("Error: Specified data directory \"%1\" does not exist.").arg(QString::fromStdString(gArgs.GetArg("-datadir", ""))));
+ QMessageBox::critical(nullptr, QObject::tr(PACKAGE_NAME),
+ QObject::tr("Error: Specified data directory \"%1\" does not exist.").arg(QString::fromStdString(gArgs.GetArg("-datadir", ""))));
return EXIT_FAILURE;
}
if (!node->readConfigFiles(error)) {
- QMessageBox::critical(0, QObject::tr(PACKAGE_NAME),
+ QMessageBox::critical(nullptr, QObject::tr(PACKAGE_NAME),
QObject::tr("Error: Cannot parse configuration file: %1.").arg(QString::fromStdString(error)));
return EXIT_FAILURE;
}
@@ -652,7 +560,7 @@ int main(int argc, char *argv[])
try {
node->selectParams(gArgs.GetChainName());
} catch(std::exception &e) {
- QMessageBox::critical(0, QObject::tr(PACKAGE_NAME), QObject::tr("Error: %1").arg(e.what()));
+ QMessageBox::critical(nullptr, QObject::tr(PACKAGE_NAME), QObject::tr("Error: %1").arg(e.what()));
return EXIT_FAILURE;
}
#ifdef ENABLE_WALLET
@@ -706,7 +614,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/bitcoinamountfield.cpp b/src/qt/bitcoinamountfield.cpp
index 558fcf50ba..5854ade655 100644
--- a/src/qt/bitcoinamountfield.cpp
+++ b/src/qt/bitcoinamountfield.cpp
@@ -60,7 +60,7 @@ public:
}
}
- CAmount value(bool *valid_out=0) const
+ CAmount value(bool *valid_out=nullptr) const
{
return parse(text(), valid_out);
}
@@ -159,7 +159,7 @@ private:
* return validity.
* @note Must return 0 if !valid.
*/
- CAmount parse(const QString &text, bool *valid_out=0) const
+ CAmount parse(const QString &text, bool *valid_out=nullptr) const
{
CAmount val = 0;
bool valid = BitcoinUnits::parse(currentUnit, text, &val);
@@ -196,7 +196,7 @@ protected:
if (text().isEmpty()) // Allow step-up with empty field
return StepUpEnabled;
- StepEnabled rv = 0;
+ StepEnabled rv = StepNone;
bool valid = false;
CAmount val = value(&valid);
if (valid) {
@@ -216,7 +216,7 @@ Q_SIGNALS:
BitcoinAmountField::BitcoinAmountField(QWidget *parent) :
QWidget(parent),
- amount(0)
+ amount(nullptr)
{
amount = new AmountSpinBox(this);
amount->setLocale(QLocale::c());
diff --git a/src/qt/bitcoinamountfield.h b/src/qt/bitcoinamountfield.h
index 650481e30d..2db6b65f2c 100644
--- a/src/qt/bitcoinamountfield.h
+++ b/src/qt/bitcoinamountfield.h
@@ -26,9 +26,9 @@ class BitcoinAmountField: public QWidget
Q_PROPERTY(qint64 value READ value WRITE setValue NOTIFY valueChanged USER true)
public:
- explicit BitcoinAmountField(QWidget *parent = 0);
+ explicit BitcoinAmountField(QWidget *parent = nullptr);
- CAmount value(bool *value=0) const;
+ CAmount value(bool *value=nullptr) const;
void setValue(const CAmount& value);
/** If allow empty is set to false the field will be set to the minimum allowed value if left empty. **/
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index 0ca5b5fcdc..ddaf771fa1 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -28,6 +28,7 @@
#include <qt/macdockiconhandler.h>
#endif
+#include <chain.h>
#include <chainparams.h>
#include <interfaces/handler.h>
#include <interfaces/node.h>
@@ -35,6 +36,7 @@
#include <util/system.h>
#include <iostream>
+#include <memory>
#include <QAction>
#include <QApplication>
@@ -43,6 +45,7 @@
#include <QDesktopWidget>
#include <QDragEnterEvent>
#include <QListWidget>
+#include <QMenu>
#include <QMenuBar>
#include <QMessageBox>
#include <QMimeData>
@@ -52,6 +55,7 @@
#include <QStackedWidget>
#include <QStatusBar>
#include <QStyle>
+#include <QSystemTrayIcon>
#include <QTimer>
#include <QToolBar>
#include <QUrlQuery>
@@ -72,7 +76,9 @@ const std::string BitcoinGUI::DEFAULT_UIPLATFORM =
BitcoinGUI::BitcoinGUI(interfaces::Node& node, const PlatformStyle *_platformStyle, const NetworkStyle *networkStyle, QWidget *parent) :
QMainWindow(parent),
m_node(node),
- platformStyle(_platformStyle)
+ trayIconMenu{new QMenu()},
+ platformStyle(_platformStyle),
+ m_network_style(networkStyle)
{
QSettings settings;
if (!restoreGeometry(settings.value("MainWindowGeometry").toByteArray())) {
@@ -80,22 +86,14 @@ BitcoinGUI::BitcoinGUI(interfaces::Node& node, const PlatformStyle *_platformSty
move(QApplication::desktop()->availableGeometry().center() - frameGeometry().center());
}
- QString windowTitle = tr(PACKAGE_NAME) + " - ";
#ifdef ENABLE_WALLET
enableWallet = WalletModel::isWalletEnabled();
#endif // ENABLE_WALLET
- if(enableWallet)
- {
- windowTitle += tr("Wallet");
- } else {
- windowTitle += tr("Node");
- }
- windowTitle += " " + networkStyle->getTitleAddText();
- QApplication::setWindowIcon(networkStyle->getTrayAndWindowIcon());
- setWindowIcon(networkStyle->getTrayAndWindowIcon());
- setWindowTitle(windowTitle);
+ QApplication::setWindowIcon(m_network_style->getTrayAndWindowIcon());
+ setWindowIcon(m_network_style->getTrayAndWindowIcon());
+ updateWindowTitle();
- rpcConsole = new RPCConsole(node, _platformStyle, 0);
+ rpcConsole = new RPCConsole(node, _platformStyle, nullptr);
helpMessageDialog = new HelpMessageDialog(node, this, false);
#ifdef ENABLE_WALLET
if(enableWallet)
@@ -110,6 +108,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
@@ -127,7 +126,7 @@ BitcoinGUI::BitcoinGUI(interfaces::Node& node, const PlatformStyle *_platformSty
// Create system tray icon and notification
if (QSystemTrayIcon::isSystemTrayAvailable()) {
- createTrayIcon(networkStyle);
+ createTrayIcon();
}
notificator = new Notificator(QApplication::applicationName(), trayIcon, this);
@@ -324,6 +323,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"));
@@ -565,10 +565,9 @@ void BitcoinGUI::setClientModel(ClientModel *_clientModel)
}
#ifdef ENABLE_WALLET
-bool BitcoinGUI::addWallet(WalletModel *walletModel)
+void BitcoinGUI::addWallet(WalletModel* walletModel)
{
- if(!walletFrame)
- return false;
+ if (!walletFrame) return;
const QString display_name = walletModel->getDisplayName();
setWalletActionsEnabled(true);
m_wallet_selector->addItem(display_name, QVariant::fromValue(walletModel));
@@ -577,12 +576,12 @@ bool BitcoinGUI::addWallet(WalletModel *walletModel)
m_wallet_selector_action->setVisible(true);
}
rpcConsole->addWallet(walletModel);
- return walletFrame->addWallet(walletModel);
+ walletFrame->addWallet(walletModel);
}
-bool BitcoinGUI::removeWallet(WalletModel* walletModel)
+void BitcoinGUI::removeWallet(WalletModel* walletModel)
{
- if (!walletFrame) return false;
+ if (!walletFrame) return;
int index = m_wallet_selector->findData(QVariant::fromValue(walletModel));
m_wallet_selector->removeItem(index);
if (m_wallet_selector->count() == 0) {
@@ -592,20 +591,21 @@ bool BitcoinGUI::removeWallet(WalletModel* walletModel)
m_wallet_selector_action->setVisible(false);
}
rpcConsole->removeWallet(walletModel);
- return walletFrame->removeWallet(walletModel);
+ walletFrame->removeWallet(walletModel);
+ updateWindowTitle();
}
-bool BitcoinGUI::setCurrentWallet(WalletModel* wallet_model)
+void BitcoinGUI::setCurrentWallet(WalletModel* wallet_model)
{
- if(!walletFrame)
- return false;
- return walletFrame->setCurrentWallet(wallet_model);
+ if (!walletFrame) return;
+ walletFrame->setCurrentWallet(wallet_model);
+ updateWindowTitle();
}
-bool BitcoinGUI::setCurrentWalletBySelectorIndex(int index)
+void BitcoinGUI::setCurrentWalletBySelectorIndex(int index)
{
WalletModel* wallet_model = m_wallet_selector->itemData(index).value<WalletModel*>();
- return setCurrentWallet(wallet_model);
+ setCurrentWallet(wallet_model);
}
void BitcoinGUI::removeAllWallets()
@@ -635,14 +635,16 @@ void BitcoinGUI::setWalletActionsEnabled(bool enabled)
openAction->setEnabled(enabled);
}
-void BitcoinGUI::createTrayIcon(const NetworkStyle *networkStyle)
+void BitcoinGUI::createTrayIcon()
{
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(m_network_style->getTrayAndWindowIcon(), this);
+ QString toolTip = tr("%1 client").arg(tr(PACKAGE_NAME)) + " " + m_network_style->getTitleAddText();
+ trayIcon->setToolTip(toolTip);
+ }
#endif
}
@@ -653,16 +655,12 @@ void BitcoinGUI::createTrayIconMenu()
if (!trayIcon)
return;
- trayIconMenu = new QMenu(this);
- trayIcon->setContextMenu(trayIconMenu);
-
+ trayIcon->setContextMenu(trayIconMenu.get());
connect(trayIcon, &QSystemTrayIcon::activated, this, &BitcoinGUI::trayIconActivated);
#else
// Note: On macOS, the Dock icon is used to provide the tray's functionality.
MacDockIconHandler *dockIconHandler = MacDockIconHandler::instance();
connect(dockIconHandler, &MacDockIconHandler::dockIconClicked, this, &BitcoinGUI::macosDockIconActivated);
-
- trayIconMenu = new QMenu(this);
trayIconMenu->setAsDockMenu();
#endif
@@ -722,6 +720,7 @@ void BitcoinGUI::aboutClicked()
void BitcoinGUI::showDebugWindow()
{
GUIUtil::bringToFront(rpcConsole);
+ Q_EMIT consoleShown(rpcConsole);
}
void BitcoinGUI::showDebugWindowActivateConsole()
@@ -896,8 +895,7 @@ void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVer
tooltip = tr("Processed %n block(s) of transaction history.", "", count);
// Set icon state: spinning if catching up, tick otherwise
- if(secs < 90*60)
- {
+ if (secs < MAX_BLOCK_TIME_GAP) {
tooltip = tr("Up to date") + QString(".<br>") + tooltip;
labelBlocksIcon->setPixmap(platformStyle->SingleColorIcon(":/icons/synced").pixmap(STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE));
@@ -1191,7 +1189,7 @@ void BitcoinGUI::updateProxyIcon()
bool proxy_enabled = clientModel->getProxyInfo(ip_port);
if (proxy_enabled) {
- if (labelProxyIcon->pixmap() == 0) {
+ if (labelProxyIcon->pixmap() == nullptr) {
QString ip_port_q = QString::fromStdString(ip_port);
labelProxyIcon->setPixmap(platformStyle->SingleColorIcon(":/icons/proxy").pixmap(STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE));
labelProxyIcon->setToolTip(tr("Proxy is <b>enabled</b>: %1").arg(ip_port_q));
@@ -1203,6 +1201,21 @@ void BitcoinGUI::updateProxyIcon()
}
}
+void BitcoinGUI::updateWindowTitle()
+{
+ QString window_title = tr(PACKAGE_NAME) + " - ";
+#ifdef ENABLE_WALLET
+ if (walletFrame) {
+ WalletModel* const wallet_model = walletFrame->currentWalletModel();
+ if (wallet_model && !wallet_model->getWalletName().isEmpty()) {
+ window_title += wallet_model->getDisplayName() + " - ";
+ }
+ }
+#endif
+ window_title += m_network_style->getTitleAddText();
+ setWindowTitle(window_title);
+}
+
void BitcoinGUI::showNormalIfMinimized(bool fToggleHidden)
{
if(!clientModel)
@@ -1237,7 +1250,7 @@ void BitcoinGUI::showProgress(const QString &title, int nProgress)
progressDialog = new QProgressDialog(title, "", 0, 100);
progressDialog->setWindowModality(Qt::ApplicationModal);
progressDialog->setMinimumDuration(0);
- progressDialog->setCancelButton(0);
+ progressDialog->setCancelButton(nullptr);
progressDialog->setAutoClose(false);
progressDialog->setValue(0);
}
@@ -1299,8 +1312,8 @@ void BitcoinGUI::unsubscribeFromCoreSignals()
}
UnitDisplayStatusBarControl::UnitDisplayStatusBarControl(const PlatformStyle *platformStyle) :
- optionsModel(0),
- menu(0)
+ optionsModel(nullptr),
+ menu(nullptr)
{
createContextMenu();
setToolTip(tr("Unit to show amounts in. Click to select another unit."));
diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h
index 1324dd6625..4eb5e43f5e 100644
--- a/src/qt/bitcoingui.h
+++ b/src/qt/bitcoingui.h
@@ -16,7 +16,6 @@
#include <QLabel>
#include <QMainWindow>
#include <QMap>
-#include <QMenu>
#include <QPoint>
#include <QSystemTrayIcon>
@@ -47,6 +46,7 @@ class Node;
QT_BEGIN_NAMESPACE
class QAction;
class QComboBox;
+class QMenu;
class QProgressBar;
class QProgressDialog;
QT_END_NAMESPACE
@@ -67,7 +67,7 @@ class BitcoinGUI : public QMainWindow
public:
static const std::string DEFAULT_UIPLATFORM;
- explicit BitcoinGUI(interfaces::Node& node, const PlatformStyle *platformStyle, const NetworkStyle *networkStyle, QWidget *parent = 0);
+ explicit BitcoinGUI(interfaces::Node& node, const PlatformStyle *platformStyle, const NetworkStyle *networkStyle, QWidget *parent = nullptr);
~BitcoinGUI();
/** Set the client model.
@@ -80,12 +80,17 @@ public:
The wallet model represents a bitcoin wallet, and offers access to the list of transactions, address book and sending
functionality.
*/
- bool addWallet(WalletModel *walletModel);
- bool removeWallet(WalletModel* walletModel);
+ void addWallet(WalletModel* walletModel);
+ void removeWallet(WalletModel* walletModel);
void removeAllWallets();
#endif // ENABLE_WALLET
bool enableWallet = false;
+ /** Get the tray icon status.
+ Some systems have not "system tray" or "notification area" available.
+ */
+ bool hasTrayIcon() const { return trayIcon; }
+
protected:
void changeEvent(QEvent *e);
void closeEvent(QCloseEvent *event);
@@ -141,7 +146,7 @@ private:
QComboBox* m_wallet_selector = nullptr;
QSystemTrayIcon* trayIcon = nullptr;
- QMenu* trayIconMenu = nullptr;
+ const std::unique_ptr<QMenu> trayIconMenu;
Notificator* notificator = nullptr;
RPCConsole* rpcConsole = nullptr;
HelpMessageDialog* helpMessageDialog = nullptr;
@@ -156,6 +161,7 @@ private:
int spinnerFrame = 0;
const PlatformStyle *platformStyle;
+ const NetworkStyle* const m_network_style;
/** Create the main UI actions. */
void createActions();
@@ -164,7 +170,7 @@ private:
/** Create the toolbars */
void createToolBars();
/** Create system tray icon and notification */
- void createTrayIcon(const NetworkStyle *networkStyle);
+ void createTrayIcon();
/** Create system tray menu (or setup the dock menu) */
void createTrayIconMenu();
@@ -187,6 +193,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 */
@@ -206,8 +214,8 @@ public Q_SLOTS:
void message(const QString &title, const QString &message, unsigned int style, bool *ret = nullptr);
#ifdef ENABLE_WALLET
- bool setCurrentWallet(WalletModel* wallet_model);
- bool setCurrentWalletBySelectorIndex(int index);
+ void setCurrentWallet(WalletModel* wallet_model);
+ void setCurrentWalletBySelectorIndex(int index);
/** Set the UI status indicators based on the currently selected wallet.
*/
void updateWalletStatus();
@@ -235,6 +243,7 @@ public Q_SLOTS:
private:
/** Set the proxy-enabled icon as shown in the UI. */
void updateProxyIcon();
+ void updateWindowTitle();
public Q_SLOTS:
#ifdef ENABLE_WALLET
diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp
index 217326f818..30d9e977b8 100644
--- a/src/qt/clientmodel.cpp
+++ b/src/qt/clientmodel.cpp
@@ -35,9 +35,9 @@ ClientModel::ClientModel(interfaces::Node& node, OptionsModel *_optionsModel, QO
QObject(parent),
m_node(node),
optionsModel(_optionsModel),
- peerTableModel(0),
- banTableModel(0),
- pollTimer(0)
+ peerTableModel(nullptr),
+ banTableModel(nullptr),
+ pollTimer(nullptr)
{
cachedBestHeaderHeight = -1;
cachedBestHeaderTime = -1;
diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h
index 79e7074cca..95f4521f06 100644
--- a/src/qt/clientmodel.h
+++ b/src/qt/clientmodel.h
@@ -46,7 +46,7 @@ class ClientModel : public QObject
Q_OBJECT
public:
- explicit ClientModel(interfaces::Node& node, OptionsModel *optionsModel, QObject *parent = 0);
+ explicit ClientModel(interfaces::Node& node, OptionsModel *optionsModel, QObject *parent = nullptr);
~ClientModel();
interfaces::Node& node() const { return m_node; }
diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp
index 77f8bcf901..0d9f1adcd2 100644
--- a/src/qt/coincontroldialog.cpp
+++ b/src/qt/coincontroldialog.cpp
@@ -49,7 +49,7 @@ bool CCoinControlWidgetItem::operator<(const QTreeWidgetItem &other) const {
CoinControlDialog::CoinControlDialog(const PlatformStyle *_platformStyle, QWidget *parent) :
QDialog(parent),
ui(new Ui::CoinControlDialog),
- model(0),
+ model(nullptr),
platformStyle(_platformStyle)
{
ui->setupUi(this);
diff --git a/src/qt/coincontroldialog.h b/src/qt/coincontroldialog.h
index 8f15ae4b20..efc06a7656 100644
--- a/src/qt/coincontroldialog.h
+++ b/src/qt/coincontroldialog.h
@@ -43,7 +43,7 @@ class CoinControlDialog : public QDialog
Q_OBJECT
public:
- explicit CoinControlDialog(const PlatformStyle *platformStyle, QWidget *parent = 0);
+ explicit CoinControlDialog(const PlatformStyle *platformStyle, QWidget *parent = nullptr);
~CoinControlDialog();
void setModel(WalletModel *model);
diff --git a/src/qt/coincontroltreewidget.h b/src/qt/coincontroltreewidget.h
index 62645fcdb0..88fc8b704f 100644
--- a/src/qt/coincontroltreewidget.h
+++ b/src/qt/coincontroltreewidget.h
@@ -13,7 +13,7 @@ class CoinControlTreeWidget : public QTreeWidget
Q_OBJECT
public:
- explicit CoinControlTreeWidget(QWidget *parent = 0);
+ explicit CoinControlTreeWidget(QWidget *parent = nullptr);
protected:
virtual void keyPressEvent(QKeyEvent *event);
diff --git a/src/qt/csvmodelwriter.cpp b/src/qt/csvmodelwriter.cpp
index fe63fed52c..656afb6e87 100644
--- a/src/qt/csvmodelwriter.cpp
+++ b/src/qt/csvmodelwriter.cpp
@@ -10,7 +10,7 @@
CSVModelWriter::CSVModelWriter(const QString &_filename, QObject *parent) :
QObject(parent),
- filename(_filename), model(0)
+ filename(_filename), model(nullptr)
{
}
diff --git a/src/qt/csvmodelwriter.h b/src/qt/csvmodelwriter.h
index edea369ad1..e8611bea35 100644
--- a/src/qt/csvmodelwriter.h
+++ b/src/qt/csvmodelwriter.h
@@ -20,7 +20,7 @@ class CSVModelWriter : public QObject
Q_OBJECT
public:
- explicit CSVModelWriter(const QString &filename, QObject *parent = 0);
+ explicit CSVModelWriter(const QString &filename, QObject *parent = nullptr);
void setModel(const QAbstractItemModel *model);
void addColumn(const QString &title, int column, int role=Qt::EditRole);
diff --git a/src/qt/editaddressdialog.cpp b/src/qt/editaddressdialog.cpp
index 0b0b96b30c..4711412ac4 100644
--- a/src/qt/editaddressdialog.cpp
+++ b/src/qt/editaddressdialog.cpp
@@ -15,9 +15,9 @@
EditAddressDialog::EditAddressDialog(Mode _mode, QWidget *parent) :
QDialog(parent),
ui(new Ui::EditAddressDialog),
- mapper(0),
+ mapper(nullptr),
mode(_mode),
- model(0)
+ model(nullptr)
{
ui->setupUi(this);
diff --git a/src/qt/editaddressdialog.h b/src/qt/editaddressdialog.h
index fd88b45793..4d0e0709be 100644
--- a/src/qt/editaddressdialog.h
+++ b/src/qt/editaddressdialog.h
@@ -30,7 +30,7 @@ public:
EditSendingAddress
};
- explicit EditAddressDialog(Mode mode, QWidget *parent = 0);
+ explicit EditAddressDialog(Mode mode, QWidget *parent = nullptr);
~EditAddressDialog();
void setModel(AddressTableModel *model);
diff --git a/src/qt/forms/debugwindow.ui b/src/qt/forms/debugwindow.ui
index dca16d6f78..8e8d436ce2 100644
--- a/src/qt/forms/debugwindow.ui
+++ b/src/qt/forms/debugwindow.ui
@@ -896,570 +896,593 @@
<attribute name="title">
<string>&amp;Peers</string>
</attribute>
- <layout class="QGridLayout" name="gridLayout_2">
- <item row="0" column="0" rowspan="2">
- <layout class="QVBoxLayout" name="verticalLayout_101">
- <property name="spacing">
- <number>0</number>
- </property>
- <item>
- <widget class="QTableView" name="peerWidget">
- <property name="horizontalScrollBarPolicy">
- <enum>Qt::ScrollBarAsNeeded</enum>
- </property>
- <property name="tabKeyNavigation">
- <bool>false</bool>
- </property>
- <property name="sortingEnabled">
- <bool>true</bool>
- </property>
- <attribute name="horizontalHeaderHighlightSections">
- <bool>false</bool>
- </attribute>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="banHeading">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="minimumSize">
- <size>
- <width>300</width>
- <height>32</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>16777215</width>
- <height>32</height>
- </size>
- </property>
- <property name="font">
- <font>
- <pointsize>12</pointsize>
- </font>
- </property>
- <property name="cursor">
- <cursorShape>IBeamCursor</cursorShape>
- </property>
- <property name="text">
- <string>Banned peers</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
- </property>
- <property name="wordWrap">
- <bool>true</bool>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::NoTextInteraction</set>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QTableView" name="banlistWidget">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="horizontalScrollBarPolicy">
- <enum>Qt::ScrollBarAsNeeded</enum>
- </property>
- <property name="tabKeyNavigation">
- <bool>false</bool>
- </property>
- <property name="sortingEnabled">
- <bool>true</bool>
- </property>
- <attribute name="horizontalHeaderHighlightSections">
- <bool>false</bool>
- </attribute>
- </widget>
- </item>
- </layout>
- </item>
- <item row="0" column="1">
- <widget class="QLabel" name="peerHeading">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="minimumSize">
- <size>
- <width>300</width>
- <height>32</height>
- </size>
- </property>
- <property name="font">
- <font>
- <pointsize>10</pointsize>
- </font>
- </property>
- <property name="cursor">
- <cursorShape>IBeamCursor</cursorShape>
- </property>
- <property name="text">
- <string>Select a peer to view detailed information.</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignHCenter|Qt::AlignTop</set>
- </property>
- <property name="wordWrap">
- <bool>true</bool>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ <layout class="QVBoxLayout" name="verticalLayout_6">
+ <item>
+ <widget class="QSplitter" name="splitter">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
</property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QWidget" name="detailWidget" native="true">
- <property name="minimumSize">
- <size>
- <width>300</width>
- <height>0</height>
- </size>
+ <property name="childrenCollapsible">
+ <bool>false</bool>
</property>
- <layout class="QGridLayout" name="gridLayout_3">
- <item row="0" column="0">
- <widget class="QLabel" name="label_30">
- <property name="text">
- <string>Whitelisted</string>
- </property>
- </widget>
- </item>
- <item row="0" column="2">
- <widget class="QLabel" name="peerWhitelisted">
- <property name="cursor">
- <cursorShape>IBeamCursor</cursorShape>
- </property>
- <property name="text">
- <string>N/A</string>
- </property>
- <property name="textFormat">
- <enum>Qt::PlainText</enum>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="label_23">
- <property name="text">
- <string>Direction</string>
- </property>
- </widget>
- </item>
- <item row="1" column="2">
- <widget class="QLabel" name="peerDirection">
- <property name="cursor">
- <cursorShape>IBeamCursor</cursorShape>
- </property>
- <property name="text">
- <string>N/A</string>
- </property>
- <property name="textFormat">
- <enum>Qt::PlainText</enum>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
- </property>
- </widget>
- </item>
- <item row="2" column="0">
- <widget class="QLabel" name="label_21">
- <property name="text">
- <string>Version</string>
- </property>
- </widget>
- </item>
- <item row="2" column="2">
- <widget class="QLabel" name="peerVersion">
- <property name="cursor">
- <cursorShape>IBeamCursor</cursorShape>
- </property>
- <property name="text">
- <string>N/A</string>
- </property>
- <property name="textFormat">
- <enum>Qt::PlainText</enum>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
- </property>
- </widget>
- </item>
- <item row="3" column="0">
- <widget class="QLabel" name="label_28">
- <property name="text">
- <string>User Agent</string>
- </property>
- </widget>
- </item>
- <item row="3" column="2">
- <widget class="QLabel" name="peerSubversion">
- <property name="cursor">
- <cursorShape>IBeamCursor</cursorShape>
- </property>
- <property name="text">
- <string>N/A</string>
- </property>
- <property name="textFormat">
- <enum>Qt::PlainText</enum>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
- </property>
- </widget>
- </item>
- <item row="4" column="0">
- <widget class="QLabel" name="label_4">
- <property name="text">
- <string>Services</string>
- </property>
- </widget>
- </item>
- <item row="4" column="2">
- <widget class="QLabel" name="peerServices">
- <property name="cursor">
- <cursorShape>IBeamCursor</cursorShape>
- </property>
- <property name="text">
- <string>N/A</string>
- </property>
- <property name="textFormat">
- <enum>Qt::PlainText</enum>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
- </property>
- </widget>
- </item>
- <item row="5" column="0">
- <widget class="QLabel" name="label_29">
- <property name="text">
- <string>Starting Block</string>
- </property>
- </widget>
- </item>
- <item row="5" column="2">
- <widget class="QLabel" name="peerHeight">
- <property name="cursor">
- <cursorShape>IBeamCursor</cursorShape>
- </property>
- <property name="text">
- <string>N/A</string>
- </property>
- <property name="textFormat">
- <enum>Qt::PlainText</enum>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
- </property>
- </widget>
- </item>
- <item row="6" column="0">
- <widget class="QLabel" name="label_27">
- <property name="text">
- <string>Synced Headers</string>
- </property>
- </widget>
- </item>
- <item row="6" column="2">
- <widget class="QLabel" name="peerSyncHeight">
- <property name="cursor">
- <cursorShape>IBeamCursor</cursorShape>
- </property>
- <property name="text">
- <string>N/A</string>
- </property>
- <property name="textFormat">
- <enum>Qt::PlainText</enum>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
- </property>
- </widget>
- </item>
- <item row="7" column="0">
- <widget class="QLabel" name="label_25">
- <property name="text">
- <string>Synced Blocks</string>
- </property>
- </widget>
- </item>
- <item row="7" column="2">
- <widget class="QLabel" name="peerCommonHeight">
- <property name="cursor">
- <cursorShape>IBeamCursor</cursorShape>
- </property>
- <property name="text">
- <string>N/A</string>
- </property>
- <property name="textFormat">
- <enum>Qt::PlainText</enum>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
- </property>
- </widget>
- </item>
- <item row="8" column="0">
- <widget class="QLabel" name="label_24">
- <property name="text">
- <string>Ban Score</string>
- </property>
- </widget>
- </item>
- <item row="8" column="2">
- <widget class="QLabel" name="peerBanScore">
- <property name="cursor">
- <cursorShape>IBeamCursor</cursorShape>
- </property>
- <property name="text">
- <string>N/A</string>
- </property>
- <property name="textFormat">
- <enum>Qt::PlainText</enum>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
- </property>
- </widget>
- </item>
- <item row="9" column="0">
- <widget class="QLabel" name="label_22">
- <property name="text">
- <string>Connection Time</string>
- </property>
- </widget>
- </item>
- <item row="9" column="2">
- <widget class="QLabel" name="peerConnTime">
- <property name="cursor">
- <cursorShape>IBeamCursor</cursorShape>
- </property>
- <property name="text">
- <string>N/A</string>
- </property>
- <property name="textFormat">
- <enum>Qt::PlainText</enum>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
- </property>
- </widget>
- </item>
- <item row="10" column="0">
- <widget class="QLabel" name="label_15">
- <property name="text">
- <string>Last Send</string>
- </property>
- </widget>
- </item>
- <item row="10" column="2">
- <widget class="QLabel" name="peerLastSend">
- <property name="cursor">
- <cursorShape>IBeamCursor</cursorShape>
- </property>
- <property name="text">
- <string>N/A</string>
- </property>
- <property name="textFormat">
- <enum>Qt::PlainText</enum>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
- </property>
- </widget>
- </item>
- <item row="11" column="0">
- <widget class="QLabel" name="label_19">
- <property name="text">
- <string>Last Receive</string>
- </property>
- </widget>
- </item>
- <item row="11" column="2">
- <widget class="QLabel" name="peerLastRecv">
- <property name="cursor">
- <cursorShape>IBeamCursor</cursorShape>
- </property>
- <property name="text">
- <string>N/A</string>
- </property>
- <property name="textFormat">
- <enum>Qt::PlainText</enum>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
- </property>
- </widget>
- </item>
- <item row="12" column="0">
- <widget class="QLabel" name="label_18">
- <property name="text">
- <string>Sent</string>
- </property>
- </widget>
- </item>
- <item row="12" column="2">
- <widget class="QLabel" name="peerBytesSent">
- <property name="cursor">
- <cursorShape>IBeamCursor</cursorShape>
- </property>
- <property name="text">
- <string>N/A</string>
- </property>
- <property name="textFormat">
- <enum>Qt::PlainText</enum>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
- </property>
- </widget>
- </item>
- <item row="13" column="0">
- <widget class="QLabel" name="label_20">
- <property name="text">
- <string>Received</string>
- </property>
- </widget>
- </item>
- <item row="13" column="2">
- <widget class="QLabel" name="peerBytesRecv">
- <property name="cursor">
- <cursorShape>IBeamCursor</cursorShape>
- </property>
- <property name="text">
- <string>N/A</string>
- </property>
- <property name="textFormat">
- <enum>Qt::PlainText</enum>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
- </property>
- </widget>
- </item>
- <item row="14" column="0">
- <widget class="QLabel" name="label_26">
- <property name="text">
- <string>Ping Time</string>
- </property>
- </widget>
- </item>
- <item row="14" column="2">
- <widget class="QLabel" name="peerPingTime">
- <property name="cursor">
- <cursorShape>IBeamCursor</cursorShape>
- </property>
- <property name="text">
- <string>N/A</string>
- </property>
- <property name="textFormat">
- <enum>Qt::PlainText</enum>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
- </property>
- </widget>
- </item>
- <item row="15" column="0">
- <widget class="QLabel" name="peerPingWaitLabel">
- <property name="toolTip">
- <string>The duration of a currently outstanding ping.</string>
- </property>
- <property name="text">
- <string>Ping Wait</string>
- </property>
- </widget>
- </item>
- <item row="15" column="2">
- <widget class="QLabel" name="peerPingWait">
- <property name="cursor">
- <cursorShape>IBeamCursor</cursorShape>
- </property>
- <property name="text">
- <string>N/A</string>
- </property>
- <property name="textFormat">
- <enum>Qt::PlainText</enum>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
- </property>
- </widget>
- </item>
- <item row="16" column="0">
- <widget class="QLabel" name="peerMinPingLabel">
- <property name="text">
- <string>Min Ping</string>
- </property>
- </widget>
- </item>
- <item row="16" column="2">
- <widget class="QLabel" name="peerMinPing">
- <property name="cursor">
- <cursorShape>IBeamCursor</cursorShape>
- </property>
- <property name="text">
- <string>N/A</string>
- </property>
- <property name="textFormat">
- <enum>Qt::PlainText</enum>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
- </property>
- </widget>
- </item>
- <item row="17" column="0">
- <widget class="QLabel" name="label_timeoffset">
- <property name="text">
- <string>Time Offset</string>
- </property>
- </widget>
- </item>
- <item row="17" column="2">
- <widget class="QLabel" name="timeoffset">
- <property name="cursor">
- <cursorShape>IBeamCursor</cursorShape>
- </property>
- <property name="text">
- <string>N/A</string>
- </property>
- <property name="textFormat">
- <enum>Qt::PlainText</enum>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
- </property>
- </widget>
- </item>
- <item row="18" column="1">
- <spacer name="verticalSpacer_3">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
+ <widget class="QWidget" name="widget_1" native="true">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>400</width>
+ <height>0</height>
+ </size>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_7">
+ <item>
+ <widget class="QTableView" name="peerWidget">
+ <property name="tabKeyNavigation">
+ <bool>false</bool>
+ </property>
+ <property name="sortingEnabled">
+ <bool>true</bool>
+ </property>
+ <attribute name="horizontalHeaderHighlightSections">
+ <bool>false</bool>
+ </attribute>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="banHeading">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>32</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>16777215</width>
+ <height>32</height>
+ </size>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>12</pointsize>
+ </font>
+ </property>
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="text">
+ <string>Banned peers</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::NoTextInteraction</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QTableView" name="banlistWidget">
+ <property name="tabKeyNavigation">
+ <bool>false</bool>
+ </property>
+ <property name="sortingEnabled">
+ <bool>true</bool>
+ </property>
+ <attribute name="horizontalHeaderHighlightSections">
+ <bool>false</bool>
+ </attribute>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="widget_2" native="true">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>300</width>
+ <height>0</height>
+ </size>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_8">
+ <item>
+ <widget class="QLabel" name="peerHeading">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>32</height>
+ </size>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>10</pointsize>
+ </font>
+ </property>
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="text">
+ <string>Select a peer to view detailed information.</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignHCenter|Qt::AlignTop</set>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QScrollArea" name="scrollArea">
+ <property name="widgetResizable">
+ <bool>true</bool>
+ </property>
+ <widget class="QWidget" name="detailWidget">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>300</width>
+ <height>426</height>
+ </rect>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>300</width>
+ <height>0</height>
+ </size>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_2" columnstretch="0,1">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_30">
+ <property name="text">
+ <string>Whitelisted</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLabel" name="peerWhitelisted">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="text">
+ <string>N/A</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_23">
+ <property name="text">
+ <string>Direction</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLabel" name="peerDirection">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="text">
+ <string>N/A</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_21">
+ <property name="text">
+ <string>Version</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QLabel" name="peerVersion">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="text">
+ <string>N/A</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="label_28">
+ <property name="text">
+ <string>User Agent</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QLabel" name="peerSubversion">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="text">
+ <string>N/A</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="0">
+ <widget class="QLabel" name="label_4">
+ <property name="text">
+ <string>Services</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="1">
+ <widget class="QLabel" name="peerServices">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="text">
+ <string>N/A</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="0">
+ <widget class="QLabel" name="label_29">
+ <property name="text">
+ <string>Starting Block</string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="1">
+ <widget class="QLabel" name="peerHeight">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="text">
+ <string>N/A</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="0">
+ <widget class="QLabel" name="label_27">
+ <property name="text">
+ <string>Synced Headers</string>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="1">
+ <widget class="QLabel" name="peerSyncHeight">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="text">
+ <string>N/A</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item row="7" column="0">
+ <widget class="QLabel" name="label_25">
+ <property name="text">
+ <string>Synced Blocks</string>
+ </property>
+ </widget>
+ </item>
+ <item row="7" column="1">
+ <widget class="QLabel" name="peerCommonHeight">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="text">
+ <string>N/A</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item row="8" column="0">
+ <widget class="QLabel" name="label_24">
+ <property name="text">
+ <string>Ban Score</string>
+ </property>
+ </widget>
+ </item>
+ <item row="8" column="1">
+ <widget class="QLabel" name="peerBanScore">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="text">
+ <string>N/A</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item row="9" column="0">
+ <widget class="QLabel" name="label_22">
+ <property name="text">
+ <string>Connection Time</string>
+ </property>
+ </widget>
+ </item>
+ <item row="9" column="1">
+ <widget class="QLabel" name="peerConnTime">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="text">
+ <string>N/A</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item row="10" column="0">
+ <widget class="QLabel" name="label_15">
+ <property name="text">
+ <string>Last Send</string>
+ </property>
+ </widget>
+ </item>
+ <item row="10" column="1">
+ <widget class="QLabel" name="peerLastSend">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="text">
+ <string>N/A</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item row="11" column="0">
+ <widget class="QLabel" name="label_19">
+ <property name="text">
+ <string>Last Receive</string>
+ </property>
+ </widget>
+ </item>
+ <item row="11" column="1">
+ <widget class="QLabel" name="peerLastRecv">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="text">
+ <string>N/A</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item row="12" column="0">
+ <widget class="QLabel" name="label_18">
+ <property name="text">
+ <string>Sent</string>
+ </property>
+ </widget>
+ </item>
+ <item row="12" column="1">
+ <widget class="QLabel" name="peerBytesSent">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="text">
+ <string>N/A</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item row="13" column="0">
+ <widget class="QLabel" name="label_20">
+ <property name="text">
+ <string>Received</string>
+ </property>
+ </widget>
+ </item>
+ <item row="13" column="1">
+ <widget class="QLabel" name="peerBytesRecv">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="text">
+ <string>N/A</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item row="14" column="0">
+ <widget class="QLabel" name="label_26">
+ <property name="text">
+ <string>Ping Time</string>
+ </property>
+ </widget>
+ </item>
+ <item row="14" column="1">
+ <widget class="QLabel" name="peerPingTime">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="text">
+ <string>N/A</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item row="15" column="0">
+ <widget class="QLabel" name="peerPingWaitLabel">
+ <property name="toolTip">
+ <string>The duration of a currently outstanding ping.</string>
+ </property>
+ <property name="text">
+ <string>Ping Wait</string>
+ </property>
+ </widget>
+ </item>
+ <item row="15" column="1">
+ <widget class="QLabel" name="peerPingWait">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="text">
+ <string>N/A</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item row="16" column="0">
+ <widget class="QLabel" name="peerMinPingLabel">
+ <property name="text">
+ <string>Min Ping</string>
+ </property>
+ </widget>
+ </item>
+ <item row="16" column="1">
+ <widget class="QLabel" name="peerMinPing">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="text">
+ <string>N/A</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item row="17" column="0">
+ <widget class="QLabel" name="label_timeoffset">
+ <property name="text">
+ <string>Time Offset</string>
+ </property>
+ </widget>
+ </item>
+ <item row="17" column="1">
+ <widget class="QLabel" name="timeoffset">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="text">
+ <string>N/A</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ </layout>
+ </widget>
</widget>
</item>
</layout>
diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h
index f1d0aa48ef..ecb770d147 100644
--- a/src/qt/guiutil.h
+++ b/src/qt/guiutil.h
@@ -133,7 +133,7 @@ namespace GUIUtil
Q_OBJECT
public:
- explicit ToolTipToRichTextFilter(int size_threshold, QObject *parent = 0);
+ explicit ToolTipToRichTextFilter(int size_threshold, QObject *parent = nullptr);
protected:
bool eventFilter(QObject *obj, QEvent *evt);
diff --git a/src/qt/intro.cpp b/src/qt/intro.cpp
index 0b61b05318..fa9a50b1ed 100644
--- a/src/qt/intro.cpp
+++ b/src/qt/intro.cpp
@@ -22,10 +22,6 @@
#include <cmath>
static const uint64_t GB_BYTES = 1000000000LL;
-/* Minimum free space (in GB) needed for data directory */
-constexpr uint64_t BLOCK_CHAIN_SIZE = 220;
-/* Minimum free space (in GB) needed for data directory when pruned; Does not include prune target */
-static const uint64_t CHAIN_STATE_SIZE = 3;
/* Total required space (in GB) depending on user choice (prune, not prune) */
static uint64_t requiredSpace;
@@ -114,11 +110,13 @@ void FreespaceChecker::check()
}
-Intro::Intro(QWidget *parent) :
+Intro::Intro(QWidget *parent, uint64_t blockchain_size, uint64_t chain_state_size) :
QDialog(parent),
ui(new Ui::Intro),
- thread(0),
- signalled(false)
+ thread(nullptr),
+ signalled(false),
+ m_blockchain_size(blockchain_size),
+ m_chain_state_size(chain_state_size)
{
ui->setupUi(this);
ui->welcomeLabel->setText(ui->welcomeLabel->text().arg(tr(PACKAGE_NAME)));
@@ -126,14 +124,14 @@ Intro::Intro(QWidget *parent) :
ui->lblExplanation1->setText(ui->lblExplanation1->text()
.arg(tr(PACKAGE_NAME))
- .arg(BLOCK_CHAIN_SIZE)
+ .arg(m_blockchain_size)
.arg(2009)
.arg(tr("Bitcoin"))
);
ui->lblExplanation2->setText(ui->lblExplanation2->text().arg(tr(PACKAGE_NAME)));
uint64_t pruneTarget = std::max<int64_t>(0, gArgs.GetArg("-prune", 0));
- requiredSpace = BLOCK_CHAIN_SIZE;
+ requiredSpace = m_blockchain_size;
QString storageRequiresMsg = tr("At least %1 GB of data will be stored in this directory, and it will grow over time.");
if (pruneTarget) {
uint64_t prunedGBs = std::ceil(pruneTarget * 1024 * 1024.0 / GB_BYTES);
@@ -145,7 +143,7 @@ Intro::Intro(QWidget *parent) :
} else {
ui->lblExplanation3->setVisible(false);
}
- requiredSpace += CHAIN_STATE_SIZE;
+ requiredSpace += m_chain_state_size;
ui->sizeWarningLabel->setText(
tr("%1 will download and store a copy of the Bitcoin block chain.").arg(tr(PACKAGE_NAME)) + " " +
storageRequiresMsg.arg(requiredSpace) + " " +
@@ -201,8 +199,15 @@ bool Intro::pickDataDirectory(interfaces::Node& node)
if(!fs::exists(GUIUtil::qstringToBoostPath(dataDir)) || gArgs.GetBoolArg("-choosedatadir", DEFAULT_CHOOSE_DATADIR) || settings.value("fReset", false).toBool() || gArgs.GetBoolArg("-resetguisettings", false))
{
+ /* Use selectParams here to guarantee Params() can be used by node interface */
+ try {
+ node.selectParams(gArgs.GetChainName());
+ } catch (const std::exception&) {
+ return false;
+ }
+
/* If current default data directory does not exist, let the user choose one */
- Intro intro;
+ Intro intro(0, node.getAssumedBlockchainSize(), node.getAssumedChainStateSize());
intro.setDataDirectory(dataDir);
intro.setWindowIcon(QIcon(":icons/bitcoin"));
@@ -221,7 +226,7 @@ bool Intro::pickDataDirectory(interfaces::Node& node)
}
break;
} catch (const fs::filesystem_error&) {
- QMessageBox::critical(0, tr(PACKAGE_NAME),
+ QMessageBox::critical(nullptr, tr(PACKAGE_NAME),
tr("Error: Specified data directory \"%1\" cannot be created.").arg(dataDir));
/* fall through, back to choosing screen */
}
@@ -281,7 +286,7 @@ void Intro::on_dataDirectory_textChanged(const QString &dataDirStr)
void Intro::on_ellipsisButton_clicked()
{
- QString dir = QDir::toNativeSeparators(QFileDialog::getExistingDirectory(0, "Choose data directory", ui->dataDirectory->text()));
+ QString dir = QDir::toNativeSeparators(QFileDialog::getExistingDirectory(nullptr, "Choose data directory", ui->dataDirectory->text()));
if(!dir.isEmpty())
ui->dataDirectory->setText(dir);
}
diff --git a/src/qt/intro.h b/src/qt/intro.h
index 2b3da963e2..3da8a16114 100644
--- a/src/qt/intro.h
+++ b/src/qt/intro.h
@@ -30,7 +30,8 @@ class Intro : public QDialog
Q_OBJECT
public:
- explicit Intro(QWidget *parent = 0);
+ explicit Intro(QWidget *parent = nullptr,
+ uint64_t blockchain_size = 0, uint64_t chain_state_size = 0);
~Intro();
QString getDataDirectory();
@@ -71,6 +72,8 @@ private:
QMutex mutex;
bool signalled;
QString pathToCheck;
+ uint64_t m_blockchain_size;
+ uint64_t m_chain_state_size;
void startThread();
void checkPath(const QString &dataDir);
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/networkstyle.cpp b/src/qt/networkstyle.cpp
index da048d3211..f0c860e669 100644
--- a/src/qt/networkstyle.cpp
+++ b/src/qt/networkstyle.cpp
@@ -88,5 +88,5 @@ const NetworkStyle *NetworkStyle::instantiate(const QString &networkId)
network_styles[x].titleAddText);
}
}
- return 0;
+ return nullptr;
}
diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp
index c9871f6c66..27cec06d4b 100644
--- a/src/qt/optionsdialog.cpp
+++ b/src/qt/optionsdialog.cpp
@@ -29,8 +29,8 @@
OptionsDialog::OptionsDialog(QWidget *parent, bool enableWallet) :
QDialog(parent),
ui(new Ui::OptionsDialog),
- model(0),
- mapper(0)
+ model(nullptr),
+ mapper(nullptr)
{
ui->setupUi(this);
diff --git a/src/qt/optionsmodel.h b/src/qt/optionsmodel.h
index 2421734527..1af3a72b92 100644
--- a/src/qt/optionsmodel.h
+++ b/src/qt/optionsmodel.h
@@ -31,7 +31,7 @@ class OptionsModel : public QAbstractListModel
Q_OBJECT
public:
- explicit OptionsModel(interfaces::Node& node, QObject *parent = 0, bool resetSettings = false);
+ explicit OptionsModel(interfaces::Node& node, QObject *parent = nullptr, bool resetSettings = false);
enum OptionID {
StartAtStartup, // bool
diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp
index bec79335e7..d8e48f350a 100644
--- a/src/qt/overviewpage.cpp
+++ b/src/qt/overviewpage.cpp
@@ -113,8 +113,8 @@ public:
OverviewPage::OverviewPage(const PlatformStyle *platformStyle, QWidget *parent) :
QWidget(parent),
ui(new Ui::OverviewPage),
- clientModel(0),
- walletModel(0),
+ clientModel(nullptr),
+ walletModel(nullptr),
txdelegate(new TxViewDelegate(platformStyle, this))
{
ui->setupUi(this);
diff --git a/src/qt/overviewpage.h b/src/qt/overviewpage.h
index 75100ae6f7..00ba7ad4ce 100644
--- a/src/qt/overviewpage.h
+++ b/src/qt/overviewpage.h
@@ -30,7 +30,7 @@ class OverviewPage : public QWidget
Q_OBJECT
public:
- explicit OverviewPage(const PlatformStyle *platformStyle, QWidget *parent = 0);
+ explicit OverviewPage(const PlatformStyle *platformStyle, QWidget *parent = nullptr);
~OverviewPage();
void setClientModel(ClientModel *clientModel);
diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp
index 8148986b51..b1ec90ad36 100644
--- a/src/qt/paymentserver.cpp
+++ b/src/qt/paymentserver.cpp
@@ -194,10 +194,10 @@ bool PaymentServer::ipcSendCommandLine()
PaymentServer::PaymentServer(QObject* parent, bool startLocalServer) :
QObject(parent),
saveURIs(true),
- uriServer(0),
- optionsModel(0)
+ uriServer(nullptr),
+ optionsModel(nullptr)
#ifdef ENABLE_BIP70
- ,netManager(0)
+ ,netManager(nullptr)
#endif
{
#ifdef ENABLE_BIP70
@@ -223,7 +223,7 @@ PaymentServer::PaymentServer(QObject* parent, bool startLocalServer) :
if (!uriServer->listen(name)) {
// constructor is called early in init, so don't use "Q_EMIT message()" here
- QMessageBox::critical(0, tr("Payment request error"),
+ QMessageBox::critical(nullptr, tr("Payment request error"),
tr("Cannot start bitcoin: click-to-pay handler"));
}
else {
diff --git a/src/qt/peertablemodel.cpp b/src/qt/peertablemodel.cpp
index 8cfedca57f..496aeebf7d 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 */
@@ -96,7 +96,7 @@ public:
if (idx >= 0 && idx < cachedNodeStats.size())
return &cachedNodeStats[idx];
- return 0;
+ return nullptr;
}
};
@@ -104,12 +104,10 @@ PeerTableModel::PeerTableModel(interfaces::Node& node, ClientModel *parent) :
QAbstractTableModel(parent),
m_node(node),
clientModel(parent),
- timer(0)
+ timer(nullptr)
{
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);
@@ -199,8 +197,7 @@ QVariant PeerTableModel::headerData(int section, Qt::Orientation orientation, in
Qt::ItemFlags PeerTableModel::flags(const QModelIndex &index) const
{
- if(!index.isValid())
- return 0;
+ if (!index.isValid()) return Qt::NoItemFlags;
Qt::ItemFlags retval = Qt::ItemIsSelectable | Qt::ItemIsEnabled;
return retval;
diff --git a/src/qt/peertablemodel.h b/src/qt/peertablemodel.h
index 738a06496f..b3f5dd7dbe 100644
--- a/src/qt/peertablemodel.h
+++ b/src/qt/peertablemodel.h
@@ -51,7 +51,7 @@ class PeerTableModel : public QAbstractTableModel
Q_OBJECT
public:
- explicit PeerTableModel(interfaces::Node& node, ClientModel *parent = 0);
+ explicit PeerTableModel(interfaces::Node& node, ClientModel *parent = nullptr);
~PeerTableModel();
const CNodeCombinedStats *getNodeStats(int idx);
int getRowByNodeId(NodeId nodeid);
diff --git a/src/qt/platformstyle.cpp b/src/qt/platformstyle.cpp
index 56e0830cdc..d537d759de 100644
--- a/src/qt/platformstyle.cpp
+++ b/src/qt/platformstyle.cpp
@@ -139,6 +139,6 @@ const PlatformStyle *PlatformStyle::instantiate(const QString &platformId)
platform_styles[x].useExtraSpacing);
}
}
- return 0;
+ return nullptr;
}
diff --git a/src/qt/qvalidatedlineedit.cpp b/src/qt/qvalidatedlineedit.cpp
index 85c5a58a84..aa936d6b7c 100644
--- a/src/qt/qvalidatedlineedit.cpp
+++ b/src/qt/qvalidatedlineedit.cpp
@@ -10,7 +10,7 @@
QValidatedLineEdit::QValidatedLineEdit(QWidget *parent) :
QLineEdit(parent),
valid(true),
- checkValidator(0)
+ checkValidator(nullptr)
{
connect(this, &QValidatedLineEdit::textChanged, this, &QValidatedLineEdit::markValid);
}
diff --git a/src/qt/qvaluecombobox.h b/src/qt/qvaluecombobox.h
index f266302310..8892071fba 100644
--- a/src/qt/qvaluecombobox.h
+++ b/src/qt/qvaluecombobox.h
@@ -16,7 +16,7 @@ class QValueComboBox : public QComboBox
Q_PROPERTY(QVariant value READ value WRITE setValue NOTIFY valueChanged USER true)
public:
- explicit QValueComboBox(QWidget *parent = 0);
+ explicit QValueComboBox(QWidget *parent = nullptr);
QVariant value() const;
void setValue(const QVariant &value);
diff --git a/src/qt/receivecoinsdialog.cpp b/src/qt/receivecoinsdialog.cpp
index a7cc5da19e..bc96b5a6f7 100644
--- a/src/qt/receivecoinsdialog.cpp
+++ b/src/qt/receivecoinsdialog.cpp
@@ -25,8 +25,8 @@
ReceiveCoinsDialog::ReceiveCoinsDialog(const PlatformStyle *_platformStyle, QWidget *parent) :
QDialog(parent),
ui(new Ui::ReceiveCoinsDialog),
- columnResizingFixer(0),
- model(0),
+ columnResizingFixer(nullptr),
+ model(nullptr),
platformStyle(_platformStyle)
{
ui->setupUi(this);
diff --git a/src/qt/receivecoinsdialog.h b/src/qt/receivecoinsdialog.h
index bc0f6248f0..5bca2f46e2 100644
--- a/src/qt/receivecoinsdialog.h
+++ b/src/qt/receivecoinsdialog.h
@@ -39,7 +39,7 @@ public:
MINIMUM_COLUMN_WIDTH = 130
};
- explicit ReceiveCoinsDialog(const PlatformStyle *platformStyle, QWidget *parent = 0);
+ explicit ReceiveCoinsDialog(const PlatformStyle *platformStyle, QWidget *parent = nullptr);
~ReceiveCoinsDialog();
void setModel(WalletModel *model);
diff --git a/src/qt/receiverequestdialog.cpp b/src/qt/receiverequestdialog.cpp
index c561d948be..f5b30cf6d2 100644
--- a/src/qt/receiverequestdialog.cpp
+++ b/src/qt/receiverequestdialog.cpp
@@ -26,7 +26,7 @@
#endif
QRImageWidget::QRImageWidget(QWidget *parent):
- QLabel(parent), contextMenu(0)
+ QLabel(parent), contextMenu(nullptr)
{
contextMenu = new QMenu(this);
QAction *saveImageAction = new QAction(tr("&Save Image..."), this);
@@ -88,7 +88,7 @@ void QRImageWidget::contextMenuEvent(QContextMenuEvent *event)
ReceiveRequestDialog::ReceiveRequestDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::ReceiveRequestDialog),
- model(0)
+ model(nullptr)
{
ui->setupUi(this);
diff --git a/src/qt/receiverequestdialog.h b/src/qt/receiverequestdialog.h
index 5662af18b7..dd28fd73c8 100644
--- a/src/qt/receiverequestdialog.h
+++ b/src/qt/receiverequestdialog.h
@@ -28,7 +28,7 @@ class QRImageWidget : public QLabel
Q_OBJECT
public:
- explicit QRImageWidget(QWidget *parent = 0);
+ explicit QRImageWidget(QWidget *parent = nullptr);
QImage exportImage();
public Q_SLOTS:
@@ -48,7 +48,7 @@ class ReceiveRequestDialog : public QDialog
Q_OBJECT
public:
- explicit ReceiveRequestDialog(QWidget *parent = 0);
+ explicit ReceiveRequestDialog(QWidget *parent = nullptr);
~ReceiveRequestDialog();
void setModel(WalletModel *model);
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..2949e43915 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())];
}
@@ -484,7 +485,7 @@ RPCConsole::RPCConsole(interfaces::Node& node, const PlatformStyle *_platformSty
// set library version labels
#ifdef ENABLE_WALLET
- ui->berkeleyDBVersion->setText(DbEnv::version(0, 0, 0));
+ ui->berkeleyDBVersion->setText(DbEnv::version(nullptr, nullptr, nullptr));
#else
ui->label_berkeleyDBVersion->hide();
ui->berkeleyDBVersion->hide();
@@ -987,10 +988,9 @@ void RPCConsole::startExecutor()
void RPCConsole::on_tabWidget_currentChanged(int index)
{
- if (ui->tabWidget->widget(index) == ui->tab_console)
+ if (ui->tabWidget->widget(index) == ui->tab_console) {
ui->lineEdit->setFocus();
- else if (ui->tabWidget->widget(index) != ui->tab_peers)
- clearSelectedNode();
+ }
}
void RPCConsole::on_openDebugLogfileButton_clicked()
diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp
index 65db0280b7..6e00ab755c 100644
--- a/src/qt/sendcoinsdialog.cpp
+++ b/src/qt/sendcoinsdialog.cpp
@@ -54,8 +54,8 @@ int getIndexForConfTarget(int target) {
SendCoinsDialog::SendCoinsDialog(const PlatformStyle *_platformStyle, QWidget *parent) :
QDialog(parent),
ui(new Ui::SendCoinsDialog),
- clientModel(0),
- model(0),
+ clientModel(nullptr),
+ model(nullptr),
fNewRecipientAllowed(true),
fFeeMinimized(true),
platformStyle(_platformStyle)
@@ -443,7 +443,7 @@ SendCoinsEntry *SendCoinsDialog::addEntry()
void SendCoinsDialog::updateTabsAndLabels()
{
- setupTabChain(0);
+ setupTabChain(nullptr);
coinControlUpdateLabels();
}
@@ -478,7 +478,7 @@ QWidget *SendCoinsDialog::setupTabChain(QWidget *prev)
void SendCoinsDialog::setAddress(const QString &address)
{
- SendCoinsEntry *entry = 0;
+ SendCoinsEntry *entry = nullptr;
// Replace the first entry if it is still unused
if(ui->entries->count() == 1)
{
@@ -501,7 +501,7 @@ void SendCoinsDialog::pasteEntry(const SendCoinsRecipient &rv)
if(!fNewRecipientAllowed)
return;
- SendCoinsEntry *entry = 0;
+ SendCoinsEntry *entry = nullptr;
// Replace the first entry if it is still unused
if(ui->entries->count() == 1)
{
diff --git a/src/qt/sendcoinsdialog.h b/src/qt/sendcoinsdialog.h
index e1ebc77d59..337a72b878 100644
--- a/src/qt/sendcoinsdialog.h
+++ b/src/qt/sendcoinsdialog.h
@@ -31,7 +31,7 @@ class SendCoinsDialog : public QDialog
Q_OBJECT
public:
- explicit SendCoinsDialog(const PlatformStyle *platformStyle, QWidget *parent = 0);
+ explicit SendCoinsDialog(const PlatformStyle *platformStyle, QWidget *parent = nullptr);
~SendCoinsDialog();
void setClientModel(ClientModel *clientModel);
@@ -108,7 +108,7 @@ class SendConfirmationDialog : public QMessageBox
Q_OBJECT
public:
- SendConfirmationDialog(const QString &title, const QString &text, int secDelay = SEND_CONFIRM_DELAY, QWidget *parent = 0);
+ SendConfirmationDialog(const QString &title, const QString &text, int secDelay = SEND_CONFIRM_DELAY, QWidget *parent = nullptr);
int exec();
private Q_SLOTS:
diff --git a/src/qt/sendcoinsentry.cpp b/src/qt/sendcoinsentry.cpp
index 76c942c8b9..7324d759fb 100644
--- a/src/qt/sendcoinsentry.cpp
+++ b/src/qt/sendcoinsentry.cpp
@@ -21,7 +21,7 @@
SendCoinsEntry::SendCoinsEntry(const PlatformStyle *_platformStyle, QWidget *parent) :
QStackedWidget(parent),
ui(new Ui::SendCoinsEntry),
- model(0),
+ model(nullptr),
platformStyle(_platformStyle)
{
ui->setupUi(this);
@@ -155,7 +155,7 @@ bool SendCoinsEntry::validate(interfaces::Node& node)
}
// Sending a zero amount is invalid
- if (ui->payAmount->value(0) <= 0)
+ if (ui->payAmount->value(nullptr) <= 0)
{
ui->payAmount->setValid(false);
retval = false;
diff --git a/src/qt/sendcoinsentry.h b/src/qt/sendcoinsentry.h
index 48ecd598d6..42e2217130 100644
--- a/src/qt/sendcoinsentry.h
+++ b/src/qt/sendcoinsentry.h
@@ -26,7 +26,7 @@ class SendCoinsEntry : public QStackedWidget
Q_OBJECT
public:
- explicit SendCoinsEntry(const PlatformStyle *platformStyle, QWidget *parent = 0);
+ explicit SendCoinsEntry(const PlatformStyle *platformStyle, QWidget *parent = nullptr);
~SendCoinsEntry();
void setModel(WalletModel *model);
diff --git a/src/qt/signverifymessagedialog.cpp b/src/qt/signverifymessagedialog.cpp
index 487fc9ee1e..d37a78fa8c 100644
--- a/src/qt/signverifymessagedialog.cpp
+++ b/src/qt/signverifymessagedialog.cpp
@@ -22,7 +22,7 @@
SignVerifyMessageDialog::SignVerifyMessageDialog(const PlatformStyle *_platformStyle, QWidget *parent) :
QDialog(parent),
ui(new Ui::SignVerifyMessageDialog),
- model(0),
+ model(nullptr),
platformStyle(_platformStyle)
{
ui->setupUi(this);
diff --git a/src/qt/splashscreen.cpp b/src/qt/splashscreen.cpp
index b109a08b1c..0126a2920e 100644
--- a/src/qt/splashscreen.cpp
+++ b/src/qt/splashscreen.cpp
@@ -26,7 +26,7 @@
SplashScreen::SplashScreen(interfaces::Node& node, Qt::WindowFlags f, const NetworkStyle *networkStyle) :
- QWidget(0, f), curAlignment(0), m_node(node)
+ QWidget(nullptr, f), curAlignment(0), m_node(node)
{
// set reference point, paddings
int paddingRight = 50;
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/trafficgraphwidget.cpp b/src/qt/trafficgraphwidget.cpp
index 3aed3f2b97..1588be8da3 100644
--- a/src/qt/trafficgraphwidget.cpp
+++ b/src/qt/trafficgraphwidget.cpp
@@ -19,14 +19,14 @@
TrafficGraphWidget::TrafficGraphWidget(QWidget *parent) :
QWidget(parent),
- timer(0),
+ timer(nullptr),
fMax(0.0f),
nMins(0),
vSamplesIn(),
vSamplesOut(),
nLastBytesIn(0),
nLastBytesOut(0),
- clientModel(0)
+ clientModel(nullptr)
{
timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, &TrafficGraphWidget::updateRates);
diff --git a/src/qt/trafficgraphwidget.h b/src/qt/trafficgraphwidget.h
index 00660574af..48bd246b34 100644
--- a/src/qt/trafficgraphwidget.h
+++ b/src/qt/trafficgraphwidget.h
@@ -20,7 +20,7 @@ class TrafficGraphWidget : public QWidget
Q_OBJECT
public:
- explicit TrafficGraphWidget(QWidget *parent = 0);
+ explicit TrafficGraphWidget(QWidget *parent = nullptr);
void setClientModel(ClientModel *model);
int getGraphRangeMins() const;
diff --git a/src/qt/transactiondescdialog.h b/src/qt/transactiondescdialog.h
index f1371b3856..8fd3f3166a 100644
--- a/src/qt/transactiondescdialog.h
+++ b/src/qt/transactiondescdialog.h
@@ -21,7 +21,7 @@ class TransactionDescDialog : public QDialog
Q_OBJECT
public:
- explicit TransactionDescDialog(const QModelIndex &idx, QWidget *parent = 0);
+ explicit TransactionDescDialog(const QModelIndex &idx, QWidget *parent = nullptr);
~TransactionDescDialog();
private:
diff --git a/src/qt/transactionfilterproxy.h b/src/qt/transactionfilterproxy.h
index 9febd59820..685f8d3a26 100644
--- a/src/qt/transactionfilterproxy.h
+++ b/src/qt/transactionfilterproxy.h
@@ -16,7 +16,7 @@ class TransactionFilterProxy : public QSortFilterProxyModel
Q_OBJECT
public:
- explicit TransactionFilterProxy(QObject *parent = 0);
+ explicit TransactionFilterProxy(QObject *parent = nullptr);
/** Earliest date that can be represented (far in the past) */
static const QDateTime MIN_DATE;
diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp
index d88cfe52ed..aa785553c8 100644
--- a/src/qt/transactionrecord.cpp
+++ b/src/qt/transactionrecord.cpp
@@ -4,6 +4,7 @@
#include <qt/transactionrecord.h>
+#include <chain.h>
#include <consensus/consensus.h>
#include <interfaces/wallet.h>
#include <key_io.h>
@@ -12,6 +13,7 @@
#include <stdint.h>
+#include <QDateTime>
/* Return positive answer if transaction should be shown in list.
*/
@@ -158,7 +160,7 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const interface
return parts;
}
-void TransactionRecord::updateStatus(const interfaces::WalletTxStatus& wtx, int numBlocks)
+void TransactionRecord::updateStatus(const interfaces::WalletTxStatus& wtx, int numBlocks, int64_t block_time)
{
// Determine transaction status
@@ -172,10 +174,9 @@ void TransactionRecord::updateStatus(const interfaces::WalletTxStatus& wtx, int
status.depth = wtx.depth_in_main_chain;
status.cur_num_blocks = numBlocks;
- if (!wtx.is_final)
- {
- if (wtx.lock_time < LOCKTIME_THRESHOLD)
- {
+ const bool up_to_date = ((int64_t)QDateTime::currentMSecsSinceEpoch() / 1000 - block_time < MAX_BLOCK_TIME_GAP);
+ if (up_to_date && !wtx.is_final) {
+ if (wtx.lock_time < LOCKTIME_THRESHOLD) {
status.status = TransactionStatus::OpenUntilBlock;
status.open_for = wtx.lock_time - numBlocks;
}
diff --git a/src/qt/transactionrecord.h b/src/qt/transactionrecord.h
index 470f70e2ab..3f64cefd09 100644
--- a/src/qt/transactionrecord.h
+++ b/src/qt/transactionrecord.h
@@ -138,7 +138,7 @@ public:
/** Update status from core wallet tx.
*/
- void updateStatus(const interfaces::WalletTxStatus& wtx, int numBlocks);
+ void updateStatus(const interfaces::WalletTxStatus& wtx, int numBlocks, int64_t block_time);
/** Return whether a status update is needed.
*/
diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp
index 01722146c5..631a9b891d 100644
--- a/src/qt/transactiontablemodel.cpp
+++ b/src/qt/transactiontablemodel.cpp
@@ -192,12 +192,13 @@ public:
// simply re-use the cached status.
interfaces::WalletTxStatus wtx;
int numBlocks;
- if (wallet.tryGetTxStatus(rec->hash, wtx, numBlocks) && rec->statusUpdateNeeded(numBlocks)) {
- rec->updateStatus(wtx, numBlocks);
+ int64_t block_time;
+ if (wallet.tryGetTxStatus(rec->hash, wtx, numBlocks, block_time) && rec->statusUpdateNeeded(numBlocks)) {
+ rec->updateStatus(wtx, numBlocks, block_time);
}
return rec;
}
- return 0;
+ return nullptr;
}
QString describe(interfaces::Node& node, interfaces::Wallet& wallet, TransactionRecord *rec, int unit)
diff --git a/src/qt/transactiontablemodel.h b/src/qt/transactiontablemodel.h
index 8be3a7ab2e..7a7d98962b 100644
--- a/src/qt/transactiontablemodel.h
+++ b/src/qt/transactiontablemodel.h
@@ -28,7 +28,7 @@ class TransactionTableModel : public QAbstractTableModel
Q_OBJECT
public:
- explicit TransactionTableModel(const PlatformStyle *platformStyle, WalletModel *parent = 0);
+ explicit TransactionTableModel(const PlatformStyle *platformStyle, WalletModel *parent = nullptr);
~TransactionTableModel();
enum ColumnIndex {
diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp
index 68410c8bd6..eb6437eb31 100644
--- a/src/qt/transactionview.cpp
+++ b/src/qt/transactionview.cpp
@@ -38,8 +38,8 @@
#include <QVBoxLayout>
TransactionView::TransactionView(const PlatformStyle *platformStyle, QWidget *parent) :
- QWidget(parent), model(0), transactionProxyModel(0),
- transactionView(0), abandonAction(0), bumpFeeAction(0), columnResizingFixer(0)
+ QWidget(parent), model(nullptr), transactionProxyModel(nullptr),
+ transactionView(nullptr), abandonAction(nullptr), bumpFeeAction(nullptr), columnResizingFixer(nullptr)
{
// Build filter row
setContentsMargins(0,0,0,0);
diff --git a/src/qt/transactionview.h b/src/qt/transactionview.h
index fdd8b069c7..e07181d1c8 100644
--- a/src/qt/transactionview.h
+++ b/src/qt/transactionview.h
@@ -35,7 +35,7 @@ class TransactionView : public QWidget
Q_OBJECT
public:
- explicit TransactionView(const PlatformStyle *platformStyle, QWidget *parent = 0);
+ explicit TransactionView(const PlatformStyle *platformStyle, QWidget *parent = nullptr);
void setModel(WalletModel *model);
diff --git a/src/qt/utilitydialog.h b/src/qt/utilitydialog.h
index ad1fda4573..f1cedff282 100644
--- a/src/qt/utilitydialog.h
+++ b/src/qt/utilitydialog.h
@@ -45,7 +45,7 @@ class ShutdownWindow : public QWidget
Q_OBJECT
public:
- explicit ShutdownWindow(QWidget *parent=0, Qt::WindowFlags f=0);
+ explicit ShutdownWindow(QWidget *parent=nullptr, Qt::WindowFlags f=Qt::Widget);
static QWidget *showShutdownWindow(BitcoinGUI *window);
protected:
diff --git a/src/qt/walletframe.cpp b/src/qt/walletframe.cpp
index 4f8b6d363e..466f2278eb 100644
--- a/src/qt/walletframe.cpp
+++ b/src/qt/walletframe.cpp
@@ -208,11 +208,17 @@ void WalletFrame::usedReceivingAddresses()
walletView->usedReceivingAddresses();
}
-WalletView *WalletFrame::currentWalletView()
+WalletView* WalletFrame::currentWalletView() const
{
return qobject_cast<WalletView*>(walletStack->currentWidget());
}
+WalletModel* WalletFrame::currentWalletModel() const
+{
+ WalletView* wallet_view = currentWalletView();
+ return wallet_view ? wallet_view->getWalletModel() : nullptr;
+}
+
void WalletFrame::outOfSyncWarningClicked()
{
Q_EMIT requestedSyncWarningInfo();
diff --git a/src/qt/walletframe.h b/src/qt/walletframe.h
index 9fbc8b4d52..6a74fde9fd 100644
--- a/src/qt/walletframe.h
+++ b/src/qt/walletframe.h
@@ -31,7 +31,7 @@ class WalletFrame : public QFrame
Q_OBJECT
public:
- explicit WalletFrame(const PlatformStyle *platformStyle, BitcoinGUI *_gui = 0);
+ explicit WalletFrame(const PlatformStyle *platformStyle, BitcoinGUI *_gui = nullptr);
~WalletFrame();
void setClientModel(ClientModel *clientModel);
@@ -60,7 +60,8 @@ private:
const PlatformStyle *platformStyle;
public:
- WalletView *currentWalletView();
+ WalletView* currentWalletView() const;
+ WalletModel* currentWalletModel() const;
public Q_SLOTS:
/** Switch to overview (home) page */
diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp
index b7fa636494..e1fb4819f1 100644
--- a/src/qt/walletmodel.cpp
+++ b/src/qt/walletmodel.cpp
@@ -33,15 +33,13 @@
WalletModel::WalletModel(std::unique_ptr<interfaces::Wallet> wallet, interfaces::Node& node, const PlatformStyle *platformStyle, OptionsModel *_optionsModel, QObject *parent) :
- QObject(parent), m_wallet(std::move(wallet)), m_node(node), optionsModel(_optionsModel), addressTableModel(0),
- transactionTableModel(0),
- recentRequestsTableModel(0),
+ QObject(parent), m_wallet(std::move(wallet)), m_node(node), optionsModel(_optionsModel), addressTableModel(nullptr),
+ transactionTableModel(nullptr),
+ recentRequestsTableModel(nullptr),
cachedEncryptionStatus(Unencrypted),
cachedNumBlocks(0)
{
fHaveWatchOnly = m_wallet->haveWatchOnly();
- fForceCheckBalanceChanged = false;
-
addressTableModel = new AddressTableModel(this);
transactionTableModel = new TransactionTableModel(platformStyle, this);
recentRequestsTableModel = new RecentRequestsTableModel(this);
@@ -512,7 +510,7 @@ bool WalletModel::bumpFee(uint256 hash, uint256& new_hash)
CAmount new_fee;
CMutableTransaction mtx;
if (!m_wallet->createBumpTransaction(hash, coin_control, 0 /* totalFee */, errors, old_fee, new_fee, mtx)) {
- QMessageBox::critical(0, tr("Fee bump error"), tr("Increasing transaction fee failed") + "<br />(" +
+ QMessageBox::critical(nullptr, tr("Fee bump error"), tr("Increasing transaction fee failed") + "<br />(" +
(errors.size() ? QString::fromStdString(errors[0]) : "") +")");
return false;
}
@@ -551,12 +549,12 @@ bool WalletModel::bumpFee(uint256 hash, uint256& new_hash)
// sign bumped transaction
if (!m_wallet->signBumpTransaction(mtx)) {
- QMessageBox::critical(0, tr("Fee bump error"), tr("Can't sign transaction."));
+ QMessageBox::critical(nullptr, tr("Fee bump error"), tr("Can't sign transaction."));
return false;
}
// commit the bumped transaction
if(!m_wallet->commitBumpTransaction(hash, std::move(mtx), errors, new_hash)) {
- QMessageBox::critical(0, tr("Fee bump error"), tr("Could not commit transaction") + "<br />(" +
+ QMessageBox::critical(nullptr, tr("Fee bump error"), tr("Could not commit transaction") + "<br />(" +
QString::fromStdString(errors[0])+")");
return false;
}
diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h
index 2988682533..c3c8f36909 100644
--- a/src/qt/walletmodel.h
+++ b/src/qt/walletmodel.h
@@ -127,7 +127,7 @@ class WalletModel : public QObject
Q_OBJECT
public:
- explicit WalletModel(std::unique_ptr<interfaces::Wallet> wallet, interfaces::Node& node, const PlatformStyle *platformStyle, OptionsModel *optionsModel, QObject *parent = 0);
+ explicit WalletModel(std::unique_ptr<interfaces::Wallet> wallet, interfaces::Node& node, const PlatformStyle *platformStyle, OptionsModel *optionsModel, QObject *parent = nullptr);
~WalletModel();
enum StatusCode // Returned by sendCoins
@@ -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/qt/walletview.cpp b/src/qt/walletview.cpp
index a619992344..dd089d8310 100644
--- a/src/qt/walletview.cpp
+++ b/src/qt/walletview.cpp
@@ -32,8 +32,8 @@
WalletView::WalletView(const PlatformStyle *_platformStyle, QWidget *parent):
QStackedWidget(parent),
- clientModel(0),
- walletModel(0),
+ clientModel(nullptr),
+ walletModel(nullptr),
platformStyle(_platformStyle)
{
// Create tabs
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index 55282f433f..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)
@@ -1564,7 +1569,7 @@ static UniValue reconsiderblock(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() != 1)
throw std::runtime_error(
RPCHelpMan{"reconsiderblock",
- "\nRemoves invalidity status of a block and its descendants, reconsider them for activation.\n"
+ "\nRemoves invalidity status of a block, its ancestors and its descendants, reconsider them for activation.\n"
"This can be used to undo the effects of invalidateblock.\n",
{
{"blockhash", RPCArg::Type::STR_HEX, /* opt */ false, /* default_val */ "", "the hash of the block to reconsider"},
diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp
index 4d6b260cc7..6fdf80dc5f 100644
--- a/src/rpc/net.cpp
+++ b/src/rpc/net.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2018 The Bitcoin Core developers
+// Copyright (c) 2009-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -109,11 +109,15 @@ static UniValue getpeerinfo(const JSONRPCRequest& request)
" \"whitelisted\": true|false, (boolean) Whether the peer is whitelisted\n"
" \"minfeefilter\": n, (numeric) The minimum fee rate for transactions this peer accepts\n"
" \"bytessent_per_msg\": {\n"
- " \"addr\": n, (numeric) The total bytes sent aggregated by message type\n"
+ " \"msg\": n, (numeric) The total bytes sent aggregated by message type\n"
+ " When a message type is not listed in this json object, the bytes sent are 0.\n"
+ " Only known message types can appear as keys in the object.\n"
" ...\n"
" },\n"
" \"bytesrecv_per_msg\": {\n"
- " \"addr\": n, (numeric) The total bytes received aggregated by message type\n"
+ " \"msg\": n, (numeric) The total bytes received aggregated by message type\n"
+ " When a message type is not listed in this json object, the bytes received are 0.\n"
+ " Only known message types can appear as keys in the object and all bytes received of unknown message types are listed under '"+NET_MESSAGE_COMMAND_OTHER+"'.\n"
" ...\n"
" }\n"
" }\n"
@@ -178,14 +182,14 @@ static UniValue getpeerinfo(const JSONRPCRequest& request)
obj.pushKV("minfeefilter", ValueFromAmount(stats.minFeeFilter));
UniValue sendPerMsgCmd(UniValue::VOBJ);
- for (const mapMsgCmdSize::value_type &i : stats.mapSendBytesPerMsgCmd) {
+ for (const auto& i : stats.mapSendBytesPerMsgCmd) {
if (i.second > 0)
sendPerMsgCmd.pushKV(i.first, i.second);
}
obj.pushKV("bytessent_per_msg", sendPerMsgCmd);
UniValue recvPerMsgCmd(UniValue::VOBJ);
- for (const mapMsgCmdSize::value_type &i : stats.mapRecvBytesPerMsgCmd) {
+ for (const auto& i : stats.mapRecvBytesPerMsgCmd) {
if (i.second > 0)
recvPerMsgCmd.pushKV(i.first, i.second);
}
@@ -419,7 +423,7 @@ static UniValue GetNetworksInfo()
UniValue obj(UniValue::VOBJ);
GetProxy(network, proxy);
obj.pushKV("name", GetNetworkName(network));
- obj.pushKV("limited", IsLimited(network));
+ obj.pushKV("limited", !IsReachable(network));
obj.pushKV("reachable", IsReachable(network));
obj.pushKV("proxy", proxy.IsValid() ? proxy.proxy.ToStringIPPort() : std::string());
obj.pushKV("proxy_randomize_credentials", proxy.randomize_credentials);
diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp
index e7e047334e..edaf64f3e1 100644
--- a/src/rpc/server.cpp
+++ b/src/rpc/server.cpp
@@ -31,11 +31,39 @@ static RPCTimerInterface* timerInterface = nullptr;
/* Map of name to timer. */
static std::map<std::string, std::unique_ptr<RPCTimerBase> > deadlineTimers;
+struct RPCCommandExecutionInfo
+{
+ std::string method;
+ int64_t start;
+};
+
+struct RPCServerInfo
+{
+ Mutex mutex;
+ std::list<RPCCommandExecutionInfo> active_commands GUARDED_BY(mutex);
+};
+
+static RPCServerInfo g_rpc_server_info;
+
+struct RPCCommandExecution
+{
+ std::list<RPCCommandExecutionInfo>::iterator it;
+ explicit RPCCommandExecution(const std::string& method)
+ {
+ LOCK(g_rpc_server_info.mutex);
+ it = g_rpc_server_info.active_commands.insert(g_rpc_server_info.active_commands.cend(), {method, GetTimeMicros()});
+ }
+ ~RPCCommandExecution()
+ {
+ LOCK(g_rpc_server_info.mutex);
+ g_rpc_server_info.active_commands.erase(it);
+ }
+};
+
static struct CRPCSignals
{
boost::signals2::signal<void ()> Started;
boost::signals2::signal<void ()> Stopped;
- boost::signals2::signal<void (const CRPCCommand&)> PreCommand;
} g_rpcSignals;
void RPCServer::OnStarted(std::function<void ()> slot)
@@ -254,11 +282,37 @@ static UniValue uptime(const JSONRPCRequest& jsonRequest)
return GetTime() - GetStartupTime();
}
+static UniValue getrpcinfo(const JSONRPCRequest& request)
+{
+ if (request.fHelp || request.params.size() > 0) {
+ throw std::runtime_error(
+ RPCHelpMan{"getrpcinfo",
+ "\nReturns details of the RPC server.\n", {}}
+ .ToString()
+ );
+ }
+
+ LOCK(g_rpc_server_info.mutex);
+ UniValue active_commands(UniValue::VARR);
+ for (const RPCCommandExecutionInfo& info : g_rpc_server_info.active_commands) {
+ UniValue entry(UniValue::VOBJ);
+ entry.pushKV("method", info.method);
+ entry.pushKV("duration", GetTimeMicros() - info.start);
+ active_commands.push_back(entry);
+ }
+
+ UniValue result(UniValue::VOBJ);
+ result.pushKV("active_commands", active_commands);
+
+ return result;
+}
+
// clang-format off
static const CRPCCommand vRPCCommands[] =
{ // category name actor (function) argNames
// --------------------- ------------------------ ----------------------- ----------
/* Overall control/query calls */
+ { "control", "getrpcinfo", &getrpcinfo, {} },
{ "control", "help", &help, {"command"} },
{ "control", "stop", &stop, {"wait"} },
{ "control", "uptime", &uptime, {} },
@@ -483,10 +537,9 @@ UniValue CRPCTable::execute(const JSONRPCRequest &request) const
if (!pcmd)
throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found");
- g_rpcSignals.PreCommand(*pcmd);
-
try
{
+ RPCCommandExecution execution(request.strMethod);
// Execute, convert arguments to array if necessary
if (request.params.isObject()) {
return pcmd->actor(transformNamedArguments(request, pcmd->argNames));
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/sync.h b/src/sync.h
index 40709bdd7f..3857eda56b 100644
--- a/src/sync.h
+++ b/src/sync.h
@@ -20,7 +20,7 @@
////////////////////////////////////////////////
/*
-CCriticalSection mutex;
+RecursiveMutex mutex;
std::recursive_mutex mutex;
LOCK(mutex);
@@ -104,6 +104,7 @@ public:
* Wrapped mutex: supports recursive locking, but no waiting
* TODO: We should move away from using the recursive lock by default.
*/
+using RecursiveMutex = AnnotatedMixin<std::recursive_mutex>;
typedef AnnotatedMixin<std::recursive_mutex> CCriticalSection;
/** Wrapped mutex: supports waiting but not recursive locking */
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/allocator_tests.cpp b/src/test/allocator_tests.cpp
index 582082f6a4..9eded4f5b2 100644
--- a/src/test/allocator_tests.cpp
+++ b/src/test/allocator_tests.cpp
@@ -105,13 +105,13 @@ BOOST_AUTO_TEST_CASE(arena_tests)
// Go entirely wild: free and alloc interleaved,
// generate targets and sizes using pseudo-randomness.
for (int x=0; x<2048; ++x)
- addr.push_back(0);
+ addr.push_back(nullptr);
uint32_t s = 0x12345678;
for (int x=0; x<5000; ++x) {
int idx = s & (addr.size()-1);
if (s & 0x80000000) {
b.free(addr[idx]);
- addr[idx] = 0;
+ addr[idx] = nullptr;
} else if(!addr[idx]) {
addr[idx] = b.alloc((s >> 16) & 2047);
}
@@ -146,7 +146,7 @@ public:
return reinterpret_cast<void*>(uint64_t{static_cast<uint64_t>(0x08000000) + (count << 24)}); // Fake address, do not actually use this memory
}
- return 0;
+ return nullptr;
}
void FreeLocked(void* addr, size_t len) override
{
diff --git a/src/test/blockencodings_tests.cpp b/src/test/blockencodings_tests.cpp
index 309b8d2d06..607af8a32a 100644
--- a/src/test/blockencodings_tests.cpp
+++ b/src/test/blockencodings_tests.cpp
@@ -62,7 +62,7 @@ BOOST_AUTO_TEST_CASE(SimpleRoundTripTest)
TestMemPoolEntryHelper entry;
CBlock block(BuildBlockTestCase());
- LOCK(pool.cs);
+ LOCK2(cs_main, pool.cs);
pool.addUnchecked(entry.FromTx(block.vtx[2]));
BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[2]->GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 0);
@@ -162,7 +162,7 @@ BOOST_AUTO_TEST_CASE(NonCoinbasePreforwardRTTest)
TestMemPoolEntryHelper entry;
CBlock block(BuildBlockTestCase());
- LOCK(pool.cs);
+ LOCK2(cs_main, pool.cs);
pool.addUnchecked(entry.FromTx(block.vtx[2]));
BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[2]->GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 0);
@@ -232,7 +232,7 @@ BOOST_AUTO_TEST_CASE(SufficientPreforwardRTTest)
TestMemPoolEntryHelper entry;
CBlock block(BuildBlockTestCase());
- LOCK(pool.cs);
+ LOCK2(cs_main, pool.cs);
pool.addUnchecked(entry.FromTx(block.vtx[1]));
BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[1]->GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 0);
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/mempool_tests.cpp b/src/test/mempool_tests.cpp
index 2396aba0f1..23ca9d89ae 100644
--- a/src/test/mempool_tests.cpp
+++ b/src/test/mempool_tests.cpp
@@ -55,7 +55,7 @@ BOOST_AUTO_TEST_CASE(MempoolRemoveTest)
CTxMemPool testPool;
- LOCK(testPool.cs);
+ LOCK2(cs_main, testPool.cs);
// Nothing in pool, remove should do nothing:
unsigned int poolSize = testPool.size();
@@ -120,7 +120,7 @@ static void CheckSort(CTxMemPool &pool, std::vector<std::string> &sortedOrder) E
BOOST_AUTO_TEST_CASE(MempoolIndexingTest)
{
CTxMemPool pool;
- LOCK(pool.cs);
+ LOCK2(cs_main, pool.cs);
TestMemPoolEntryHelper entry;
/* 3rd highest fee */
@@ -293,7 +293,7 @@ BOOST_AUTO_TEST_CASE(MempoolIndexingTest)
BOOST_AUTO_TEST_CASE(MempoolAncestorIndexingTest)
{
CTxMemPool pool;
- LOCK(pool.cs);
+ LOCK2(cs_main, pool.cs);
TestMemPoolEntryHelper entry;
/* 3rd highest fee */
@@ -422,7 +422,7 @@ BOOST_AUTO_TEST_CASE(MempoolAncestorIndexingTest)
BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest)
{
CTxMemPool pool;
- LOCK(pool.cs);
+ LOCK2(cs_main, pool.cs);
TestMemPoolEntryHelper entry;
CMutableTransaction tx1 = CMutableTransaction();
@@ -595,7 +595,7 @@ BOOST_AUTO_TEST_CASE(MempoolAncestryTests)
size_t ancestors, descendants;
CTxMemPool pool;
- LOCK(pool.cs);
+ LOCK2(cs_main, pool.cs);
TestMemPoolEntryHelper entry;
/* Base transaction */
diff --git a/src/test/merkle_tests.cpp b/src/test/merkle_tests.cpp
index 5e55ad6622..4cdf0f003e 100644
--- a/src/test/merkle_tests.cpp
+++ b/src/test/merkle_tests.cpp
@@ -13,9 +13,9 @@ static uint256 ComputeMerkleRootFromBranch(const uint256& leaf, const std::vecto
uint256 hash = leaf;
for (std::vector<uint256>::const_iterator it = vMerkleBranch.begin(); it != vMerkleBranch.end(); ++it) {
if (nIndex & 1) {
- hash = Hash(BEGIN(*it), END(*it), BEGIN(hash), END(hash));
+ hash = Hash(it->begin(), it->end(), hash.begin(), hash.end());
} else {
- hash = Hash(BEGIN(hash), END(hash), BEGIN(*it), END(*it));
+ hash = Hash(hash.begin(), hash.end(), it->begin(), it->end());
}
nIndex >>= 1;
}
diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp
index f3648e2eee..5ba1df2ec2 100644
--- a/src/test/miner_tests.cpp
+++ b/src/test/miner_tests.cpp
@@ -99,7 +99,7 @@ static bool TestSequenceLocks(const CTransaction &tx, int flags) EXCLUSIVE_LOCKS
// Test suite for ancestor feerate transaction selection.
// Implemented as an additional function, rather than a separate test case,
// to allow reusing the blockchain created in CreateNewBlock_validity.
-static void TestPackageSelection(const CChainParams& chainparams, const CScript& scriptPubKey, const std::vector<CTransactionRef>& txFirst) EXCLUSIVE_LOCKS_REQUIRED(::mempool.cs)
+static void TestPackageSelection(const CChainParams& chainparams, const CScript& scriptPubKey, const std::vector<CTransactionRef>& txFirst) EXCLUSIVE_LOCKS_REQUIRED(cs_main, ::mempool.cs)
{
// Test the ancestor feerate transaction selection.
TestMemPoolEntryHelper entry;
diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp
index e7a3c96343..b4ae8e9765 100644
--- a/src/test/net_tests.cpp
+++ b/src/test/net_tests.cpp
@@ -227,4 +227,80 @@ BOOST_AUTO_TEST_CASE(ipv4_peer_with_ipv6_addrMe_test)
BOOST_CHECK(1);
}
+
+BOOST_AUTO_TEST_CASE(LimitedAndReachable_Network)
+{
+ BOOST_CHECK_EQUAL(IsReachable(NET_IPV4), true);
+ BOOST_CHECK_EQUAL(IsReachable(NET_IPV6), true);
+ BOOST_CHECK_EQUAL(IsReachable(NET_ONION), true);
+
+ SetReachable(NET_IPV4, false);
+ SetReachable(NET_IPV6, false);
+ SetReachable(NET_ONION, false);
+
+ BOOST_CHECK_EQUAL(IsReachable(NET_IPV4), false);
+ BOOST_CHECK_EQUAL(IsReachable(NET_IPV6), false);
+ BOOST_CHECK_EQUAL(IsReachable(NET_ONION), false);
+
+ SetReachable(NET_IPV4, true);
+ SetReachable(NET_IPV6, true);
+ SetReachable(NET_ONION, true);
+
+ 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(IsReachable(NET_UNROUTABLE), true);
+ BOOST_CHECK_EQUAL(IsReachable(NET_INTERNAL), true);
+
+ SetReachable(NET_UNROUTABLE, false);
+ SetReachable(NET_INTERNAL, false);
+
+ BOOST_CHECK_EQUAL(IsReachable(NET_UNROUTABLE), true); // Ignored for both networks
+ 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
+
+ SetReachable(NET_IPV4, true);
+ BOOST_CHECK_EQUAL(IsReachable(addr), true);
+
+ SetReachable(NET_IPV4, false);
+ BOOST_CHECK_EQUAL(IsReachable(addr), false);
+
+ SetReachable(NET_IPV4, true); // 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
+
+ SetReachable(NET_IPV4, true);
+
+ 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/policyestimator_tests.cpp b/src/test/policyestimator_tests.cpp
index 431b16cfc2..7b274a1658 100644
--- a/src/test/policyestimator_tests.cpp
+++ b/src/test/policyestimator_tests.cpp
@@ -18,7 +18,7 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates)
{
CBlockPolicyEstimator feeEst;
CTxMemPool mpool(&feeEst);
- LOCK(mpool.cs);
+ LOCK2(cs_main, mpool.cs);
TestMemPoolEntryHelper entry;
CAmount basefee(2000);
CAmount deltaFee(100);
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/test/util_tests.cpp b/src/test/util_tests.cpp
index 9acebdd820..71b6ec7425 100644
--- a/src/test/util_tests.cpp
+++ b/src/test/util_tests.cpp
@@ -1224,7 +1224,7 @@ BOOST_AUTO_TEST_CASE(test_ToLower)
BOOST_CHECK_EQUAL(ToLower('Z'), 'z');
BOOST_CHECK_EQUAL(ToLower('['), '[');
BOOST_CHECK_EQUAL(ToLower(0), 0);
- BOOST_CHECK_EQUAL(ToLower(255), 255);
+ BOOST_CHECK_EQUAL(ToLower('\xff'), '\xff');
std::string testVector;
Downcase(testVector);
@@ -1246,7 +1246,7 @@ BOOST_AUTO_TEST_CASE(test_ToUpper)
BOOST_CHECK_EQUAL(ToUpper('z'), 'Z');
BOOST_CHECK_EQUAL(ToUpper('{'), '{');
BOOST_CHECK_EQUAL(ToUpper(0), 0);
- BOOST_CHECK_EQUAL(ToUpper(255), 255);
+ BOOST_CHECK_EQUAL(ToUpper('\xff'), '\xff');
}
BOOST_AUTO_TEST_CASE(test_Capitalize)
diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp
index c9ee6f9f81..550e23b222 100644
--- a/src/torcontrol.cpp
+++ b/src/torcontrol.cpp
@@ -527,7 +527,7 @@ void TorController::auth_cb(TorControlConnection& _conn, const TorControlReply&
CService resolved(LookupNumeric("127.0.0.1", 9050));
proxyType addrOnion = proxyType(resolved, true);
SetProxy(NET_ONION, addrOnion);
- SetLimited(NET_ONION, false);
+ SetReachable(NET_ONION, true);
}
// Finally - now create the service
diff --git a/src/txmempool.h b/src/txmempool.h
index fadb554723..b10c9f099f 100644
--- a/src/txmempool.h
+++ b/src/txmempool.h
@@ -485,7 +485,43 @@ public:
>
> indexed_transaction_set;
- mutable CCriticalSection cs;
+ /**
+ * This mutex needs to be locked when accessing `mapTx` or other members
+ * that are guarded by it.
+ *
+ * @par Consistency guarantees
+ *
+ * By design, it is guaranteed that:
+ *
+ * 1. Locking both `cs_main` and `mempool.cs` will give a view of mempool
+ * that is consistent with current chain tip (`chainActive` and
+ * `pcoinsTip`) and is fully populated. Fully populated means that if the
+ * current active chain is missing transactions that were present in a
+ * previously active chain, all the missing transactions will have been
+ * re-added to the mempool and should be present if they meet size and
+ * consistency constraints.
+ *
+ * 2. Locking `mempool.cs` without `cs_main` will give a view of a mempool
+ * consistent with some chain that was active since `cs_main` was last
+ * locked, and that is fully populated as described above. It is ok for
+ * code that only needs to query or remove transactions from the mempool
+ * to lock just `mempool.cs` without `cs_main`.
+ *
+ * To provide these guarantees, it is necessary to lock both `cs_main` and
+ * `mempool.cs` whenever adding transactions to the mempool and whenever
+ * changing the chain tip. It's necessary to keep both mutexes locked until
+ * the mempool is consistent with the new chain tip and fully populated.
+ *
+ * @par Consistency bug
+ *
+ * The second guarantee above is not currently enforced, but
+ * https://github.com/bitcoin/bitcoin/pull/14193 will fix it. No known code
+ * in bitcoin currently depends on second guarantee, but it is important to
+ * fix for third party code that needs be able to frequently poll the
+ * mempool without locking `cs_main` and without encountering missing
+ * transactions during reorgs.
+ */
+ mutable RecursiveMutex cs;
indexed_transaction_set mapTx GUARDED_BY(cs);
using txiter = indexed_transaction_set::nth_index<0>::type::const_iterator;
@@ -541,8 +577,8 @@ public:
// Note that addUnchecked is ONLY called from ATMP outside of tests
// and any other callers may break wallet's in-mempool tracking (due to
// lack of CValidationInterface::TransactionAddedToMempool callbacks).
- void addUnchecked(const CTxMemPoolEntry& entry, bool validFeeEstimate = true) EXCLUSIVE_LOCKS_REQUIRED(cs);
- void addUnchecked(const CTxMemPoolEntry& entry, setEntries& setAncestors, bool validFeeEstimate = true) EXCLUSIVE_LOCKS_REQUIRED(cs);
+ void addUnchecked(const CTxMemPoolEntry& entry, bool validFeeEstimate = true) EXCLUSIVE_LOCKS_REQUIRED(cs, cs_main);
+ void addUnchecked(const CTxMemPoolEntry& entry, setEntries& setAncestors, bool validFeeEstimate = true) EXCLUSIVE_LOCKS_REQUIRED(cs, cs_main);
void removeRecursive(const CTransaction &tx, MemPoolRemovalReason reason = MemPoolRemovalReason::UNKNOWN);
void removeForReorg(const CCoinsViewCache *pcoins, unsigned int nMemPoolHeight, int flags) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
@@ -594,7 +630,7 @@ public:
* for). Note: vHashesToUpdate should be the set of transactions from the
* disconnected block that have been accepted back into the mempool.
*/
- void UpdateTransactionsFromBlock(const std::vector<uint256> &vHashesToUpdate);
+ void UpdateTransactionsFromBlock(const std::vector<uint256>& vHashesToUpdate) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
/** Try to calculate all in-mempool ancestors of entry.
* (these are all calculated including the tx itself)
@@ -636,7 +672,7 @@ public:
*/
void GetTransactionAncestry(const uint256& txid, size_t& ancestors, size_t& descendants) const;
- unsigned long size()
+ unsigned long size() const
{
LOCK(cs);
return mapTx.size();
diff --git a/src/uint256.cpp b/src/uint256.cpp
index d9da668036..e3bc9712e8 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(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/strencodings.cpp b/src/util/strencodings.cpp
index 46146be66f..fedeeac39b 100644
--- a/src/util/strencodings.cpp
+++ b/src/util/strencodings.cpp
@@ -589,7 +589,7 @@ bool ParseHDKeypath(const std::string& keypath_str, std::vector<uint32_t>& keypa
void Downcase(std::string& str)
{
- std::transform(str.begin(), str.end(), str.begin(), [](unsigned char c){return ToLower(c);});
+ std::transform(str.begin(), str.end(), str.begin(), [](char c){return ToLower(c);});
}
std::string Capitalize(std::string str)
diff --git a/src/util/strencodings.h b/src/util/strencodings.h
index 7d16d7dcfd..e392055f27 100644
--- a/src/util/strencodings.h
+++ b/src/util/strencodings.h
@@ -15,10 +15,6 @@
#include <string>
#include <vector>
-#define BEGIN(a) ((char*)&(a))
-#define END(a) ((char*)&((&(a))[1]))
-#define UBEGIN(a) ((unsigned char*)&(a))
-#define UEND(a) ((unsigned char*)&((&(a))[1]))
#define ARRAYLEN(array) (sizeof(array)/sizeof((array)[0]))
/** Used by SanitizeString() */
@@ -212,7 +208,7 @@ NODISCARD bool ParseHDKeypath(const std::string& keypath_str, std::vector<uint32
* @return the lowercase equivalent of c; or the argument
* if no conversion is possible.
*/
-constexpr unsigned char ToLower(unsigned char c)
+constexpr char ToLower(char c)
{
return (c >= 'A' && c <= 'Z' ? (c - 'A') + 'a' : c);
}
@@ -233,7 +229,7 @@ void Downcase(std::string& str);
* @return the uppercase equivalent of c; or the argument
* if no conversion is possible.
*/
-constexpr unsigned char ToUpper(unsigned char c)
+constexpr char ToUpper(char c)
{
return (c >= 'a' && c <= 'z' ? (c - 'a') + 'A' : c);
}
diff --git a/src/util/system.cpp b/src/util/system.cpp
index 8e201ec590..7f2e9a3114 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
@@ -749,18 +749,17 @@ fs::path GetDefaultDataDir()
#endif
}
-static fs::path g_blocks_path_cached;
static fs::path g_blocks_path_cache_net_specific;
static fs::path pathCached;
static fs::path pathCachedNetSpecific;
static CCriticalSection csPathCached;
-const fs::path &GetBlocksDir(bool fNetSpecific)
+const fs::path &GetBlocksDir()
{
LOCK(csPathCached);
- fs::path &path = fNetSpecific ? g_blocks_path_cache_net_specific : g_blocks_path_cached;
+ fs::path &path = g_blocks_path_cache_net_specific;
// This can be called during exceptions by LogPrintf(), so we cache the
// value so we don't have to do memory allocations after that.
@@ -776,9 +775,8 @@ const fs::path &GetBlocksDir(bool fNetSpecific)
} else {
path = GetDataDir(false);
}
- if (fNetSpecific)
- path /= BaseParams().DataDir();
+ path /= BaseParams().DataDir();
path /= "blocks";
fs::create_directories(path);
return path;
@@ -822,7 +820,6 @@ void ClearDatadirCache()
pathCached = fs::path();
pathCachedNetSpecific = fs::path();
- g_blocks_path_cached = fs::path();
g_blocks_path_cache_net_specific = fs::path();
}
@@ -865,7 +862,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/util/system.h b/src/util/system.h
index dca32cc6fc..5932e55793 100644
--- a/src/util/system.h
+++ b/src/util/system.h
@@ -79,7 +79,8 @@ void ReleaseDirectoryLocks();
bool TryCreateDirectories(const fs::path& p);
fs::path GetDefaultDataDir();
-const fs::path &GetBlocksDir(bool fNetSpecific = true);
+// The blocks directory is always net specific.
+const fs::path &GetBlocksDir();
const fs::path &GetDataDir(bool fNetSpecific = true);
void ClearDatadirCache();
fs::path GetConfigFile(const std::string& confPath);
diff --git a/src/validation.cpp b/src/validation.cpp
index a18e449af6..6a26bf9baa 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -173,7 +173,7 @@ public:
CCoinsViewCache& view, const CChainParams& chainparams, bool fJustCheck = false) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
// Block disconnection on our pcoinsTip:
- bool DisconnectTip(CValidationState& state, const CChainParams& chainparams, DisconnectedBlockTransactions *disconnectpool);
+ bool DisconnectTip(CValidationState& state, const CChainParams& chainparams, DisconnectedBlockTransactions* disconnectpool) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
// Manual block validity manipulation:
bool PreciousBlock(CValidationState& state, const CChainParams& params, CBlockIndex* pindex) LOCKS_EXCLUDED(cs_main);
@@ -210,9 +210,17 @@ private:
bool RollforwardBlock(const CBlockIndex* pindex, CCoinsViewCache& inputs, const CChainParams& params) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
} g_chainstate;
-
-
-CCriticalSection cs_main;
+/**
+ * Mutex to guard access to validation specific variables, such as reading
+ * or changing the chainstate.
+ *
+ * This may also need to be locked when updating the transaction pool, e.g. on
+ * AcceptToMemoryPool. See CTxMemPool::cs comment for details.
+ *
+ * The transaction pool has a separate lock to allow reading from it and the
+ * chainstate at the same time.
+ */
+RecursiveMutex cs_main;
BlockMap& mapBlockIndex = g_chainstate.mapBlockIndex;
CChain& chainActive = g_chainstate.chainActive;
diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp
index 98e2abbd18..3677194a40 100644
--- a/src/wallet/db.cpp
+++ b/src/wallet/db.cpp
@@ -338,7 +338,7 @@ bool BerkeleyBatch::VerifyEnvironment(const fs::path& file_path, std::string& er
BerkeleyEnvironment* env = GetWalletEnv(file_path, walletFile);
fs::path walletDir = env->Directory();
- LogPrintf("Using BerkeleyDB version %s\n", DbEnv::version(0, 0, 0));
+ LogPrintf("Using BerkeleyDB version %s\n", DbEnv::version(nullptr, nullptr, nullptr));
LogPrintf("Using wallet %s\n", walletFile);
// Wallet file must be a plain filename without a directory
diff --git a/src/wallet/init.cpp b/src/wallet/init.cpp
index 14d811c6cd..87cd264c3d 100644
--- a/src/wallet/init.cpp
+++ b/src/wallet/init.cpp
@@ -242,7 +242,11 @@ void StopWallets()
void UnloadWallets()
{
- for (const std::shared_ptr<CWallet>& pwallet : GetWallets()) {
- RemoveWallet(pwallet);
+ auto wallets = GetWallets();
+ while (!wallets.empty()) {
+ auto wallet = wallets.back();
+ wallets.pop_back();
+ RemoveWallet(wallet);
+ UnloadWallet(std::move(wallet));
}
}
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index c1cdd0b2ee..39c17743ec 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;
}
};
@@ -2640,16 +2637,8 @@ static UniValue unloadwallet(const JSONRPCRequest& request)
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.
+ UnloadWallet(std::move(wallet));
return NullUniValue;
}
diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp
index 1ed1926af2..0db22cf6fe 100644
--- a/src/wallet/test/wallet_tests.cpp
+++ b/src/wallet/test/wallet_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2018 The Bitcoin Core developers
+// Copyright (c) 2012-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -47,7 +47,7 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
auto locked_chain = chain->lock();
- // Verify ScanForWalletTransactions accomodates a null start block.
+ // Verify ScanForWalletTransactions accommodates a null start block.
{
CWallet wallet(*chain, WalletLocation(), WalletDatabase::CreateDummy());
AddKey(wallet, coinbaseKey);
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 109f8e6da0..098055673b 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -82,13 +82,52 @@ std::shared_ptr<CWallet> GetWallet(const std::string& name)
return nullptr;
}
+static Mutex g_wallet_release_mutex;
+static std::condition_variable g_wallet_release_cv;
+static std::set<CWallet*> g_unloading_wallet_set;
+
// Custom deleter for shared_ptr<CWallet>.
static void ReleaseWallet(CWallet* wallet)
{
+ // Unregister and delete the wallet right after BlockUntilSyncedToCurrentChain
+ // so that it's in sync with the current chainstate.
wallet->WalletLogPrintf("Releasing wallet\n");
wallet->BlockUntilSyncedToCurrentChain();
wallet->Flush();
+ UnregisterValidationInterface(wallet);
delete wallet;
+ // Wallet is now released, notify UnloadWallet, if any.
+ {
+ LOCK(g_wallet_release_mutex);
+ if (g_unloading_wallet_set.erase(wallet) == 0) {
+ // UnloadWallet was not called for this wallet, all done.
+ return;
+ }
+ }
+ g_wallet_release_cv.notify_all();
+}
+
+void UnloadWallet(std::shared_ptr<CWallet>&& wallet)
+{
+ // Mark wallet for unloading.
+ CWallet* pwallet = wallet.get();
+ {
+ LOCK(g_wallet_release_mutex);
+ auto it = g_unloading_wallet_set.insert(pwallet);
+ assert(it.second);
+ }
+ // The wallet can be in use so it's not possible to explicitly unload here.
+ // Notify the unload intent so that all remaining shared pointers are
+ // released.
+ pwallet->NotifyUnload();
+ // Time to ditch our shared_ptr and wait for ReleaseWallet call.
+ wallet.reset();
+ {
+ WAIT_LOCK(g_wallet_release_mutex, lock);
+ while (g_unloading_wallet_set.count(pwallet) == 1) {
+ g_wallet_release_cv.wait(lock);
+ }
+ }
}
const uint32_t BIP32_HARDENED_KEY_LIMIT = 0x80000000;
@@ -2516,6 +2555,65 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nC
return true;
}
+static bool IsCurrentForAntiFeeSniping(interfaces::Chain::Lock& locked_chain)
+{
+ if (IsInitialBlockDownload()) {
+ return false;
+ }
+ constexpr int64_t MAX_ANTI_FEE_SNIPING_TIP_AGE = 8 * 60 * 60; // in seconds
+ if (chainActive.Tip()->GetBlockTime() < (GetTime() - MAX_ANTI_FEE_SNIPING_TIP_AGE)) {
+ return false;
+ }
+ return true;
+}
+
+/**
+ * Return a height-based locktime for new transactions (uses the height of the
+ * current chain tip unless we are not synced with the current chain
+ */
+static uint32_t GetLocktimeForNewTransaction(interfaces::Chain::Lock& locked_chain)
+{
+ uint32_t locktime;
+ // Discourage fee sniping.
+ //
+ // For a large miner the value of the transactions in the best block and
+ // the mempool can exceed the cost of deliberately attempting to mine two
+ // blocks to orphan the current best block. By setting nLockTime such that
+ // only the next block can include the transaction, we discourage this
+ // practice as the height restricted and limited blocksize gives miners
+ // considering fee sniping fewer options for pulling off this attack.
+ //
+ // A simple way to think about this is from the wallet's point of view we
+ // always want the blockchain to move forward. By setting nLockTime this
+ // way we're basically making the statement that we only want this
+ // transaction to appear in the next block; we don't want to potentially
+ // encourage reorgs by allowing transactions to appear at lower heights
+ // than the next block in forks of the best chain.
+ //
+ // Of course, the subsidy is high enough, and transaction volume low
+ // enough, that fee sniping isn't a problem yet, but by implementing a fix
+ // now we ensure code won't be written that makes assumptions about
+ // nLockTime that preclude a fix later.
+ if (IsCurrentForAntiFeeSniping(locked_chain)) {
+ locktime = chainActive.Height();
+
+ // Secondly occasionally randomly pick a nLockTime even further back, so
+ // that transactions that are delayed after signing for whatever reason,
+ // e.g. high-latency mix networks and some CoinJoin implementations, have
+ // better privacy.
+ if (GetRandInt(10) == 0)
+ locktime = std::max(0, (int)locktime - GetRandInt(100));
+ } else {
+ // If our chain is lagging behind, we can't discourage fee sniping nor help
+ // the privacy of high-latency transactions. To avoid leaking a potentially
+ // unique "nLockTime fingerprint", set nLockTime to a constant.
+ locktime = 0;
+ }
+ assert(locktime <= (unsigned int)chainActive.Height());
+ assert(locktime < LOCKTIME_THRESHOLD);
+ return locktime;
+}
+
OutputType CWallet::TransactionChangeType(OutputType change_type, const std::vector<CRecipient>& vecSend)
{
// If -changetype is specified, always use that change type.
@@ -2570,37 +2668,8 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std
CMutableTransaction txNew;
- // Discourage fee sniping.
- //
- // For a large miner the value of the transactions in the best block and
- // the mempool can exceed the cost of deliberately attempting to mine two
- // blocks to orphan the current best block. By setting nLockTime such that
- // only the next block can include the transaction, we discourage this
- // practice as the height restricted and limited blocksize gives miners
- // considering fee sniping fewer options for pulling off this attack.
- //
- // A simple way to think about this is from the wallet's point of view we
- // always want the blockchain to move forward. By setting nLockTime this
- // way we're basically making the statement that we only want this
- // transaction to appear in the next block; we don't want to potentially
- // encourage reorgs by allowing transactions to appear at lower heights
- // than the next block in forks of the best chain.
- //
- // Of course, the subsidy is high enough, and transaction volume low
- // enough, that fee sniping isn't a problem yet, but by implementing a fix
- // now we ensure code won't be written that makes assumptions about
- // nLockTime that preclude a fix later.
- txNew.nLockTime = chainActive.Height();
-
- // Secondly occasionally randomly pick a nLockTime even further back, so
- // that transactions that are delayed after signing for whatever reason,
- // e.g. high-latency mix networks and some CoinJoin implementations, have
- // better privacy.
- if (GetRandInt(10) == 0)
- txNew.nLockTime = std::max(0, (int)txNew.nLockTime - GetRandInt(100));
+ txNew.nLockTime = GetLocktimeForNewTransaction(locked_chain);
- assert(txNew.nLockTime <= (unsigned int)chainActive.Height());
- assert(txNew.nLockTime < LOCKTIME_THRESHOLD);
FeeCalculation feeCalc;
CAmount nFeeNeeded;
int nBytes;
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index 95a2c833f8..6872fbad2d 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -54,6 +54,13 @@ void StopWallets();
//! Close all wallets.
void UnloadWallets();
+//! Explicitly unload and delete the wallet.
+// Blocks the current thread after signaling the unload intent so that all
+// wallet clients release the wallet.
+// Note that, when blocking is not required, the wallet is implicitly unloaded
+// by the shared pointer deleter.
+void UnloadWallet(std::shared_ptr<CWallet>&& wallet);
+
bool AddWallet(const std::shared_ptr<CWallet>& wallet);
bool RemoveWallet(const std::shared_ptr<CWallet>& wallet);
bool HasWallets();
@@ -770,6 +777,8 @@ public:
~CWallet()
{
+ // Should not have slots connected at this point.
+ assert(NotifyUnload.empty());
delete encrypted_batch;
encrypted_batch = nullptr;
}
@@ -1178,18 +1187,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;
}
};