From 0aee4a132b6d3be276503c517cb2b7f07d774bf6 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Fri, 14 Apr 2017 16:29:57 -0400 Subject: [PATCH 1/9] Check interruptNet during dnsseed lookups --- src/net.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/net.cpp b/src/net.cpp index 5593f81ef..2fca99474 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1579,6 +1579,9 @@ void CConnman::ThreadDNSAddressSeed() LogPrintf("Loading addresses from DNS seeds (could take a while)\n"); BOOST_FOREACH(const CDNSSeedData &seed, vSeeds) { + if (interruptNet) { + return; + } if (HaveNameProxy()) { AddOneShot(seed.host); } else { @@ -1596,6 +1599,9 @@ void CConnman::ThreadDNSAddressSeed() found++; } } + if (interruptNet) { + return; + } // TODO: The seed name resolve may fail, yielding an IP of [::], which results in // addrman assigning the same source to results from different seeds. // This should switch to a hard-coded stable dummy IP for each seed name, so that the From 1e936d7e8760de230377f4e4af5eb68368f1f550 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Wed, 19 Apr 2017 18:45:11 +0200 Subject: [PATCH 2/9] Reduce cs_main locks during modal overlay by adding an atomic cache --- src/qt/clientmodel.cpp | 35 +++++++++++++++++++++++++---------- src/qt/clientmodel.h | 8 ++++++-- 2 files changed, 31 insertions(+), 12 deletions(-) diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index bb10e4942..9a8af01a3 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -36,6 +36,8 @@ ClientModel::ClientModel(OptionsModel *_optionsModel, QObject *parent) : banTableModel(0), pollTimer(0) { + cachedBestHeaderHeight = -1; + cachedBestHeaderTime = -1; peerTableModel = new PeerTableModel(this); banTableModel = new BanTableModel(this); pollTimer = new QTimer(this); @@ -72,20 +74,28 @@ int ClientModel::getNumBlocks() const return chainActive.Height(); } -int ClientModel::getHeaderTipHeight() const +int ClientModel::getHeaderTipHeight() { - LOCK(cs_main); - if (!pindexBestHeader) - return 0; - return pindexBestHeader->nHeight; + if (cachedBestHeaderHeight == -1) { + // make sure we initially populate the cache via a cs_main lock + // otherwise we need to wait for a tip update + LOCK(cs_main); + if (pindexBestHeader) { + cachedBestHeaderHeight = pindexBestHeader->nHeight; + } + } + return cachedBestHeaderHeight; } -int64_t ClientModel::getHeaderTipTime() const +int64_t ClientModel::getHeaderTipTime() { - LOCK(cs_main); - if (!pindexBestHeader) - return 0; - return pindexBestHeader->GetBlockTime(); + if (cachedBestHeaderTime == -1) { + LOCK(cs_main); + if (pindexBestHeader) { + cachedBestHeaderTime = pindexBestHeader->GetBlockTime(); + } + } + return cachedBestHeaderTime; } quint64 ClientModel::getTotalBytesRecv() const @@ -283,6 +293,11 @@ static void BlockTipChanged(ClientModel *clientmodel, bool initialSync, const CB int64_t& nLastUpdateNotification = fHeader ? nLastHeaderTipUpdateNotification : nLastBlockTipUpdateNotification; + if (fHeader) { + // cache best headers time and height to reduce future cs_main locks + clientmodel->cachedBestHeaderHeight = pIndex->nHeight; + clientmodel->cachedBestHeaderTime = pIndex->GetBlockTime(); + } // if we are in-sync, update the UI regardless of last update time if (!initialSync || now - nLastUpdateNotification > MODEL_UPDATE_DELAY) { //pass a async signal to the UI thread diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h index 2c10e633b..6f7077dad 100644 --- a/src/qt/clientmodel.h +++ b/src/qt/clientmodel.h @@ -51,8 +51,8 @@ public: //! Return number of connections, default is in- and outbound (total) int getNumConnections(unsigned int flags = CONNECTIONS_ALL) const; int getNumBlocks() const; - int getHeaderTipHeight() const; - int64_t getHeaderTipTime() const; + int getHeaderTipHeight(); + int64_t getHeaderTipTime(); //! Return number of transactions in the mempool long getMempoolSize() const; //! Return the dynamic memory usage of the mempool @@ -81,6 +81,10 @@ public: QString formatClientStartupTime() const; QString dataDir() const; + // caches for the best header + std::atomic cachedBestHeaderHeight; + std::atomic cachedBestHeaderTime; + private: OptionsModel *optionsModel; PeerTableModel *peerTableModel; From 9ac40e853c868b4f7294b708104dc65d2b45c2a2 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Wed, 19 Apr 2017 20:54:30 +0200 Subject: [PATCH 3/9] Update the remaining blocks left in modaloverlay at init. --- src/qt/bitcoingui.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index be79a6799..5c26baef9 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -478,6 +478,7 @@ void BitcoinGUI::setClientModel(ClientModel *_clientModel) connect(_clientModel, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int))); connect(_clientModel, SIGNAL(networkActiveChanged(bool)), this, SLOT(setNetworkActive(bool))); + modalOverlay->setKnownBestHeight(_clientModel->getHeaderTipHeight(), QDateTime::fromTime_t(_clientModel->getHeaderTipTime())); setNumBlocks(_clientModel->getNumBlocks(), _clientModel->getLastBlockDate(), _clientModel->getVerificationProgress(NULL), false); connect(_clientModel, SIGNAL(numBlocksChanged(int,QDateTime,double,bool)), this, SLOT(setNumBlocks(int,QDateTime,double,bool))); @@ -505,8 +506,6 @@ void BitcoinGUI::setClientModel(ClientModel *_clientModel) // initialize the disable state of the tray icon with the current value in the model. setTrayIconVisible(optionsModel->getHideTrayIcon()); } - - modalOverlay->setKnownBestHeight(clientModel->getHeaderTipHeight(), QDateTime::fromTime_t(clientModel->getHeaderTipTime())); } else { // Disable possibility to show main window via action toggleHideAction->setEnabled(false); From 7da133772dd18b44316f7f12567e321eceec8838 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Thu, 20 Apr 2017 09:51:05 +0200 Subject: [PATCH 4/9] Declare headers height/time cache mutable, re-set the methods const --- src/qt/clientmodel.cpp | 4 ++-- src/qt/clientmodel.h | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 9a8af01a3..cbc6ca129 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -74,7 +74,7 @@ int ClientModel::getNumBlocks() const return chainActive.Height(); } -int ClientModel::getHeaderTipHeight() +int ClientModel::getHeaderTipHeight() const { if (cachedBestHeaderHeight == -1) { // make sure we initially populate the cache via a cs_main lock @@ -87,7 +87,7 @@ int ClientModel::getHeaderTipHeight() return cachedBestHeaderHeight; } -int64_t ClientModel::getHeaderTipTime() +int64_t ClientModel::getHeaderTipTime() const { if (cachedBestHeaderTime == -1) { LOCK(cs_main); diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h index 6f7077dad..0e6b34fbf 100644 --- a/src/qt/clientmodel.h +++ b/src/qt/clientmodel.h @@ -51,8 +51,8 @@ public: //! Return number of connections, default is in- and outbound (total) int getNumConnections(unsigned int flags = CONNECTIONS_ALL) const; int getNumBlocks() const; - int getHeaderTipHeight(); - int64_t getHeaderTipTime(); + int getHeaderTipHeight() const; + int64_t getHeaderTipTime() const; //! Return number of transactions in the mempool long getMempoolSize() const; //! Return the dynamic memory usage of the mempool @@ -82,8 +82,8 @@ public: QString dataDir() const; // caches for the best header - std::atomic cachedBestHeaderHeight; - std::atomic cachedBestHeaderTime; + mutable std::atomic cachedBestHeaderHeight; + mutable std::atomic cachedBestHeaderTime; private: OptionsModel *optionsModel; From 222f3775cfee505a8f5cdb7f0e12af38998bd3fc Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Thu, 20 Apr 2017 09:51:41 +0200 Subject: [PATCH 5/9] Set both time/height header caches at the same time --- src/qt/clientmodel.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index cbc6ca129..20d468797 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -82,6 +82,7 @@ int ClientModel::getHeaderTipHeight() const LOCK(cs_main); if (pindexBestHeader) { cachedBestHeaderHeight = pindexBestHeader->nHeight; + cachedBestHeaderTime = pindexBestHeader->GetBlockTime(); } } return cachedBestHeaderHeight; @@ -92,6 +93,7 @@ int64_t ClientModel::getHeaderTipTime() const if (cachedBestHeaderTime == -1) { LOCK(cs_main); if (pindexBestHeader) { + cachedBestHeaderHeight = pindexBestHeader->nHeight; cachedBestHeaderTime = pindexBestHeader->GetBlockTime(); } } From 4bc99c3b2854f94bb42ca6ecc7a31980498857ac Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Thu, 20 Apr 2017 13:29:12 +0200 Subject: [PATCH 6/9] Add missing header in clientmodel.h --- src/qt/clientmodel.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h index 0e6b34fbf..4c92e2144 100644 --- a/src/qt/clientmodel.h +++ b/src/qt/clientmodel.h @@ -8,6 +8,8 @@ #include #include +#include + class AddressTableModel; class BanTableModel; class OptionsModel; From 3d395d6815e36850db0af4153756352bcc9c356a Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Tue, 18 Apr 2017 19:12:17 -0400 Subject: [PATCH 7/9] build: remove wonky auto top-level convenience targets These were meant to help build subdir targets from the top builddir, but cause infinite recursion when going the other way. If anyone actually uses these, we can add back specific targets. --- Makefile.am | 3 --- 1 file changed, 3 deletions(-) diff --git a/Makefile.am b/Makefile.am index 6a8c1b761..4484bafc5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -76,9 +76,6 @@ $(BITCOIN_WIN_INSTALLER): all-recursive echo error: could not build $@ @echo built $@ -$(if $(findstring src/,$(MAKECMDGOALS)),$(MAKECMDGOALS), none): FORCE - $(MAKE) -C src $(patsubst src/%,%,$@) - $(OSX_APP)/Contents/PkgInfo: $(MKDIR_P) $(@D) @echo "APPL????" > $@ From ae479bc45bfdfb33e7f1293391db5b9f81b3ce17 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Tue, 18 Apr 2017 19:14:22 -0400 Subject: [PATCH 8/9] build: fix bitcoin-config.h regeneration after touching build files This was a long-standing and annoying problem. If autogen.sh was not manually run after touching configure.ac, bitcoin-config.h would not be properly regenerated. This causes very subtle problems when configure appears to enable a new value, but it does not end up reflected in the build. --- src/Makefile.am | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Makefile.am b/src/Makefile.am index e8d22313d..76dbbced6 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -457,6 +457,14 @@ DISTCLEANFILES = obj/build.h EXTRA_DIST = $(CTAES_DIST) + +config/bitcoin-config.h: config/stamp-h1 + @$(MAKE) -C $(top_builddir) $(subdir)/$(@) +config/stamp-h1: $(top_srcdir)/$(subdir)/config/bitcoin-config.h.in $(top_builddir)/config.status + $(AM_V_at)$(MAKE) -C $(top_builddir) $(subdir)/$(@) +$(top_srcdir)/$(subdir)/config/bitcoin-config.h.in: $(am__configure_deps) + $(AM_V_at)$(MAKE) -C $(top_srcdir) $(subdir)/config/bitcoin-config.h.in + clean-local: -$(MAKE) -C secp256k1 clean -$(MAKE) -C univalue clean From 18476423fba5d2cadd2b0973e425a6ebedeb66a4 Mon Sep 17 00:00:00 2001 From: Gregory Sanders Date: Fri, 28 Apr 2017 17:22:37 -0400 Subject: [PATCH 9/9] [Wallet] unset change position when there is no change on exact match --- qa/rpc-tests/fundrawtransaction.py | 5 +++++ src/wallet/wallet.cpp | 5 +++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/qa/rpc-tests/fundrawtransaction.py b/qa/rpc-tests/fundrawtransaction.py index 8d2bc73c0..cdea390e2 100755 --- a/qa/rpc-tests/fundrawtransaction.py +++ b/qa/rpc-tests/fundrawtransaction.py @@ -54,6 +54,11 @@ class RawTransactionsTest(BitcoinTestFramework): self.nodes[0].generate(121) self.sync_all() + # ensure that setting changePosition in fundraw with an exact match is handled properly + rawmatch = self.nodes[2].createrawtransaction([], {self.nodes[2].getnewaddress():50}) + rawmatch = self.nodes[2].fundrawtransaction(rawmatch, {"changePosition":1, "subtractFeeFromOutputs":[0]}) + assert_equal(rawmatch["changepos"], -1) + watchonly_address = self.nodes[0].getnewaddress() watchonly_pubkey = self.nodes[0].validateaddress(watchonly_address)["pubkey"] watchonly_amount = Decimal(200) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 1b59c3cd8..3e93a56d5 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2587,9 +2587,10 @@ bool CWallet::CreateTransaction(const vector& vecSend, CWalletTx& wt vector::iterator position = txNew.vout.begin()+nChangePosInOut; txNew.vout.insert(position, newTxOut); } - } - else + } else { reservekey.ReturnKey(); + nChangePosInOut = -1; + } // Fill vin //