diff options
| -rw-r--r-- | Makefile.am | 3 | ||||
| -rw-r--r-- | configure.ac | 2 | ||||
| -rw-r--r-- | depends/packages/miniupnpc.mk | 4 | ||||
| -rw-r--r-- | doc/Doxyfile | 2 | ||||
| -rw-r--r-- | doc/README.md | 2 | ||||
| -rw-r--r-- | doc/README_windows.txt | 2 | ||||
| -rw-r--r-- | doc/build-unix.md | 6 | ||||
| -rw-r--r-- | doc/release-notes.md | 102 | ||||
| -rw-r--r-- | doc/release-notes/release-notes-0.14.1.md | 143 | ||||
| -rwxr-xr-x | qa/rpc-tests/fundrawtransaction.py | 5 | ||||
| -rw-r--r-- | src/Makefile.am | 8 | ||||
| -rw-r--r-- | src/clientversion.h | 2 | ||||
| -rw-r--r-- | src/net.cpp | 29 | ||||
| -rw-r--r-- | src/qt/bitcoingui.cpp | 3 | ||||
| -rw-r--r-- | src/qt/clientmodel.cpp | 33 | ||||
| -rw-r--r-- | src/qt/clientmodel.h | 6 | ||||
| -rw-r--r-- | src/wallet/rpcdump.cpp | 11 | ||||
| -rw-r--r-- | src/wallet/test/wallet_tests.cpp | 62 | ||||
| -rw-r--r-- | src/wallet/wallet.cpp | 5 |
19 files changed, 319 insertions, 111 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????" > $@ diff --git a/configure.ac b/configure.ac index a9156c348..0894c7197 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N) AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 0) define(_CLIENT_VERSION_MINOR, 14) -define(_CLIENT_VERSION_REVISION, 1) +define(_CLIENT_VERSION_REVISION, 2) define(_CLIENT_VERSION_BUILD, 0) define(_CLIENT_VERSION_IS_RELEASE, true) define(_COPYRIGHT_YEAR, 2017) diff --git a/depends/packages/miniupnpc.mk b/depends/packages/miniupnpc.mk index e34cf7be2..1bb8cb5d2 100644 --- a/depends/packages/miniupnpc.mk +++ b/depends/packages/miniupnpc.mk @@ -1,8 +1,8 @@ package=miniupnpc -$(package)_version=2.0 +$(package)_version=2.0.20170509 $(package)_download_path=http://miniupnp.free.fr/files $(package)_file_name=$(package)-$($(package)_version).tar.gz -$(package)_sha256_hash=d434ceb8986efbe199c5ca53f90ed53eab290b1e6d0530b717eb6fa49d61f93b +$(package)_sha256_hash=d3c368627f5cdfb66d3ebd64ca39ba54d6ff14a61966dbecb8dd296b7039f16a define $(package)_set_vars $(package)_build_opts=CC="$($(package)_cc)" diff --git a/doc/Doxyfile b/doc/Doxyfile index 2146a0022..a76918df7 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -38,7 +38,7 @@ PROJECT_NAME = "Bitcoin Core" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 0.14.1 +PROJECT_NUMBER = 0.14.2 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/doc/README.md b/doc/README.md index 52a4cc0bf..81ded9e10 100644 --- a/doc/README.md +++ b/doc/README.md @@ -1,4 +1,4 @@ -Bitcoin Core 0.14.1 +Bitcoin Core 0.14.2 ===================== Setup diff --git a/doc/README_windows.txt b/doc/README_windows.txt index 5b9aaef57..ec365178a 100644 --- a/doc/README_windows.txt +++ b/doc/README_windows.txt @@ -1,4 +1,4 @@ -Bitcoin Core 0.14.1
+Bitcoin Core 0.14.2
=====================
Intro
diff --git a/doc/build-unix.md b/doc/build-unix.md index 31a88a1b1..b7eae2a63 100644 --- a/doc/build-unix.md +++ b/doc/build-unix.md @@ -321,8 +321,10 @@ Clang is installed by default as `cc` compiler, this makes it easier to get started than on [OpenBSD](build-openbsd.md). Installing dependencies: pkg install autoconf automake libtool pkgconf - pkg install boost-libs openssl libevent2 + pkg install boost-libs openssl libevent + pkg install gmake +You need to use GNU make (`gmake`) instead of `make`. (`libressl` instead of `openssl` will also work) For the wallet (optional): @@ -338,7 +340,7 @@ Then build using: ./autogen.sh ./configure --with-incompatible-bdb BDB_CFLAGS="-I/usr/local/include/db5" BDB_LIBS="-L/usr/local/lib -ldb_cxx-5" - make + gmake *Note on debugging*: The version of `gdb` installed by default is [ancient and considered harmful](https://wiki.freebsd.org/GdbRetirement). It is not suitable for debugging a multi-threaded C++ program, not even for getting backtraces. Please install the package `gdb` and diff --git a/doc/release-notes.md b/doc/release-notes.md index 4b5e3c56e..1fbade55a 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -1,6 +1,6 @@ -Bitcoin Core version 0.14.1 is now available from: +Bitcoin Core version 0.14.2 is now available from: - <https://bitcoin.org/bin/bitcoin-core-0.14.1/> + <https://bitcoin.org/bin/bitcoin-core-0.14.2/> This is a new minor version release, including various bugfixes and performance improvements, as well as updated translations. @@ -30,50 +30,12 @@ frequently tested on them. Notable changes =============== -RPC changes ------------ +miniupnp CVE-2017-8798 +---------------------------- -- The first positional argument of `createrawtransaction` was renamed from - `transactions` to `inputs`. +[todo] -- The argument of `disconnectnode` was renamed from `node` to `address`. - -These interface changes break compatibility with 0.14.0, when the named -arguments functionality, introduced in 0.14.0, is used. Client software -using these calls with named arguments needs to be updated. - -Mining ------- - -Getblocktemplate sets the segwit version bit even when the downstream -client has not been updated to include the segwit commitment. Ability -to enforce the rule is the only required criteria for safe activation, -but previously signaling was only requested if the miner could include -transactions in order to avoid a potential outcome where segwit would -activate at a time when no segwit transactions could be included. -Since many miners are now including the segwit commitment this concern -no longer applies. - -UTXO memory accounting ----------------------- - -Memory usage for the UTXO cache is being calculated more accurately, so that -the configured limit (`-dbcache`) will be respected when memory usage peaks -during cache flushes. The memory accounting in prior releases is estimated to -only account for half the actual peak utilization. - -The default `-dbcache` has also been changed in this release to 450MiB. Users -who currently set `-dbcache` to a high value (e.g. to keep the UTXO more fully -cached in memory) should consider increasing this setting in order to achieve -the same cache performance as prior releases. Users on low-memory systems -(such as systems with 1GB or less) should consider specifying a lower value for -this parameter. - -Additional information relating to running on low-memory systems can be found -here: -[reducing-bitcoind-memory-usage.md](https://gist.github.com/laanwj/efe29c7661ce9b6620a7). - -0.14.1 Change log +0.14.2 Change log ================= Detailed release notes follow. This overview includes changes that affect @@ -82,38 +44,25 @@ the code changes and accompanying discussion, both the pull request and git merge commit are mentioned. ### RPC and other APIs -- #10084 `142fbb2` Rename first named arg of createrawtransaction (MarcoFalke) -- #10139 `f15268d` Remove auth cookie on shutdown (practicalswift) -- #10146 `2fea10a` Better error handling for submitblock (rawodb, gmaxwell) -- #10144 `d947afc` Prioritisetransaction wasn't always updating ancestor fee (sdaftuar) -- #10204 `3c79602` Rename disconnectnode argument (jnewbery) - -### Block and transaction handling -- #10126 `0b5e162` Compensate for memory peak at flush time (sipa) -- #9912 `fc3d7db` Optimize GetWitnessHash() for non-segwit transactions (sdaftuar) -- #10133 `ab864d3` Clean up calculations of pcoinsTip memory usage (morcos) +- #10410 `321419b` Fix importwallet edge case rescan bug (ryanofsky) ### P2P protocol and network code -- #9953/#10013 `d2548a4` Fix shutdown hang with >= 8 -addnodes set (TheBlueMatt) -- #10176 `30fa231` net: gracefully handle NodeId wrapping (theuni) +- #10424 `37a8fc5` Populate services in GetLocalAddress (morcos) +- #10441 `9e3ad50` net: only enforce expected services for half of outgoing connections (theuni) ### Build system -- #9973 `e9611d1` depends: fix zlib build on osx (theuni) - -### GUI -- #10060 `ddc2dd1` Ensure an item exists on the rpcconsole stack before adding (achow101) +- #10414 `ffb0c4b` [depends] miniupnpc 2.0.20170509 (fanquake) +- #10228 `ae479bc` Regenerate bitcoin-config.h as necessary (theuni) -### Mining -- #9955/#10006 `569596c` Don't require segwit in getblocktemplate for segwit signalling or mining (sdaftuar) -- #9959/#10127 `b5c3440` Prevent slowdown in CreateNewBlock on large mempools (sdaftuar) +### Miscellaneous +- #10245 `44a17f2` Minor fix in build documentation for FreeBSD 11 (shigeya) +- #10215 `0aee4a1` Check interruptNet during dnsseed lookups (TheBlueMatt) -### Tests and QA -- #10157 `55f641c` Fix the `mempool_packages.py` test (sdaftuar) +### GUI +- #10231 `1e936d7` Reduce a significant cs_main lock freeze (jonasschnelli) -### Miscellaneous -- #10037 `4d8e660` Trivial: Fix typo in help getrawtransaction RPC (keystrike) -- #10120 `e4c9a90` util: Work around (virtual) memory exhaustion on 32-bit w/ glibc (laanwj) -- #10130 `ecc5232` bitcoin-tx input verification (awemany, jnewbery) +### Wallet +- #10294 `1847642` Unset change position when there is no change (instagibbs) Credits ======= @@ -121,18 +70,13 @@ Credits Thanks to everyone who directly contributed to this release: - Alex Morcos -- Andrew Chow -- Awemany - Cory Fields -- Gregory Maxwell -- James Evans -- John Newbery -- MarcoFalke +- fanquake +- Gregory Sanders +- Jonas Schnelli - Matt Corallo -- Pieter Wuille -- practicalswift -- rawodb -- Suhas Daftuar +- Russell Yanofsky +- Shigeya Suzuki - Wladimir J. van der Laan As well as everyone that helped translating on [Transifex](https://www.transifex.com/projects/p/bitcoin/). diff --git a/doc/release-notes/release-notes-0.14.1.md b/doc/release-notes/release-notes-0.14.1.md new file mode 100644 index 000000000..ef072afd4 --- /dev/null +++ b/doc/release-notes/release-notes-0.14.1.md @@ -0,0 +1,143 @@ +Bitcoin Core version 0.14.1 is now available from: + + <https://bitcoin.org/bin/bitcoin-core-0.14.1/> + +This is a new minor version release, including various bugfixes and +performance improvements, as well as updated translations. + +Please report bugs using the issue tracker at github: + + <https://github.com/bitcoin/bitcoin/issues> + +To receive security and update notifications, please subscribe to: + + <https://bitcoincore.org/en/list/announcements/join/> + +Compatibility +============== + +Bitcoin Core is extensively tested on multiple operating systems using +the Linux kernel, macOS 10.8+, and Windows Vista and later. + +Microsoft ended support for Windows XP on [April 8th, 2014](https://www.microsoft.com/en-us/WindowsForBusiness/end-of-xp-support), +No attempt is made to prevent installing or running the software on Windows XP, you +can still do so at your own risk but be aware that there are known instabilities and issues. +Please do not report issues about Windows XP to the issue tracker. + +Bitcoin Core should also work on most other Unix-like systems but is not +frequently tested on them. + +Notable changes +=============== + +RPC changes +----------- + +- The first positional argument of `createrawtransaction` was renamed from + `transactions` to `inputs`. + +- The argument of `disconnectnode` was renamed from `node` to `address`. + +These interface changes break compatibility with 0.14.0, when the named +arguments functionality, introduced in 0.14.0, is used. Client software +using these calls with named arguments needs to be updated. + +Mining +------ + +In previous versions, getblocktemplate required segwit support from downstream +clients/miners once the feature activated on the network. In this version, it +now supports non-segwit clients even after activation, by removing all segwit +transactions from the returned block template. This allows non-segwit miners to +continue functioning correctly even after segwit has activated. + +Due to the limitations in previous versions, getblocktemplate also recommended +non-segwit clients to not signal for the segwit version-bit. Since this is no +longer an issue, getblocktemplate now always recommends signalling segwit for +all miners. This is safe because ability to enforce the rule is the only +required criteria for safe activation, not actually producing segwit-enabled +blocks. + +UTXO memory accounting +---------------------- + +Memory usage for the UTXO cache is being calculated more accurately, so that +the configured limit (`-dbcache`) will be respected when memory usage peaks +during cache flushes. The memory accounting in prior releases is estimated to +only account for half the actual peak utilization. + +The default `-dbcache` has also been changed in this release to 450MiB. Users +who currently set `-dbcache` to a high value (e.g. to keep the UTXO more fully +cached in memory) should consider increasing this setting in order to achieve +the same cache performance as prior releases. Users on low-memory systems +(such as systems with 1GB or less) should consider specifying a lower value for +this parameter. + +Additional information relating to running on low-memory systems can be found +here: +[reducing-bitcoind-memory-usage.md](https://gist.github.com/laanwj/efe29c7661ce9b6620a7). + +0.14.1 Change log +================= + +Detailed release notes follow. This overview includes changes that affect +behavior, not code moves, refactors and string updates. For convenience in locating +the code changes and accompanying discussion, both the pull request and +git merge commit are mentioned. + +### RPC and other APIs +- #10084 `142fbb2` Rename first named arg of createrawtransaction (MarcoFalke) +- #10139 `f15268d` Remove auth cookie on shutdown (practicalswift) +- #10146 `2fea10a` Better error handling for submitblock (rawodb, gmaxwell) +- #10144 `d947afc` Prioritisetransaction wasn't always updating ancestor fee (sdaftuar) +- #10204 `3c79602` Rename disconnectnode argument (jnewbery) + +### Block and transaction handling +- #10126 `0b5e162` Compensate for memory peak at flush time (sipa) +- #9912 `fc3d7db` Optimize GetWitnessHash() for non-segwit transactions (sdaftuar) +- #10133 `ab864d3` Clean up calculations of pcoinsTip memory usage (morcos) + +### P2P protocol and network code +- #9953/#10013 `d2548a4` Fix shutdown hang with >= 8 -addnodes set (TheBlueMatt) +- #10176 `30fa231` net: gracefully handle NodeId wrapping (theuni) + +### Build system +- #9973 `e9611d1` depends: fix zlib build on osx (theuni) + +### GUI +- #10060 `ddc2dd1` Ensure an item exists on the rpcconsole stack before adding (achow101) + +### Mining +- #9955/#10006 `569596c` Don't require segwit in getblocktemplate for segwit signalling or mining (sdaftuar) +- #9959/#10127 `b5c3440` Prevent slowdown in CreateNewBlock on large mempools (sdaftuar) + +### Tests and QA +- #10157 `55f641c` Fix the `mempool_packages.py` test (sdaftuar) + +### Miscellaneous +- #10037 `4d8e660` Trivial: Fix typo in help getrawtransaction RPC (keystrike) +- #10120 `e4c9a90` util: Work around (virtual) memory exhaustion on 32-bit w/ glibc (laanwj) +- #10130 `ecc5232` bitcoin-tx input verification (awemany, jnewbery) + +Credits +======= + +Thanks to everyone who directly contributed to this release: + +- Alex Morcos +- Andrew Chow +- Awemany +- Cory Fields +- Gregory Maxwell +- James Evans +- John Newbery +- MarcoFalke +- Matt Corallo +- Pieter Wuille +- practicalswift +- rawodb +- Suhas Daftuar +- Wladimir J. van der Laan + +As well as everyone that helped translating on [Transifex](https://www.transifex.com/projects/p/bitcoin/). + 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/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 diff --git a/src/clientversion.h b/src/clientversion.h index aa46955da..2a6c55cf9 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -16,7 +16,7 @@ //! These need to be macros, as clientversion.cpp's and bitcoin*-res.rc's voodoo requires it #define CLIENT_VERSION_MAJOR 0 #define CLIENT_VERSION_MINOR 14 -#define CLIENT_VERSION_REVISION 1 +#define CLIENT_VERSION_REVISION 2 #define CLIENT_VERSION_BUILD 0 //! Set to true for release, false for prerelease or test build diff --git a/src/net.cpp b/src/net.cpp index 03c8e5ecc..1752c7707 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -143,7 +143,7 @@ static std::vector<CAddress> convertSeed6(const std::vector<SeedSpec6> &vSeedsIn // one by discovery. CAddress GetLocalAddress(const CNetAddr *paddrPeer, ServiceFlags nLocalServices) { - CAddress ret(CService(CNetAddr(),GetListenPort()), NODE_NONE); + CAddress ret(CService(CNetAddr(),GetListenPort()), nLocalServices); CService addr; if (GetLocal(addr, paddrPeer)) { @@ -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 @@ -1716,11 +1722,17 @@ void CConnman::ThreadOpenConnections() // Only connect out to one peer per network group (/16 for IPv4). // Do this here so we don't have to critsect vNodes inside mapAddresses critsect. int nOutbound = 0; + int nOutboundRelevant = 0; std::set<std::vector<unsigned char> > setConnected; { LOCK(cs_vNodes); BOOST_FOREACH(CNode* pnode, vNodes) { if (!pnode->fInbound && !pnode->fAddnode) { + + // Count the peers that have all relevant services + if (pnode->fSuccessfullyConnected && !pnode->fFeeler && ((pnode->nServices & nRelevantServices) == nRelevantServices)) { + nOutboundRelevant++; + } // Netgroups for inbound and addnode peers are not excluded because our goal here // is to not use multiple of our limited outbound slots on a single netgroup // but inbound and addnode peers do not use our outbound slots. Inbound peers @@ -1784,14 +1796,27 @@ void CConnman::ThreadOpenConnections() continue; // only consider nodes missing relevant services after 40 failed attempts and only if less than half the outbound are up. - if ((addr.nServices & nRelevantServices) != nRelevantServices && (nTries < 40 || nOutbound >= (nMaxOutbound >> 1))) + ServiceFlags nRequiredServices = nRelevantServices; + if (nTries >= 40 && nOutbound < (nMaxOutbound >> 1)) { + nRequiredServices = REQUIRED_SERVICES; + } + + if ((addr.nServices & nRequiredServices) != nRequiredServices) { continue; + } // do not allow non-default ports, unless after 50 invalid addresses selected already if (addr.GetPort() != Params().GetDefaultPort() && nTries < 50) continue; addrConnect = addr; + + // regardless of the services assumed to be available, only require the minimum if half or more outbound have relevant services + if (nOutboundRelevant >= (nMaxOutbound >> 1)) { + addrConnect.nServices = REQUIRED_SERVICES; + } else { + addrConnect.nServices = nRequiredServices; + } break; } 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); diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index bb10e4942..20d468797 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); @@ -74,18 +76,28 @@ int ClientModel::getNumBlocks() const int ClientModel::getHeaderTipHeight() const { - 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; + cachedBestHeaderTime = pindexBestHeader->GetBlockTime(); + } + } + return cachedBestHeaderHeight; } int64_t ClientModel::getHeaderTipTime() const { - LOCK(cs_main); - if (!pindexBestHeader) - return 0; - return pindexBestHeader->GetBlockTime(); + if (cachedBestHeaderTime == -1) { + LOCK(cs_main); + if (pindexBestHeader) { + cachedBestHeaderHeight = pindexBestHeader->nHeight; + cachedBestHeaderTime = pindexBestHeader->GetBlockTime(); + } + } + return cachedBestHeaderTime; } quint64 ClientModel::getTotalBytesRecv() const @@ -283,6 +295,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..4c92e2144 100644 --- a/src/qt/clientmodel.h +++ b/src/qt/clientmodel.h @@ -8,6 +8,8 @@ #include <QObject> #include <QDateTime> +#include <atomic> + class AddressTableModel; class BanTableModel; class OptionsModel; @@ -81,6 +83,10 @@ public: QString formatClientStartupTime() const; QString dataDir() const; + // caches for the best header + mutable std::atomic<int> cachedBestHeaderHeight; + mutable std::atomic<int64_t> cachedBestHeaderTime; + private: OptionsModel *optionsModel; PeerTableModel *peerTableModel; diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 20a3cbda1..cd6ec207f 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -96,6 +96,8 @@ UniValue importprivkey(const JSONRPCRequest& request) + HelpExampleCli("importprivkey", "\"mykey\"") + "\nImport using a label and without rescan\n" + HelpExampleCli("importprivkey", "\"mykey\" \"testing\" false") + + "\nImport using default blank label and without rescan\n" + + HelpExampleCli("importprivkey", "\"mykey\" \"\" false") + "\nAs a JSON-RPC call\n" + HelpExampleRpc("importprivkey", "\"mykey\", \"testing\", false") ); @@ -495,14 +497,11 @@ UniValue importwallet(const JSONRPCRequest& request) } file.close(); pwalletMain->ShowProgress("", 100); // hide progress dialog in GUI - - CBlockIndex *pindex = chainActive.Tip(); - while (pindex && pindex->pprev && pindex->GetBlockTime() > nTimeBegin - 7200) - pindex = pindex->pprev; - pwalletMain->UpdateTimeFirstKey(nTimeBegin); - LogPrintf("Rescanning last %i blocks\n", chainActive.Height() - pindex->nHeight + 1); + CBlockIndex *pindex = chainActive.FindEarliestAtLeast(nTimeBegin - 7200); + + LogPrintf("Rescanning last %i blocks\n", pindex ? chainActive.Height() - pindex->nHeight + 1 : 0); pwalletMain->ScanForWalletTransactions(pindex); pwalletMain->MarkDirty(); diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp index 7ac2112dd..083ff0afc 100644 --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -19,6 +19,8 @@ #include <univalue.h> extern UniValue importmulti(const JSONRPCRequest& request); +extern UniValue dumpwallet(const JSONRPCRequest& request); +extern UniValue importwallet(const JSONRPCRequest& request); // how many times to run all the tests to have a chance to catch errors that only show up with particular random shuffles #define RUN_TESTS 100 @@ -428,4 +430,64 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup) } } +// Verify importwallet RPC starts rescan at earliest block with timestamp +// greater or equal than key birthday. Previously there was a bug where +// importwallet RPC would start the scan at the latest block with timestamp less +// than or equal to key birthday. +BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup) +{ + CWallet *pwalletMainBackup = ::pwalletMain; + LOCK(cs_main); + + // Create two blocks with same timestamp to verify that importwallet rescan + // will pick up both blocks, not just the first. + const int64_t BLOCK_TIME = chainActive.Tip()->GetBlockTimeMax() + 5; + SetMockTime(BLOCK_TIME); + coinbaseTxns.emplace_back(*CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]); + coinbaseTxns.emplace_back(*CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]); + + // Set key birthday to block time increased by the timestamp window, so + // rescan will start at the block time. + const int64_t KEY_TIME = BLOCK_TIME + 7200; + SetMockTime(KEY_TIME); + coinbaseTxns.emplace_back(*CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]); + + // Import key into wallet and call dumpwallet to create backup file. + { + CWallet wallet; + LOCK(wallet.cs_wallet); + wallet.mapKeyMetadata[coinbaseKey.GetPubKey().GetID()].nCreateTime = KEY_TIME; + wallet.AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey()); + + JSONRPCRequest request; + request.params.setArray(); + request.params.push_back("wallet.backup"); + ::pwalletMain = &wallet; + ::dumpwallet(request); + } + + // Call importwallet RPC and verify all blocks with timestamps >= BLOCK_TIME + // were scanned, and no prior blocks were scanned. + { + CWallet wallet; + + JSONRPCRequest request; + request.params.setArray(); + request.params.push_back("wallet.backup"); + ::pwalletMain = &wallet; + ::importwallet(request); + + BOOST_CHECK_EQUAL(wallet.mapWallet.size(), 3); + BOOST_CHECK_EQUAL(coinbaseTxns.size(), 103); + for (size_t i = 0; i < coinbaseTxns.size(); ++i) { + bool found = wallet.GetWalletTx(coinbaseTxns[i].GetHash()); + bool expected = i >= 100; + BOOST_CHECK_EQUAL(found, expected); + } + } + + SetMockTime(0); + ::pwalletMain = pwalletMainBackup; +} + BOOST_AUTO_TEST_SUITE_END() 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<CRecipient>& vecSend, CWalletTx& wt vector<CTxOut>::iterator position = txNew.vout.begin()+nChangePosInOut; txNew.vout.insert(position, newTxOut); } - } - else + } else { reservekey.ReturnKey(); + nChangePosInOut = -1; + } // Fill vin // |