aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml8
-rw-r--r--build-aux/m4/bitcoin_qt.m4237
-rw-r--r--configure.ac4
-rwxr-xr-xcontrib/devtools/gen-manpages.sh2
-rwxr-xr-xcontrib/gitian-build.sh2
-rw-r--r--contrib/gitian-descriptors/gitian-linux.yml6
-rw-r--r--contrib/gitian-descriptors/gitian-osx-signer.yml2
-rw-r--r--contrib/gitian-descriptors/gitian-osx.yml4
-rw-r--r--contrib/gitian-descriptors/gitian-win.yml8
-rw-r--r--contrib/init/bitcoind.init2
-rwxr-xr-xcontrib/macdeploy/extract-osx-sdk.sh2
-rwxr-xr-xcontrib/verify-commits/pre-push-hook.sh2
-rwxr-xr-xcontrib/verifybinaries/verify.sh2
-rw-r--r--doc/build-osx.md2
-rw-r--r--doc/build-unix.md11
-rw-r--r--doc/dependencies.md2
-rw-r--r--doc/release-notes-pr10740.md3
-rw-r--r--src/Makefile.am2
-rw-r--r--src/Makefile.bench.include1
-rw-r--r--src/bench/block_assemble.cpp116
-rw-r--r--src/crypto/sha256.cpp21
-rw-r--r--src/interfaces/wallet.cpp4
-rw-r--r--src/interfaces/wallet.h4
-rw-r--r--src/miner.cpp4
-rw-r--r--src/qt/README.md8
-rw-r--r--src/qt/addressbookpage.cpp5
-rw-r--r--src/qt/bantablemodel.cpp2
-rw-r--r--src/qt/bitcoin.cpp54
-rw-r--r--src/qt/bitcoingui.cpp92
-rw-r--r--src/qt/bitcoingui.h101
-rw-r--r--src/qt/coincontroldialog.cpp10
-rw-r--r--src/qt/guiutil.cpp32
-rw-r--r--src/qt/guiutil.h2
-rw-r--r--src/qt/macdockiconhandler.mm8
-rw-r--r--src/qt/networkstyle.cpp4
-rw-r--r--src/qt/openuridialog.cpp2
-rw-r--r--src/qt/optionsdialog.cpp12
-rw-r--r--src/qt/paymentrequestplus.cpp2
-rw-r--r--src/qt/paymentserver.cpp15
-rw-r--r--src/qt/peertablemodel.cpp2
-rw-r--r--src/qt/platformstyle.cpp2
-rw-r--r--src/qt/receiverequestdialog.cpp3
-rw-r--r--src/qt/rpcconsole.cpp14
-rw-r--r--src/qt/rpcconsole.h1
-rw-r--r--src/qt/sendcoinsentry.cpp2
-rw-r--r--src/qt/signverifymessagedialog.cpp2
-rw-r--r--src/qt/test/test_main.cpp7
-rw-r--r--src/qt/test/wallettests.cpp13
-rw-r--r--src/qt/transactionview.cpp4
-rw-r--r--src/qt/walletframe.cpp1
-rw-r--r--src/qt/walletmodel.cpp8
-rw-r--r--src/qt/walletmodel.h4
-rw-r--r--src/qt/winshutdownmonitor.cpp2
-rw-r--r--src/qt/winshutdownmonitor.h2
-rw-r--r--src/rpc/blockchain.cpp2
-rw-r--r--src/txmempool.cpp4
-rw-r--r--src/validation.cpp4
-rw-r--r--src/wallet/db.cpp5
-rw-r--r--src/wallet/init.cpp2
-rw-r--r--src/wallet/rpcdump.cpp2
-rw-r--r--src/wallet/rpcwallet.cpp74
-rw-r--r--src/wallet/wallet.cpp17
-rw-r--r--src/wallet/wallet.h3
-rwxr-xr-xtest/functional/feature_assumevalid.py4
-rwxr-xr-xtest/functional/p2p_compactblocks.py2
-rwxr-xr-xtest/functional/p2p_leak.py6
-rwxr-xr-xtest/functional/p2p_timeouts.py18
-rwxr-xr-xtest/functional/test_framework/mininode.py68
-rwxr-xr-xtest/functional/wallet_basic.py9
-rwxr-xr-xtest/functional/wallet_multiwallet.py27
-rwxr-xr-xtest/lint/lint-all.sh2
-rwxr-xr-xtest/lint/lint-filenames.sh7
-rwxr-xr-xtest/lint/lint-include-guards.sh2
-rwxr-xr-xtest/lint/lint-includes.sh2
-rwxr-xr-xtest/lint/lint-locale-dependence.sh2
-rwxr-xr-xtest/lint/lint-logs.sh2
-rwxr-xr-xtest/lint/lint-python-shebang.sh2
-rwxr-xr-xtest/lint/lint-python-utf8-encoding.sh2
-rwxr-xr-xtest/lint/lint-shell-locale.sh2
-rwxr-xr-xtest/lint/lint-shell.sh2
-rwxr-xr-xtest/lint/lint-tests.sh2
-rwxr-xr-xtest/lint/lint-whitespace.sh2
82 files changed, 591 insertions, 552 deletions
diff --git a/.travis.yml b/.travis.yml
index 75df290187..9332160926 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -35,8 +35,8 @@ env:
- HOST=i686-pc-linux-gnu PACKAGES="g++-multilib python3-zmq" DEP_OPTS="NO_QT=1" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-zmq --enable-glibc-back-compat --enable-reduce-exports LDFLAGS=-static-libstdc++" CONFIG_SHELL="/bin/dash"
# x86_64 Linux (uses qt5 dev package instead of depends Qt to speed up build and avoid timeout)
- HOST=x86_64-unknown-linux-gnu PACKAGES="python3-zmq qtbase5-dev qttools5-dev-tools protobuf-compiler libdbus-1-dev libharfbuzz-dev libprotobuf-dev" DEP_OPTS="NO_QT=1 NO_UPNP=1 DEBUG=1 ALLOW_HOST_PACKAGES=1" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-zmq --with-gui=qt5 --enable-glibc-back-compat --enable-reduce-exports CPPFLAGS=-DDEBUG_LOCKORDER"
-# Qt4 & system libs
- - HOST=x86_64-unknown-linux-gnu PACKAGES="python3-zmq qt4-dev-tools libssl1.0-dev libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-program-options-dev libboost-test-dev libboost-thread-dev libdb5.3++-dev libminiupnpc-dev libzmq3-dev libprotobuf-dev protobuf-compiler libqrencode-dev xvfb libqt4-dev" NO_DEPENDS=1 NEED_XVFB=1 RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-zmq --with-incompatible-bdb --enable-glibc-back-compat --enable-reduce-exports --with-gui=qt4 CPPFLAGS=-DDEBUG_LOCKORDER" DISPLAY=:99.0
+# x86_64 Linux (Qt5 & system libs)
+ - HOST=x86_64-unknown-linux-gnu PACKAGES="python3-zmq qtbase5-dev qttools5-dev-tools libssl1.0-dev libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-program-options-dev libboost-test-dev libboost-thread-dev libdb5.3++-dev libminiupnpc-dev libzmq3-dev libprotobuf-dev protobuf-compiler libqrencode-dev" NO_DEPENDS=1 RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-zmq --with-incompatible-bdb --enable-glibc-back-compat --enable-reduce-exports --with-gui=qt5 CPPFLAGS=-DDEBUG_LOCKORDER"
# x86_64 Linux, No wallet
- HOST=x86_64-unknown-linux-gnu PACKAGES="python3" DEP_OPTS="NO_WALLET=1" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports"
# Cross-Mac
@@ -45,7 +45,7 @@ env:
before_install:
- export PATH=$(echo $PATH | tr ':' "\n" | sed '/\/opt\/python/d' | tr "\n" ":" | sed "s|::|:|g")
install:
- - env | grep -E '^(CCACHE_|WINEDEBUG|DISPLAY|BOOST_TEST_RANDOM|CONFIG_SHELL)' | tee /tmp/env
+ - env | grep -E '^(CCACHE_|WINEDEBUG|BOOST_TEST_RANDOM|CONFIG_SHELL)' | tee /tmp/env
- if [[ $HOST = *-mingw32 ]]; then DOCKER_ADMIN="--cap-add SYS_ADMIN"; fi
- DOCKER_ID=$(docker run $DOCKER_ADMIN -idt --mount type=bind,src=$TRAVIS_BUILD_DIR,dst=$TRAVIS_BUILD_DIR --mount type=bind,src=$CCACHE_DIR,dst=$CCACHE_DIR -w $TRAVIS_BUILD_DIR --env-file /tmp/env ubuntu:18.04)
- DOCKER_EXEC () { docker exec $DOCKER_ID bash -c "cd $PWD && $*"; }
@@ -58,8 +58,6 @@ before_script:
- if [ -n "$OSX_SDK" -a -f depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz ]; then tar -C depends/SDKs -xf depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz; fi
- if [[ $HOST = *-mingw32 ]]; then DOCKER_EXEC update-alternatives --set $HOST-g++ \$\(which $HOST-g++-posix\); fi
- if [ -z "$NO_DEPENDS" ]; then DOCKER_EXEC CONFIG_SHELL= make $MAKEJOBS -C depends HOST=$HOST $DEP_OPTS; fi
- # Start xvfb if needed, as documented at https://docs.travis-ci.com/user/gui-and-headless-browsers/#Using-xvfb-to-Run-Tests-That-Require-a-GUI
- - if [ "$NEED_XVFB" = 1 ]; then DOCKER_EXEC /sbin/start-stop-daemon --start --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -ac; fi
script:
- export TRAVIS_COMMIT_LOG=`git log --format=fuller -1`
- OUTDIR=$BASE_OUTDIR/$TRAVIS_PULL_REQUEST/$TRAVIS_JOB_NUMBER-$HOST
diff --git a/build-aux/m4/bitcoin_qt.m4 b/build-aux/m4/bitcoin_qt.m4
index f41508336c..fe0cc6c36d 100644
--- a/build-aux/m4/bitcoin_qt.m4
+++ b/build-aux/m4/bitcoin_qt.m4
@@ -53,8 +53,8 @@ dnl CAUTION: Do not use this inside of a conditional.
AC_DEFUN([BITCOIN_QT_INIT],[
dnl enable qt support
AC_ARG_WITH([gui],
- [AS_HELP_STRING([--with-gui@<:@=no|qt4|qt5|auto@:>@],
- [build bitcoin-qt GUI (default=auto, qt5 tried first)])],
+ [AS_HELP_STRING([--with-gui@<:@=no|qt5|auto@:>@],
+ [build bitcoin-qt GUI (default=auto)])],
[
bitcoin_qt_want_version=$withval
if test "x$bitcoin_qt_want_version" = xyes; then
@@ -94,18 +94,17 @@ AC_DEFUN([BITCOIN_QT_CONFIGURE],[
fi
if test "x$use_pkgconfig" = xyes; then
- BITCOIN_QT_CHECK([_BITCOIN_QT_FIND_LIBS_WITH_PKGCONFIG([$2])])
+ BITCOIN_QT_CHECK([_BITCOIN_QT_FIND_LIBS_WITH_PKGCONFIG])
else
BITCOIN_QT_CHECK([_BITCOIN_QT_FIND_LIBS_WITHOUT_PKGCONFIG])
fi
dnl This is ugly and complicated. Yuck. Works as follows:
- dnl We can't discern whether Qt4 builds are static or not. For Qt5, we can
- dnl check a header to find out. When Qt is built statically, some plugins must
- dnl be linked into the final binary as well. These plugins have changed between
- dnl Qt4 and Qt5. With Qt5, languages moved into core and the WindowsIntegration
- dnl plugin was added. Since we can't tell if Qt4 is static or not, it is
- dnl assumed for windows builds.
+ dnl For Qt5, we can check a header to find out whether Qt is build
+ dnl statically. When Qt is built statically, some plugins must be linked into
+ dnl the final binary as well.
+ dnl With Qt5, languages moved into core and the WindowsIntegration plugin was
+ dnl added.
dnl _BITCOIN_QT_CHECK_STATIC_PLUGINS does a quick link-check and appends the
dnl results to QT_LIBS.
BITCOIN_QT_CHECK([
@@ -113,53 +112,40 @@ AC_DEFUN([BITCOIN_QT_CONFIGURE],[
TEMP_CXXFLAGS=$CXXFLAGS
CPPFLAGS="$QT_INCLUDES $CPPFLAGS"
CXXFLAGS="$PIC_FLAGS $CXXFLAGS"
- if test "x$bitcoin_qt_got_major_vers" = x5; then
- _BITCOIN_QT_IS_STATIC
- if test "x$bitcoin_cv_static_qt" = xyes; then
- _BITCOIN_QT_FIND_STATIC_PLUGINS
- AC_DEFINE(QT_STATICPLUGIN, 1, [Define this symbol if qt plugins are static])
- AC_CACHE_CHECK(for Qt < 5.4, bitcoin_cv_need_acc_widget,[
- AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
- #include <QtCore/qconfig.h>
- #ifndef QT_VERSION
- # include <QtCore/qglobal.h>
- #endif
- ]],
- [[
- #if QT_VERSION >= 0x050400
- choke
- #endif
- ]])],
- [bitcoin_cv_need_acc_widget=yes],
- [bitcoin_cv_need_acc_widget=no])
- ])
- if test "x$bitcoin_cv_need_acc_widget" = xyes; then
- _BITCOIN_QT_CHECK_STATIC_PLUGINS([Q_IMPORT_PLUGIN(AccessibleFactory)], [-lqtaccessiblewidgets])
- fi
- _BITCOIN_QT_CHECK_STATIC_PLUGINS([Q_IMPORT_PLUGIN(QMinimalIntegrationPlugin)],[-lqminimal])
- AC_DEFINE(QT_QPA_PLATFORM_MINIMAL, 1, [Define this symbol if the minimal qt platform exists])
- if test "x$TARGET_OS" = xwindows; then
- _BITCOIN_QT_CHECK_STATIC_PLUGINS([Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin)],[-lqwindows])
- AC_DEFINE(QT_QPA_PLATFORM_WINDOWS, 1, [Define this symbol if the qt platform is windows])
- elif test "x$TARGET_OS" = xlinux; then
- _BITCOIN_QT_CHECK_STATIC_PLUGINS([Q_IMPORT_PLUGIN(QXcbIntegrationPlugin)],[-lqxcb -lxcb-static])
- AC_DEFINE(QT_QPA_PLATFORM_XCB, 1, [Define this symbol if the qt platform is xcb])
- elif test "x$TARGET_OS" = xdarwin; then
- AX_CHECK_LINK_FLAG([[-framework IOKit]],[QT_LIBS="$QT_LIBS -framework IOKit"],[AC_MSG_ERROR(could not iokit framework)])
- _BITCOIN_QT_CHECK_STATIC_PLUGINS([Q_IMPORT_PLUGIN(QCocoaIntegrationPlugin)],[-lqcocoa])
- AC_DEFINE(QT_QPA_PLATFORM_COCOA, 1, [Define this symbol if the qt platform is cocoa])
- fi
+ _BITCOIN_QT_IS_STATIC
+ if test "x$bitcoin_cv_static_qt" = xyes; then
+ _BITCOIN_QT_FIND_STATIC_PLUGINS
+ AC_DEFINE(QT_STATICPLUGIN, 1, [Define this symbol if qt plugins are static])
+ AC_CACHE_CHECK(for Qt < 5.4, bitcoin_cv_need_acc_widget,[
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+ #include <QtCore/qconfig.h>
+ #ifndef QT_VERSION
+ # include <QtCore/qglobal.h>
+ #endif
+ ]],
+ [[
+ #if QT_VERSION >= 0x050400
+ choke
+ #endif
+ ]])],
+ [bitcoin_cv_need_acc_widget=yes],
+ [bitcoin_cv_need_acc_widget=no])
+ ])
+ if test "x$bitcoin_cv_need_acc_widget" = xyes; then
+ _BITCOIN_QT_CHECK_STATIC_PLUGINS([Q_IMPORT_PLUGIN(AccessibleFactory)], [-lqtaccessiblewidgets])
fi
- else
+ _BITCOIN_QT_CHECK_STATIC_PLUGINS([Q_IMPORT_PLUGIN(QMinimalIntegrationPlugin)],[-lqminimal])
+ AC_DEFINE(QT_QPA_PLATFORM_MINIMAL, 1, [Define this symbol if the minimal qt platform exists])
if test "x$TARGET_OS" = xwindows; then
- AC_DEFINE(QT_STATICPLUGIN, 1, [Define this symbol if qt plugins are static])
- _BITCOIN_QT_CHECK_STATIC_PLUGINS([
- Q_IMPORT_PLUGIN(qcncodecs)
- Q_IMPORT_PLUGIN(qjpcodecs)
- Q_IMPORT_PLUGIN(qtwcodecs)
- Q_IMPORT_PLUGIN(qkrcodecs)
- Q_IMPORT_PLUGIN(AccessibleFactory)],
- [-lqcncodecs -lqjpcodecs -lqtwcodecs -lqkrcodecs -lqtaccessiblewidgets])
+ _BITCOIN_QT_CHECK_STATIC_PLUGINS([Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin)],[-lqwindows])
+ AC_DEFINE(QT_QPA_PLATFORM_WINDOWS, 1, [Define this symbol if the qt platform is windows])
+ elif test "x$TARGET_OS" = xlinux; then
+ _BITCOIN_QT_CHECK_STATIC_PLUGINS([Q_IMPORT_PLUGIN(QXcbIntegrationPlugin)],[-lqxcb -lxcb-static])
+ AC_DEFINE(QT_QPA_PLATFORM_XCB, 1, [Define this symbol if the qt platform is xcb])
+ elif test "x$TARGET_OS" = xdarwin; then
+ AX_CHECK_LINK_FLAG([[-framework IOKit]],[QT_LIBS="$QT_LIBS -framework IOKit"],[AC_MSG_ERROR(could not iokit framework)])
+ _BITCOIN_QT_CHECK_STATIC_PLUGINS([Q_IMPORT_PLUGIN(QCocoaIntegrationPlugin)],[-lqcocoa])
+ AC_DEFINE(QT_QPA_PLATFORM_COCOA, 1, [Define this symbol if the qt platform is cocoa])
fi
fi
CPPFLAGS=$TEMP_CPPFLAGS
@@ -167,9 +153,7 @@ AC_DEFUN([BITCOIN_QT_CONFIGURE],[
])
if test "x$use_pkgconfig$qt_bin_path" = xyes; then
- if test "x$bitcoin_qt_got_major_vers" = x5; then
- qt_bin_path="`$PKG_CONFIG --variable=host_bins Qt5Core 2>/dev/null`"
- fi
+ qt_bin_path="`$PKG_CONFIG --variable=host_bins Qt5Core 2>/dev/null`"
fi
if test "x$use_hardening" != xno; then
@@ -219,11 +203,11 @@ AC_DEFUN([BITCOIN_QT_CONFIGURE],[
])
fi
- BITCOIN_QT_PATH_PROGS([MOC], [moc-qt${bitcoin_qt_got_major_vers} moc${bitcoin_qt_got_major_vers} moc], $qt_bin_path)
- BITCOIN_QT_PATH_PROGS([UIC], [uic-qt${bitcoin_qt_got_major_vers} uic${bitcoin_qt_got_major_vers} uic], $qt_bin_path)
- BITCOIN_QT_PATH_PROGS([RCC], [rcc-qt${bitcoin_qt_got_major_vers} rcc${bitcoin_qt_got_major_vers} rcc], $qt_bin_path)
- BITCOIN_QT_PATH_PROGS([LRELEASE], [lrelease-qt${bitcoin_qt_got_major_vers} lrelease${bitcoin_qt_got_major_vers} lrelease], $qt_bin_path)
- BITCOIN_QT_PATH_PROGS([LUPDATE], [lupdate-qt${bitcoin_qt_got_major_vers} lupdate${bitcoin_qt_got_major_vers} lupdate],$qt_bin_path, yes)
+ BITCOIN_QT_PATH_PROGS([MOC], [moc-qt5 moc5 moc], $qt_bin_path)
+ BITCOIN_QT_PATH_PROGS([UIC], [uic-qt5 uic5 uic], $qt_bin_path)
+ BITCOIN_QT_PATH_PROGS([RCC], [rcc-qt5 rcc5 rcc], $qt_bin_path)
+ BITCOIN_QT_PATH_PROGS([LRELEASE], [lrelease-qt5 lrelease5 lrelease], $qt_bin_path)
+ BITCOIN_QT_PATH_PROGS([LUPDATE], [lupdate-qt5 lupdate5 lupdate],$qt_bin_path, yes)
MOC_DEFS='-DHAVE_CONFIG_H -I$(srcdir)'
case $host in
@@ -262,7 +246,7 @@ AC_DEFUN([BITCOIN_QT_CONFIGURE],[
],[
bitcoin_enable_qt=no
])
- AC_MSG_RESULT([$bitcoin_enable_qt (Qt${bitcoin_qt_got_major_vers})])
+ AC_MSG_RESULT([$bitcoin_enable_qt (Qt5)])
AC_SUBST(QT_PIE_FLAGS)
AC_SUBST(QT_INCLUDES)
@@ -272,7 +256,7 @@ AC_DEFUN([BITCOIN_QT_CONFIGURE],[
AC_SUBST(QT_DBUS_LIBS)
AC_SUBST(QT_TEST_INCLUDES)
AC_SUBST(QT_TEST_LIBS)
- AC_SUBST(QT_SELECT, qt${bitcoin_qt_got_major_vers})
+ AC_SUBST(QT_SELECT, qt5)
AC_SUBST(MOC_DEFS)
])
@@ -301,7 +285,7 @@ AC_DEFUN([_BITCOIN_QT_CHECK_QT5],[
])])
dnl Internal. Check if the linked version of Qt was built as static libs.
-dnl Requires: Qt5. This check cannot determine if Qt4 is static.
+dnl Requires: Qt5.
dnl Requires: INCLUDES and LIBS must be populated as necessary.
dnl Output: bitcoin_cv_static_qt=yes|no
dnl Output: Defines QT_STATICPLUGIN if plugins are static.
@@ -346,58 +330,50 @@ AC_DEFUN([_BITCOIN_QT_CHECK_STATIC_PLUGINS],[
])
dnl Internal. Find paths necessary for linking qt static plugins
-dnl Inputs: bitcoin_qt_got_major_vers. 4 or 5.
dnl Inputs: qt_plugin_path. optional.
dnl Outputs: QT_LIBS is appended
AC_DEFUN([_BITCOIN_QT_FIND_STATIC_PLUGINS],[
- if test "x$bitcoin_qt_got_major_vers" = x5; then
- if test "x$qt_plugin_path" != x; then
- QT_LIBS="$QT_LIBS -L$qt_plugin_path/platforms"
- if test -d "$qt_plugin_path/accessible"; then
- QT_LIBS="$QT_LIBS -L$qt_plugin_path/accessible"
- fi
+ if test "x$qt_plugin_path" != x; then
+ QT_LIBS="$QT_LIBS -L$qt_plugin_path/platforms"
+ if test -d "$qt_plugin_path/accessible"; then
+ QT_LIBS="$QT_LIBS -L$qt_plugin_path/accessible"
fi
- if test "x$use_pkgconfig" = xyes; then
- : dnl
- m4_ifdef([PKG_CHECK_MODULES],[
- PKG_CHECK_MODULES([QTPLATFORM], [Qt5PlatformSupport], [QT_LIBS="$QTPLATFORM_LIBS $QT_LIBS"])
- if test "x$TARGET_OS" = xlinux; then
- PKG_CHECK_MODULES([X11XCB], [x11-xcb], [QT_LIBS="$X11XCB_LIBS $QT_LIBS"])
- if ${PKG_CONFIG} --exists "Qt5Core >= 5.5" 2>/dev/null; then
- PKG_CHECK_MODULES([QTXCBQPA], [Qt5XcbQpa], [QT_LIBS="$QTXCBQPA_LIBS $QT_LIBS"])
- fi
- elif test "x$TARGET_OS" = xdarwin; then
- PKG_CHECK_MODULES([QTPRINT], [Qt5PrintSupport], [QT_LIBS="$QTPRINT_LIBS $QT_LIBS"])
+ fi
+ if test "x$use_pkgconfig" = xyes; then
+ : dnl
+ m4_ifdef([PKG_CHECK_MODULES],[
+ PKG_CHECK_MODULES([QTPLATFORM], [Qt5PlatformSupport], [QT_LIBS="$QTPLATFORM_LIBS $QT_LIBS"])
+ if test "x$TARGET_OS" = xlinux; then
+ PKG_CHECK_MODULES([X11XCB], [x11-xcb], [QT_LIBS="$X11XCB_LIBS $QT_LIBS"])
+ if ${PKG_CONFIG} --exists "Qt5Core >= 5.5" 2>/dev/null; then
+ PKG_CHECK_MODULES([QTXCBQPA], [Qt5XcbQpa], [QT_LIBS="$QTXCBQPA_LIBS $QT_LIBS"])
fi
- ])
- else
- if test "x$TARGET_OS" = xwindows; then
- AC_CACHE_CHECK(for Qt >= 5.6, bitcoin_cv_need_platformsupport,[
- AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
- #include <QtCore/qconfig.h>
- #ifndef QT_VERSION
- # include <QtCore/qglobal.h>
- #endif
- ]],
- [[
- #if QT_VERSION < 0x050600
- choke
- #endif
- ]])],
- [bitcoin_cv_need_platformsupport=yes],
- [bitcoin_cv_need_platformsupport=no])
- ])
- if test "x$bitcoin_cv_need_platformsupport" = xyes; then
- BITCOIN_QT_CHECK(AC_CHECK_LIB([${QT_LIB_PREFIX}PlatformSupport],[main],,BITCOIN_QT_FAIL(lib${QT_LIB_PREFIX}PlatformSupport not found)))
- fi
+ elif test "x$TARGET_OS" = xdarwin; then
+ PKG_CHECK_MODULES([QTPRINT], [Qt5PrintSupport], [QT_LIBS="$QTPRINT_LIBS $QT_LIBS"])
+ fi
+ ])
+ else
+ if test "x$TARGET_OS" = xwindows; then
+ AC_CACHE_CHECK(for Qt >= 5.6, bitcoin_cv_need_platformsupport,[
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+ #include <QtCore/qconfig.h>
+ #ifndef QT_VERSION
+ # include <QtCore/qglobal.h>
+ #endif
+ ]],
+ [[
+ #if QT_VERSION < 0x050600
+ choke
+ #endif
+ ]])],
+ [bitcoin_cv_need_platformsupport=yes],
+ [bitcoin_cv_need_platformsupport=no])
+ ])
+ if test "x$bitcoin_cv_need_platformsupport" = xyes; then
+ BITCOIN_QT_CHECK(AC_CHECK_LIB([${QT_LIB_PREFIX}PlatformSupport],[main],,BITCOIN_QT_FAIL(lib${QT_LIB_PREFIX}PlatformSupport not found)))
fi
fi
- else
- if test "x$qt_plugin_path" != x; then
- QT_LIBS="$QT_LIBS -L$qt_plugin_path/accessible"
- QT_LIBS="$QT_LIBS -L$qt_plugin_path/codecs"
- fi
- fi
+ fi
])
dnl Internal. Find Qt libraries using pkg-config.
@@ -406,38 +382,14 @@ dnl first.
dnl Inputs: $1: If bitcoin_qt_want_version is "auto", check for this version
dnl first.
dnl Outputs: All necessary QT_* variables are set.
-dnl Outputs: bitcoin_qt_got_major_vers is set to "4" or "5".
dnl Outputs: have_qt_test and have_qt_dbus are set (if applicable) to yes|no.
AC_DEFUN([_BITCOIN_QT_FIND_LIBS_WITH_PKGCONFIG],[
m4_ifdef([PKG_CHECK_MODULES],[
- auto_priority_version=$1
- if test "x$auto_priority_version" = x; then
- auto_priority_version=qt5
- fi
- if test "x$bitcoin_qt_want_version" = xqt5 || ( test "x$bitcoin_qt_want_version" = xauto && test "x$auto_priority_version" = xqt5 ); then
- QT_LIB_PREFIX=Qt5
- bitcoin_qt_got_major_vers=5
- else
- QT_LIB_PREFIX=Qt
- bitcoin_qt_got_major_vers=4
- fi
+ QT_LIB_PREFIX=Qt5
qt5_modules="Qt5Core Qt5Gui Qt5Network Qt5Widgets"
- qt4_modules="QtCore QtGui QtNetwork"
BITCOIN_QT_CHECK([
- if test "x$bitcoin_qt_want_version" = xqt5 || ( test "x$bitcoin_qt_want_version" = xauto && test "x$auto_priority_version" = xqt5 ); then
- PKG_CHECK_MODULES([QT5], [$qt5_modules], [QT_INCLUDES="$QT5_CFLAGS"; QT_LIBS="$QT5_LIBS" have_qt=yes],[have_qt=no])
- elif test "x$bitcoin_qt_want_version" = xqt4 || ( test "x$bitcoin_qt_want_version" = xauto && test "x$auto_priority_version" = xqt4 ); then
- PKG_CHECK_MODULES([QT4], [$qt4_modules], [QT_INCLUDES="$QT4_CFLAGS"; QT_LIBS="$QT4_LIBS" ; have_qt=yes], [have_qt=no])
- fi
+ PKG_CHECK_MODULES([QT5], [$qt5_modules], [QT_INCLUDES="$QT5_CFLAGS"; QT_LIBS="$QT5_LIBS" have_qt=yes],[have_qt=no])
- dnl qt version is set to 'auto' and the preferred version wasn't found. Now try the other.
- if test "x$have_qt" = xno && test "x$bitcoin_qt_want_version" = xauto; then
- if test "x$auto_priority_version" = xqt5; then
- PKG_CHECK_MODULES([QT4], [$qt4_modules], [QT_INCLUDES="$QT4_CFLAGS"; QT_LIBS="$QT4_LIBS" ; have_qt=yes; QT_LIB_PREFIX=Qt; bitcoin_qt_got_major_vers=4], [have_qt=no])
- else
- PKG_CHECK_MODULES([QT5], [$qt5_modules], [QT_INCLUDES="$QT5_CFLAGS"; QT_LIBS="$QT5_LIBS" ; have_qt=yes; QT_LIB_PREFIX=Qt5; bitcoin_qt_got_major_vers=5], [have_qt=no])
- fi
- fi
if test "x$have_qt" != xyes; then
have_qt=no
BITCOIN_QT_FAIL([Qt dependencies not found])
@@ -458,7 +410,6 @@ dnl from the discovered headers.
dnl Inputs: bitcoin_qt_want_version (from --with-gui=). The version to use.
dnl If "auto", the version will be discovered by _BITCOIN_QT_CHECK_QT5.
dnl Outputs: All necessary QT_* variables are set.
-dnl Outputs: bitcoin_qt_got_major_vers is set to "4" or "5".
dnl Outputs: have_qt_test and have_qt_dbus are set (if applicable) to yes|no.
AC_DEFUN([_BITCOIN_QT_FIND_LIBS_WITHOUT_PKGCONFIG],[
TEMP_CPPFLAGS="$CPPFLAGS"
@@ -480,13 +431,7 @@ AC_DEFUN([_BITCOIN_QT_FIND_LIBS_WITHOUT_PKGCONFIG],[
if test "x$bitcoin_qt_want_version" = xauto; then
_BITCOIN_QT_CHECK_QT5
fi
- if test "x$bitcoin_cv_qt5" = xyes || test "x$bitcoin_qt_want_version" = xqt5; then
- QT_LIB_PREFIX=Qt5
- bitcoin_qt_got_major_vers=5
- else
- QT_LIB_PREFIX=Qt
- bitcoin_qt_got_major_vers=4
- fi
+ QT_LIB_PREFIX=Qt5
])
BITCOIN_QT_CHECK([
@@ -508,9 +453,7 @@ AC_DEFUN([_BITCOIN_QT_FIND_LIBS_WITHOUT_PKGCONFIG],[
BITCOIN_QT_CHECK(AC_CHECK_LIB([${QT_LIB_PREFIX}Core] ,[main],,BITCOIN_QT_FAIL(lib${QT_LIB_PREFIX}Core not found)))
BITCOIN_QT_CHECK(AC_CHECK_LIB([${QT_LIB_PREFIX}Gui] ,[main],,BITCOIN_QT_FAIL(lib${QT_LIB_PREFIX}Gui not found)))
BITCOIN_QT_CHECK(AC_CHECK_LIB([${QT_LIB_PREFIX}Network],[main],,BITCOIN_QT_FAIL(lib${QT_LIB_PREFIX}Network not found)))
- if test "x$bitcoin_qt_got_major_vers" = x5; then
- BITCOIN_QT_CHECK(AC_CHECK_LIB([${QT_LIB_PREFIX}Widgets],[main],,BITCOIN_QT_FAIL(lib${QT_LIB_PREFIX}Widgets not found)))
- fi
+ BITCOIN_QT_CHECK(AC_CHECK_LIB([${QT_LIB_PREFIX}Widgets],[main],,BITCOIN_QT_FAIL(lib${QT_LIB_PREFIX}Widgets not found)))
QT_LIBS="$LIBS"
LIBS="$TEMP_LIBS"
diff --git a/configure.ac b/configure.ac
index 926d0b8d00..ff7f1b39c8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -301,6 +301,7 @@ if test "x$CXXFLAGS_overridden" = "xno"; then
AX_CHECK_COMPILE_FLAG([-Wvla],[WARN_CXXFLAGS="$WARN_CXXFLAGS -Wvla"],,[[$CXXFLAG_WERROR]])
AX_CHECK_COMPILE_FLAG([-Wformat-security],[WARN_CXXFLAGS="$WARN_CXXFLAGS -Wformat-security"],,[[$CXXFLAG_WERROR]])
AX_CHECK_COMPILE_FLAG([-Wthread-safety-analysis],[WARN_CXXFLAGS="$WARN_CXXFLAGS -Wthread-safety-analysis"],,[[$CXXFLAG_WERROR]])
+ AX_CHECK_COMPILE_FLAG([-Wrange-loop-analysis],[WARN_CXXFLAGS="$WARN_CXXFLAGS -Wrange-loop-analysis"],,[[$CXXFLAG_WERROR]])
## Some compilers (gcc) ignore unknown -Wno-* options, but warn about all
## unknown options if any other warning is produced. Test the -Wfoo case, and
@@ -837,7 +838,7 @@ fi
BITCOIN_QT_INIT
dnl sets $bitcoin_enable_qt, $bitcoin_enable_qt_test, $bitcoin_enable_qt_dbus
-BITCOIN_QT_CONFIGURE([$use_pkgconfig], [qt5])
+BITCOIN_QT_CONFIGURE([$use_pkgconfig])
if test x$build_bitcoin_utils$build_bitcoind$bitcoin_enable_qt$use_tests$use_bench = xnonononono; then
use_boost=no
@@ -1422,7 +1423,6 @@ echo "Options used to compile and link:"
echo " with wallet = $enable_wallet"
echo " with gui / qt = $bitcoin_enable_qt"
if test x$bitcoin_enable_qt != xno; then
- echo " qt version = $bitcoin_qt_got_major_vers"
echo " with qr = $use_qr"
fi
echo " with zmq = $use_zmq"
diff --git a/contrib/devtools/gen-manpages.sh b/contrib/devtools/gen-manpages.sh
index 76d4adc81c..b5de5a395f 100755
--- a/contrib/devtools/gen-manpages.sh
+++ b/contrib/devtools/gen-manpages.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
export LC_ALL=C
TOPDIR=${TOPDIR:-$(git rev-parse --show-toplevel)}
diff --git a/contrib/gitian-build.sh b/contrib/gitian-build.sh
index 8bfbf6d1a0..05e7d6f4c6 100755
--- a/contrib/gitian-build.sh
+++ b/contrib/gitian-build.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# Copyright (c) 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.
diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml
index 3e9ee0495a..f78eea73a3 100644
--- a/contrib/gitian-descriptors/gitian-linux.yml
+++ b/contrib/gitian-descriptors/gitian-linux.yml
@@ -56,7 +56,7 @@ script: |
function create_global_faketime_wrappers {
for prog in ${FAKETIME_PROGS}; do
- echo '#!/bin/bash' > ${WRAP_DIR}/${prog}
+ echo '#!/usr/bin/env bash' > ${WRAP_DIR}/${prog}
echo "REAL=\`which -a ${prog} | grep -v ${WRAP_DIR}/${prog} | head -1\`" >> ${WRAP_DIR}/${prog}
echo 'export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1' >> ${WRAP_DIR}/${prog}
echo "export FAKETIME=\"$1\"" >> ${WRAP_DIR}/${prog}
@@ -68,7 +68,7 @@ script: |
function create_per-host_faketime_wrappers {
for i in $HOSTS; do
for prog in ${FAKETIME_HOST_PROGS}; do
- echo '#!/bin/bash' > ${WRAP_DIR}/${i}-${prog}
+ echo '#!/usr/bin/env bash' > ${WRAP_DIR}/${i}-${prog}
echo "REAL=\`which -a ${i}-${prog} | grep -v ${WRAP_DIR}/${i}-${prog} | head -1\`" >> ${WRAP_DIR}/${i}-${prog}
echo 'export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1' >> ${WRAP_DIR}/${i}-${prog}
echo "export FAKETIME=\"$1\"" >> ${WRAP_DIR}/${i}-${prog}
@@ -98,7 +98,7 @@ script: |
for prog in gcc g++; do
rm -f ${WRAP_DIR}/${prog}
cat << EOF > ${WRAP_DIR}/${prog}
- #!/bin/bash
+ #!/usr/bin/env bash
REAL="`which -a ${prog} | grep -v ${WRAP_DIR}/${prog} | head -1`"
for var in "\$@"
do
diff --git a/contrib/gitian-descriptors/gitian-osx-signer.yml b/contrib/gitian-descriptors/gitian-osx-signer.yml
index f6e9414ab1..b5c863bb14 100644
--- a/contrib/gitian-descriptors/gitian-osx-signer.yml
+++ b/contrib/gitian-descriptors/gitian-osx-signer.yml
@@ -19,7 +19,7 @@ script: |
# Create global faketime wrappers
for prog in ${FAKETIME_PROGS}; do
- echo '#!/bin/bash' > ${WRAP_DIR}/${prog}
+ echo '#!/usr/bin/env bash' > ${WRAP_DIR}/${prog}
echo "REAL=\`which -a ${prog} | grep -v ${WRAP_DIR}/${prog} | head -1\`" >> ${WRAP_DIR}/${prog}
echo 'export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1' >> ${WRAP_DIR}/${prog}
echo "export FAKETIME=\"${REFERENCE_DATETIME}\"" >> ${WRAP_DIR}/${prog}
diff --git a/contrib/gitian-descriptors/gitian-osx.yml b/contrib/gitian-descriptors/gitian-osx.yml
index a84dce3e3a..2cc62d4ce7 100644
--- a/contrib/gitian-descriptors/gitian-osx.yml
+++ b/contrib/gitian-descriptors/gitian-osx.yml
@@ -55,7 +55,7 @@ script: |
function create_global_faketime_wrappers {
for prog in ${FAKETIME_PROGS}; do
- echo '#!/bin/bash' > ${WRAP_DIR}/${prog}
+ echo '#!/usr/bin/env bash' > ${WRAP_DIR}/${prog}
echo "REAL=\`which -a ${prog} | grep -v ${WRAP_DIR}/${prog} | head -1\`" >> ${WRAP_DIR}/${prog}
echo 'export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1' >> ${WRAP_DIR}/${prog}
echo "export FAKETIME=\"$1\"" >> ${WRAP_DIR}/${prog}
@@ -67,7 +67,7 @@ script: |
function create_per-host_faketime_wrappers {
for i in $HOSTS; do
for prog in ${FAKETIME_HOST_PROGS}; do
- echo '#!/bin/bash' > ${WRAP_DIR}/${i}-${prog}
+ echo '#!/usr/bin/env bash' > ${WRAP_DIR}/${i}-${prog}
echo "REAL=\`which -a ${i}-${prog} | grep -v ${WRAP_DIR}/${i}-${prog} | head -1\`" >> ${WRAP_DIR}/${i}-${prog}
echo 'export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1' >> ${WRAP_DIR}/${i}-${prog}
echo "export FAKETIME=\"$1\"" >> ${WRAP_DIR}/${i}-${prog}
diff --git a/contrib/gitian-descriptors/gitian-win.yml b/contrib/gitian-descriptors/gitian-win.yml
index 8a87d91754..f6eb1815f6 100644
--- a/contrib/gitian-descriptors/gitian-win.yml
+++ b/contrib/gitian-descriptors/gitian-win.yml
@@ -48,7 +48,7 @@ script: |
function create_global_faketime_wrappers {
for prog in ${FAKETIME_PROGS}; do
- echo '#!/bin/bash' > ${WRAP_DIR}/${prog}
+ echo '#!/usr/bin/env bash' > ${WRAP_DIR}/${prog}
echo "REAL=\`which -a ${prog} | grep -v ${WRAP_DIR}/${prog} | head -1\`" >> ${WRAP_DIR}/${prog}
echo 'export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1' >> ${WRAP_DIR}/${prog}
echo "export FAKETIME=\"$1\"" >> ${WRAP_DIR}/${prog}
@@ -60,7 +60,7 @@ script: |
function create_per-host_faketime_wrappers {
for i in $HOSTS; do
for prog in ${FAKETIME_HOST_PROGS}; do
- echo '#!/bin/bash' > ${WRAP_DIR}/${i}-${prog}
+ echo '#!/usr/bin/env bash' > ${WRAP_DIR}/${i}-${prog}
echo "REAL=\`which -a ${i}-${prog} | grep -v ${WRAP_DIR}/${i}-${prog} | head -1\`" >> ${WRAP_DIR}/${i}-${prog}
echo 'export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1' >> ${WRAP_DIR}/${i}-${prog}
echo "export FAKETIME=\"$1\"" >> ${WRAP_DIR}/${i}-${prog}
@@ -76,14 +76,14 @@ script: |
for i in $HOSTS; do
mkdir -p ${WRAP_DIR}/${i}
for prog in collect2; do
- echo '#!/bin/bash' > ${WRAP_DIR}/${i}/${prog}
+ echo '#!/usr/bin/env bash' > ${WRAP_DIR}/${i}/${prog}
REAL=$(${i}-gcc -print-prog-name=${prog})
echo "export MALLOC_PERTURB_=255" >> ${WRAP_DIR}/${i}/${prog}
echo "${REAL} \$@" >> $WRAP_DIR/${i}/${prog}
chmod +x ${WRAP_DIR}/${i}/${prog}
done
for prog in gcc g++; do
- echo '#!/bin/bash' > ${WRAP_DIR}/${i}-${prog}
+ echo '#!/usr/bin/env bash' > ${WRAP_DIR}/${i}-${prog}
echo "REAL=\`which -a ${i}-${prog} | grep -v ${WRAP_DIR}/${i}-${prog} | head -1\`" >> ${WRAP_DIR}/${i}-${prog}
echo 'export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1' >> ${WRAP_DIR}/${i}-${prog}
echo "export FAKETIME=\"$1\"" >> ${WRAP_DIR}/${i}-${prog}
diff --git a/contrib/init/bitcoind.init b/contrib/init/bitcoind.init
index db5061874b..0c95baf3a1 100644
--- a/contrib/init/bitcoind.init
+++ b/contrib/init/bitcoind.init
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
#
# bitcoind The bitcoin core server.
#
diff --git a/contrib/macdeploy/extract-osx-sdk.sh b/contrib/macdeploy/extract-osx-sdk.sh
index 94122b56fc..4c175156f4 100755
--- a/contrib/macdeploy/extract-osx-sdk.sh
+++ b/contrib/macdeploy/extract-osx-sdk.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# Copyright (c) 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.
diff --git a/contrib/verify-commits/pre-push-hook.sh b/contrib/verify-commits/pre-push-hook.sh
index 152f4e32e4..4db4a90853 100755
--- a/contrib/verify-commits/pre-push-hook.sh
+++ b/contrib/verify-commits/pre-push-hook.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# Copyright (c) 2014-2015 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/contrib/verifybinaries/verify.sh b/contrib/verifybinaries/verify.sh
index 42d9ffb752..fc7492ad3b 100755
--- a/contrib/verifybinaries/verify.sh
+++ b/contrib/verifybinaries/verify.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# Copyright (c) 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.
diff --git a/doc/build-osx.md b/doc/build-osx.md
index abd305cf9a..a07dbd1e1d 100644
--- a/doc/build-osx.md
+++ b/doc/build-osx.md
@@ -24,8 +24,6 @@ If you want to build the disk image with `make deploy` (.dmg / optional), you ne
brew install librsvg
-NOTE: Building with Qt4 is still supported, however, could result in a broken UI. Building with Qt5 is recommended.
-
Berkeley DB
-----------
It is recommended to use Berkeley DB 4.8. If you have to build it yourself,
diff --git a/doc/build-unix.md b/doc/build-unix.md
index 1ab5659511..e884c0ab67 100644
--- a/doc/build-unix.md
+++ b/doc/build-unix.md
@@ -100,18 +100,13 @@ ZMQ dependencies (provides ZMQ API 4.x):
#### Dependencies for the GUI
If you want to build Bitcoin-Qt, make sure that the required packages for Qt development
-are installed. Either Qt 5 or Qt 4 are necessary to build the GUI.
-If both Qt 4 and Qt 5 are installed, Qt 5 will be used. Pass `--with-gui=qt4` to configure to choose Qt4.
+are installed. Qt 5 is necessary to build the GUI.
To build without GUI pass `--without-gui`.
-To build with Qt 5 (recommended) you need the following:
+To build with Qt 5 you need the following:
sudo apt-get install libqt5gui5 libqt5core5a libqt5dbus5 qttools5-dev qttools5-dev-tools libprotobuf-dev protobuf-compiler
-Alternatively, to build with Qt 4 you need the following:
-
- sudo apt-get install libqt4-dev libprotobuf-dev protobuf-compiler
-
libqrencode (optional) can be installed with:
sudo apt-get install libqrencode-dev
@@ -132,7 +127,7 @@ Optional:
sudo dnf install miniupnpc-devel
-To build with Qt 5 (recommended) you need the following:
+To build with Qt 5 you need the following:
sudo dnf install qt5-qttools-devel qt5-qtbase-devel protobuf-devel
diff --git a/doc/dependencies.md b/doc/dependencies.md
index 7aa96c4c9b..793c659419 100644
--- a/doc/dependencies.md
+++ b/doc/dependencies.md
@@ -23,7 +23,7 @@ These are the dependencies currently used by Bitcoin Core. You can find instruct
| protobuf | [2.6.3](https://github.com/google/protobuf/releases) | | No | | |
| Python (tests) | | [3.4](https://www.python.org/downloads) | | | |
| qrencode | [3.4.4](https://fukuchi.org/works/qrencode) | | No | | |
-| Qt | [5.7.1](https://download.qt.io/official_releases/qt/) | 4.7+ | No | | |
+| Qt | [5.7.1](https://download.qt.io/official_releases/qt/) | 5.x | No | | |
| XCB | | | | | [Yes](https://github.com/bitcoin/bitcoin/blob/master/depends/packages/qt.mk#L94) (Linux only) |
| xkbcommon | | | | | [Yes](https://github.com/bitcoin/bitcoin/blob/master/depends/packages/qt.mk#L93) (Linux only) |
| ZeroMQ | [4.2.3](https://github.com/zeromq/libzmq/releases) | | No | | |
diff --git a/doc/release-notes-pr10740.md b/doc/release-notes-pr10740.md
index c81ea6a4db..a2eb8cd837 100644
--- a/doc/release-notes-pr10740.md
+++ b/doc/release-notes-pr10740.md
@@ -1,9 +1,10 @@
Dynamic loading and creation of wallets
---------------------------------------
-Previously, wallets could only be loaded or created at startup, by specifying `-wallet` parameters on the command line or in the bitcoin.conf file. It is now possible to load and create wallets dynamically at runtime:
+Previously, wallets could only be loaded or created at startup, by specifying `-wallet` parameters on the command line or in the bitcoin.conf file. It is now possible to load, create and unload wallets dynamically at runtime:
- Existing wallets can be loaded by calling the `loadwallet` RPC. The wallet can be specified as file/directory basename (which must be located in the `walletdir` directory), or as an absolute path to a file/directory.
- New wallets can be created (and loaded) by calling the `createwallet` RPC. The provided name must not match a wallet file in the `walletdir` directory or the name of a wallet that is currently loaded.
+- Loaded wallets can be unloaded by calling the `unloadwallet` RPC.
This feature is currently only available through the RPC interface.
diff --git a/src/Makefile.am b/src/Makefile.am
index e03c21f16e..a2599d33e1 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -235,6 +235,7 @@ libbitcoin_server_a_SOURCES = \
rpc/net.cpp \
rpc/rawtransaction.cpp \
rpc/server.cpp \
+ rpc/util.cpp \
script/sigcache.cpp \
timedata.cpp \
torcontrol.cpp \
@@ -392,7 +393,6 @@ libbitcoin_util_a_SOURCES = \
logging.cpp \
random.cpp \
rpc/protocol.cpp \
- rpc/util.cpp \
support/cleanse.cpp \
sync.cpp \
threadinterrupt.cpp \
diff --git a/src/Makefile.bench.include b/src/Makefile.bench.include
index bc2c46f228..d70df3c9e8 100644
--- a/src/Makefile.bench.include
+++ b/src/Makefile.bench.include
@@ -15,6 +15,7 @@ bench_bench_bitcoin_SOURCES = \
bench/bench_bitcoin.cpp \
bench/bench.cpp \
bench/bench.h \
+ bench/block_assemble.cpp \
bench/checkblock.cpp \
bench/checkqueue.cpp \
bench/examples.cpp \
diff --git a/src/bench/block_assemble.cpp b/src/bench/block_assemble.cpp
new file mode 100644
index 0000000000..36fa175a76
--- /dev/null
+++ b/src/bench/block_assemble.cpp
@@ -0,0 +1,116 @@
+// Copyright (c) 2011-2017 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 <bench/bench.h>
+#include <chainparams.h>
+#include <coins.h>
+#include <consensus/merkle.h>
+#include <consensus/validation.h>
+#include <miner.h>
+#include <policy/policy.h>
+#include <pow.h>
+#include <scheduler.h>
+#include <txdb.h>
+#include <txmempool.h>
+#include <utiltime.h>
+#include <validation.h>
+#include <validationinterface.h>
+
+#include <boost/thread.hpp>
+
+#include <list>
+#include <vector>
+
+static std::shared_ptr<CBlock> PrepareBlock(const CScript& coinbase_scriptPubKey)
+{
+ auto block = std::make_shared<CBlock>(
+ BlockAssembler{Params()}
+ .CreateNewBlock(coinbase_scriptPubKey, /* fMineWitnessTx */ true)
+ ->block);
+
+ block->nTime = ::chainActive.Tip()->GetMedianTimePast() + 1;
+ block->hashMerkleRoot = BlockMerkleRoot(*block);
+
+ return block;
+}
+
+
+static CTxIn MineBlock(const CScript& coinbase_scriptPubKey)
+{
+ auto block = PrepareBlock(coinbase_scriptPubKey);
+
+ while (!CheckProofOfWork(block->GetHash(), block->nBits, Params().GetConsensus())) {
+ assert(++block->nNonce);
+ }
+
+ bool processed{ProcessNewBlock(Params(), block, true, nullptr)};
+ assert(processed);
+
+ return CTxIn{block->vtx[0]->GetHash(), 0};
+}
+
+
+static void AssembleBlock(benchmark::State& state)
+{
+ const std::vector<unsigned char> op_true{OP_TRUE};
+ CScriptWitness witness;
+ witness.stack.push_back(op_true);
+
+ uint256 witness_program;
+ CSHA256().Write(&op_true[0], op_true.size()).Finalize(witness_program.begin());
+
+ const CScript SCRIPT_PUB{CScript(OP_0) << std::vector<unsigned char>{witness_program.begin(), witness_program.end()}};
+
+ // Switch to regtest so we can mine faster
+ // Also segwit is active, so we can include witness transactions
+ SelectParams(CBaseChainParams::REGTEST);
+
+ InitScriptExecutionCache();
+
+ boost::thread_group thread_group;
+ CScheduler scheduler;
+ {
+ ::pblocktree.reset(new CBlockTreeDB(1 << 20, true));
+ ::pcoinsdbview.reset(new CCoinsViewDB(1 << 23, true));
+ ::pcoinsTip.reset(new CCoinsViewCache(pcoinsdbview.get()));
+
+ const CChainParams& chainparams = Params();
+ thread_group.create_thread(boost::bind(&CScheduler::serviceQueue, &scheduler));
+ GetMainSignals().RegisterBackgroundSignalScheduler(scheduler);
+ LoadGenesisBlock(chainparams);
+ CValidationState state;
+ ActivateBestChain(state, chainparams);
+ assert(::chainActive.Tip() != nullptr);
+ const bool witness_enabled{IsWitnessEnabled(::chainActive.Tip(), chainparams.GetConsensus())};
+ assert(witness_enabled);
+ }
+
+ // Collect some loose transactions that spend the coinbases of our mined blocks
+ constexpr size_t NUM_BLOCKS{200};
+ std::array<CTransactionRef, NUM_BLOCKS - COINBASE_MATURITY + 1> txs;
+ for (size_t b{0}; b < NUM_BLOCKS; ++b) {
+ CMutableTransaction tx;
+ tx.vin.push_back(MineBlock(SCRIPT_PUB));
+ tx.vin.back().scriptWitness = witness;
+ tx.vout.emplace_back(1337, SCRIPT_PUB);
+ if (NUM_BLOCKS - b >= COINBASE_MATURITY)
+ txs.at(b) = MakeTransactionRef(tx);
+ }
+ for (const auto& txr : txs) {
+ CValidationState state;
+ bool ret{::AcceptToMemoryPool(::mempool, state, txr, nullptr /* pfMissingInputs */, nullptr /* plTxnReplaced */, false /* bypass_limits */, /* nAbsurdFee */ 0)};
+ assert(ret);
+ }
+
+ while (state.KeepRunning()) {
+ PrepareBlock(SCRIPT_PUB);
+ }
+
+ thread_group.interrupt_all();
+ thread_group.join_all();
+ GetMainSignals().FlushBackgroundCallbacks();
+ GetMainSignals().UnregisterBackgroundSignalScheduler();
+}
+
+BENCHMARK(AssembleBlock, 700);
diff --git a/src/crypto/sha256.cpp b/src/crypto/sha256.cpp
index 100d0d1fac..e62ddc125e 100644
--- a/src/crypto/sha256.cpp
+++ b/src/crypto/sha256.cpp
@@ -536,6 +536,14 @@ void inline cpuid(uint32_t leaf, uint32_t subleaf, uint32_t& a, uint32_t& b, uin
{
__asm__ ("cpuid" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(leaf), "2"(subleaf));
}
+
+/** Check whether the OS has enabled AVX registers. */
+bool AVXEnabled()
+{
+ uint32_t a, d;
+ __asm__("xgetbv" : "=a"(a), "=d"(d) : "c"(0));
+ return (a & 6) == 6;
+}
#endif
} // namespace
@@ -544,6 +552,7 @@ std::string SHA256AutoDetect()
{
std::string ret = "standard";
#if defined(USE_ASM) && (defined(__x86_64__) || defined(__amd64__) || defined(__i386__))
+ (void)AVXEnabled; // Silence unused warning (in case ENABLE_AVX2 is not defined)
uint32_t eax, ebx, ecx, edx;
cpuid(1, 0, eax, ebx, ecx, edx);
if ((ecx >> 19) & 1) {
@@ -555,10 +564,14 @@ std::string SHA256AutoDetect()
TransformD64_4way = sha256d64_sse41::Transform_4way;
ret = "sse4(1way+4way)";
#if defined(ENABLE_AVX2) && !defined(BUILD_BITCOIN_INTERNAL)
- cpuid(7, 0, eax, ebx, ecx, edx);
- if ((ebx >> 5) & 1) {
- TransformD64_8way = sha256d64_avx2::Transform_8way;
- ret += ",avx2(8way)";
+ if (((ecx >> 27) & 1) && ((ecx >> 28) & 1)) { // XSAVE and AVX
+ cpuid(7, 0, eax, ebx, ecx, edx);
+ if ((ebx >> 5) & 1) { // AVX2 flag
+ if (AVXEnabled()) { // OS has enabled AVX registers
+ TransformD64_8way = sha256d64_avx2::Transform_8way;
+ ret += ",avx2(8way)";
+ }
+ }
}
#endif
#else
diff --git a/src/interfaces/wallet.cpp b/src/interfaces/wallet.cpp
index 3029dbe8e3..e98acba0df 100644
--- a/src/interfaces/wallet.cpp
+++ b/src/interfaces/wallet.cpp
@@ -429,6 +429,10 @@ public:
bool hdEnabled() override { return m_wallet.IsHDEnabled(); }
OutputType getDefaultAddressType() override { return m_wallet.m_default_address_type; }
OutputType getDefaultChangeType() override { return m_wallet.m_default_change_type; }
+ std::unique_ptr<Handler> handleUnload(UnloadFn fn) override
+ {
+ return MakeHandler(m_wallet.NotifyUnload.connect(fn));
+ }
std::unique_ptr<Handler> handleShowProgress(ShowProgressFn fn) override
{
return MakeHandler(m_wallet.ShowProgress.connect(fn));
diff --git a/src/interfaces/wallet.h b/src/interfaces/wallet.h
index 82ae0b14b5..ce42e14eea 100644
--- a/src/interfaces/wallet.h
+++ b/src/interfaces/wallet.h
@@ -242,6 +242,10 @@ public:
// Get default change type.
virtual OutputType getDefaultChangeType() = 0;
+ //! Register handler for unload message.
+ using UnloadFn = std::function<void()>;
+ virtual std::unique_ptr<Handler> handleUnload(UnloadFn fn) = 0;
+
//! Register handler for show progress messages.
using ShowProgressFn = std::function<void(const std::string& title, int progress)>;
virtual std::unique_ptr<Handler> handleShowProgress(ShowProgressFn fn) = 0;
diff --git a/src/miner.cpp b/src/miner.cpp
index d4527a1d67..738ccad1b9 100644
--- a/src/miner.cpp
+++ b/src/miner.cpp
@@ -209,7 +209,7 @@ bool BlockAssembler::TestPackage(uint64_t packageSize, int64_t packageSigOpsCost
// segwit activation)
bool BlockAssembler::TestPackageTransactions(const CTxMemPool::setEntries& package)
{
- for (const CTxMemPool::txiter it : package) {
+ for (CTxMemPool::txiter it : package) {
if (!IsFinalTx(it->GetTx(), nHeight, nLockTimeCutoff))
return false;
if (!fIncludeWitness && it->GetTx().HasWitness())
@@ -241,7 +241,7 @@ int BlockAssembler::UpdatePackagesForAdded(const CTxMemPool::setEntries& already
indexed_modified_transaction_set &mapModifiedTx)
{
int nDescendantsUpdated = 0;
- for (const CTxMemPool::txiter it : alreadyAdded) {
+ for (CTxMemPool::txiter it : alreadyAdded) {
CTxMemPool::setEntries descendants;
mempool.CalculateDescendants(it, descendants);
// Insert all descendants (not yet in block) into the modified set
diff --git a/src/qt/README.md b/src/qt/README.md
index bf8139666c..3ec538b4f4 100644
--- a/src/qt/README.md
+++ b/src/qt/README.md
@@ -1,6 +1,6 @@
This directory contains the BitcoinQT graphical user interface (GUI). It uses the cross-platform framework [Qt](https://www1.qt.io/developers/).
-The current precise version for Qt 5 is specified in [qt.mk](/depends/packages/qt.mk). Qt 4 is also supported (see [#8263](https://github.com/bitcoin/bitcoin/issues/8263)).
+The current precise version for Qt 5 is specified in [qt.mk](/depends/packages/qt.mk).
## Compile and run
@@ -16,7 +16,7 @@ To run:
### forms
-Contains [Designer UI](http://doc.qt.io/qt-5.9/designer-using-a-ui-file.html) files. They are created with [Qt Creator](#using-qt-creator-as-ide), but can be edited using any text editor.
+Contains [Designer UI](https://doc.qt.io/qt-5.9/designer-using-a-ui-file.html) files. They are created with [Qt Creator](#using-qt-creator-as-ide), but can be edited using any text editor.
### locale
@@ -36,7 +36,7 @@ Represents the main window of the Bitcoin UI.
### \*model.(h/cpp)
-The model. When it has a corresponding controller, it generally inherits from [QAbstractTableModel](http://doc.qt.io/qt-5/qabstracttablemodel.html). Models that are used by controllers as helpers inherit from other Qt classes like [QValidator](http://doc.qt.io/qt-5/qvalidator.html).
+The model. When it has a corresponding controller, it generally inherits from [QAbstractTableModel](https://doc.qt.io/qt-5/qabstracttablemodel.html). Models that are used by controllers as helpers inherit from other Qt classes like [QValidator](https://doc.qt.io/qt-5/qvalidator.html).
ClientModel is used by the main application `bitcoingui` and several models like `peertablemodel`.
@@ -46,7 +46,7 @@ A controller. `:NAMEpage.cpp` generally includes `:NAMEmodel.h` and `forms/:NAME
### \*dialog.(h/cpp)
-Various dialogs, e.g. to open a URL. Inherit from [QDialog](http://doc.qt.io/qt-4.8/qdialog.html).
+Various dialogs, e.g. to open a URL. Inherit from [QDialog](https://doc.qt.io/qt-5/qdialog.html).
### paymentserver.(h/cpp)
diff --git a/src/qt/addressbookpage.cpp b/src/qt/addressbookpage.cpp
index f2ddbf259b..d51069d922 100644
--- a/src/qt/addressbookpage.cpp
+++ b/src/qt/addressbookpage.cpp
@@ -160,13 +160,8 @@ void AddressBookPage::setModel(AddressTableModel *_model)
ui->tableView->sortByColumn(0, Qt::AscendingOrder);
// Set column widths
-#if QT_VERSION < 0x050000
- ui->tableView->horizontalHeader()->setResizeMode(AddressTableModel::Label, QHeaderView::Stretch);
- ui->tableView->horizontalHeader()->setResizeMode(AddressTableModel::Address, QHeaderView::ResizeToContents);
-#else
ui->tableView->horizontalHeader()->setSectionResizeMode(AddressTableModel::Label, QHeaderView::Stretch);
ui->tableView->horizontalHeader()->setSectionResizeMode(AddressTableModel::Address, QHeaderView::ResizeToContents);
-#endif
connect(ui->tableView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
this, SLOT(selectionChanged()));
diff --git a/src/qt/bantablemodel.cpp b/src/qt/bantablemodel.cpp
index 26cb03c2c7..aa0d4a31d3 100644
--- a/src/qt/bantablemodel.cpp
+++ b/src/qt/bantablemodel.cpp
@@ -52,9 +52,7 @@ public:
node.getBanned(banMap);
cachedBanlist.clear();
-#if QT_VERSION >= 0x040700
cachedBanlist.reserve(banMap.size());
-#endif
for (const auto& entry : banMap)
{
CCombinedBan banEntry;
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp
index 31d9f936e7..e3d1c746b1 100644
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -55,13 +55,6 @@
#if defined(QT_STATICPLUGIN)
#include <QtPlugin>
-#if QT_VERSION < 0x050000
-Q_IMPORT_PLUGIN(qcncodecs)
-Q_IMPORT_PLUGIN(qjpcodecs)
-Q_IMPORT_PLUGIN(qtwcodecs)
-Q_IMPORT_PLUGIN(qkrcodecs)
-Q_IMPORT_PLUGIN(qtaccessiblewidgets)
-#else
#if QT_VERSION < 0x050400
Q_IMPORT_PLUGIN(AccessibleFactory)
#endif
@@ -73,11 +66,6 @@ Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin);
Q_IMPORT_PLUGIN(QCocoaIntegrationPlugin);
#endif
#endif
-#endif
-
-#if QT_VERSION < 0x050000
-#include <QTextCodec>
-#endif
// Declare meta types used for QMetaObject::invokeMethod
Q_DECLARE_METATYPE(bool*)
@@ -151,16 +139,6 @@ static void initTranslations(QTranslator &qtTranslatorBase, QTranslator &qtTrans
}
/* qDebug() message handler --> debug.log */
-#if QT_VERSION < 0x050000
-void DebugMessageHandler(QtMsgType type, const char *msg)
-{
- if (type == QtDebugMsg) {
- LogPrint(BCLog::QT, "GUI: %s\n", msg);
- } else {
- LogPrintf("GUI: %s\n", msg);
- }
-}
-#else
void DebugMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString &msg)
{
Q_UNUSED(context);
@@ -170,7 +148,6 @@ void DebugMessageHandler(QtMsgType type, const QMessageLogContext& context, cons
LogPrintf("GUI: %s\n", msg.toStdString());
}
}
-#endif
/** Class encapsulating Bitcoin Core startup and shutdown.
* Allows running startup and shutdown in a different thread from the UI thread.
@@ -238,6 +215,7 @@ public Q_SLOTS:
/// 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();
@@ -467,11 +445,22 @@ void BitcoinApplication::addWallet(WalletModel* walletModel)
connect(walletModel, SIGNAL(coinsSent(WalletModel*, SendCoinsRecipient, QByteArray)),
paymentServer, SLOT(fetchPaymentACK(WalletModel*, const SendCoinsRecipient&, QByteArray)));
+ connect(walletModel, SIGNAL(unload()), this, SLOT(removeWallet()));
m_wallet_models.push_back(walletModel);
#endif
}
+void BitcoinApplication::removeWallet()
+{
+#ifdef ENABLE_WALLET
+ WalletModel* walletModel = static_cast<WalletModel*>(sender());
+ m_wallet_models.erase(std::find(m_wallet_models.begin(), m_wallet_models.end(), walletModel));
+ window->removeWallet(walletModel);
+ walletModel->deleteLater();
+#endif
+}
+
void BitcoinApplication::initializeResult(bool success)
{
qDebug() << __func__ << ": Initialization result: " << success;
@@ -491,8 +480,10 @@ void BitcoinApplication::initializeResult(bool success)
#ifdef ENABLE_WALLET
m_handler_load_wallet = m_node.handleLoadWallet([this](std::unique_ptr<interfaces::Wallet> wallet) {
- QMetaObject::invokeMethod(this, "addWallet", Qt::QueuedConnection,
- Q_ARG(WalletModel*, new WalletModel(std::move(wallet), m_node, platformStyle, optionsModel)));
+ WalletModel* wallet_model = new WalletModel(std::move(wallet), m_node, platformStyle, optionsModel, nullptr);
+ // Fix wallet model thread affinity.
+ wallet_model->moveToThread(thread());
+ QMetaObject::invokeMethod(this, "addWallet", Qt::QueuedConnection, Q_ARG(WalletModel*, wallet_model));
});
for (auto& wallet : m_node.getWallets()) {
@@ -572,12 +563,6 @@ int main(int argc, char *argv[])
// Do not refer to data directory yet, this can be overridden by Intro::pickDataDirectory
/// 1. Basic Qt initialization (not dependent on parameters or configuration)
-#if QT_VERSION < 0x050000
- // Internal string conversion is all UTF-8
- QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
- QTextCodec::setCodecForCStrings(QTextCodec::codecForTr());
-#endif
-
Q_INIT_RESOURCE(bitcoin);
Q_INIT_RESOURCE(bitcoin_locale);
@@ -708,17 +693,12 @@ int main(int argc, char *argv[])
/// 9. Main GUI initialization
// Install global event filter that makes sure that long tooltips can be word-wrapped
app.installEventFilter(new GUIUtil::ToolTipToRichTextFilter(TOOLTIP_WRAP_THRESHOLD, &app));
-#if QT_VERSION < 0x050000
- // Install qDebug() message handler to route to debug.log
- qInstallMsgHandler(DebugMessageHandler);
-#else
#if defined(Q_OS_WIN)
// Install global event filter for processing Windows session related Windows messages (WM_QUERYENDSESSION and WM_ENDSESSION)
qApp->installNativeEventFilter(new WinShutdownMonitor());
#endif
// Install qDebug() message handler to route to debug.log
qInstallMessageHandler(DebugMessageHandler);
-#endif
// Allow parameter interaction before we create the options model
app.parameterSetup();
// Load GUI settings from QSettings
@@ -739,7 +719,7 @@ int main(int argc, char *argv[])
// so the GUI thread won't be held up.
if (node->baseInitialize()) {
app.requestInitialize();
-#if defined(Q_OS_WIN) && QT_VERSION >= 0x050000
+#if defined(Q_OS_WIN)
WinShutdownMonitor::registerShutdownBlockReason(QObject::tr("%1 didn't yet exit safely...").arg(QObject::tr(PACKAGE_NAME)), (HWND)app.getMainWinId());
#endif
app.exec();
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index 9f5ea02e14..df78652376 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -55,14 +55,8 @@
#include <QStyle>
#include <QTimer>
#include <QToolBar>
-#include <QVBoxLayout>
-
-#if QT_VERSION < 0x050000
-#include <QTextDocument>
-#include <QUrl>
-#else
#include <QUrlQuery>
-#endif
+#include <QVBoxLayout>
const std::string BitcoinGUI::DEFAULT_UIPLATFORM =
#if defined(Q_OS_MAC)
@@ -76,50 +70,7 @@ const std::string BitcoinGUI::DEFAULT_UIPLATFORM =
BitcoinGUI::BitcoinGUI(interfaces::Node& node, const PlatformStyle *_platformStyle, const NetworkStyle *networkStyle, QWidget *parent) :
QMainWindow(parent),
- enableWallet(false),
m_node(node),
- clientModel(0),
- walletFrame(0),
- unitDisplayControl(0),
- labelWalletEncryptionIcon(0),
- labelWalletHDStatusIcon(0),
- labelProxyIcon(0),
- connectionsControl(0),
- labelBlocksIcon(0),
- progressBarLabel(0),
- progressBar(0),
- progressDialog(0),
- appMenuBar(0),
- appToolBar(0),
- overviewAction(0),
- historyAction(0),
- quitAction(0),
- sendCoinsAction(0),
- sendCoinsMenuAction(0),
- usedSendingAddressesAction(0),
- usedReceivingAddressesAction(0),
- signMessageAction(0),
- verifyMessageAction(0),
- aboutAction(0),
- receiveCoinsAction(0),
- receiveCoinsMenuAction(0),
- optionsAction(0),
- toggleHideAction(0),
- encryptWalletAction(0),
- backupWalletAction(0),
- changePassphraseAction(0),
- aboutQtAction(0),
- openRPCConsoleAction(0),
- openAction(0),
- showHelpMessageAction(0),
- trayIcon(0),
- trayIconMenu(0),
- notificator(0),
- rpcConsole(0),
- helpMessageDialog(0),
- modalOverlay(0),
- prevBlocks(0),
- spinnerFrame(0),
platformStyle(_platformStyle)
{
QSettings settings;
@@ -147,12 +98,6 @@ BitcoinGUI::BitcoinGUI(interfaces::Node& node, const PlatformStyle *_platformSty
#endif
setWindowTitle(windowTitle);
-#if defined(Q_OS_MAC) && QT_VERSION < 0x050000
- // This property is not implemented in Qt 5. Setting it has no effect.
- // A replacement API (QtMacUnifiedToolBar) is available in QtMacExtras.
- setUnifiedTitleAndToolBarOnMac(true);
-#endif
-
rpcConsole = new RPCConsole(node, _platformStyle, 0);
helpMessageDialog = new HelpMessageDialog(node, this, false);
#ifdef ENABLE_WALLET
@@ -229,7 +174,7 @@ BitcoinGUI::BitcoinGUI(interfaces::Node& node, const PlatformStyle *_platformSty
// Override style sheet for progress bar for styles that have a segmented progress bar,
// as they make the text unreadable (workaround for issue #1071)
- // See https://qt-project.org/doc/qt-4.8/gallery.html
+ // See https://doc.qt.io/qt-5/gallery.html
QString curStyle = QApplication::style()->metaObject()->className();
if(curStyle == "QWindowsStyle" || curStyle == "QWindowsXPStyle")
{
@@ -477,6 +422,16 @@ void BitcoinGUI::createToolBars()
m_wallet_selector = new QComboBox();
connect(m_wallet_selector, SIGNAL(currentIndexChanged(int)), this, SLOT(setCurrentWalletBySelectorIndex(int)));
+
+ m_wallet_selector_label = new QLabel();
+ m_wallet_selector_label->setText(tr("Wallet:") + " ");
+ m_wallet_selector_label->setBuddy(m_wallet_selector);
+
+ m_wallet_selector_label_action = appToolBar->addWidget(m_wallet_selector_label);
+ m_wallet_selector_action = appToolBar->addWidget(m_wallet_selector);
+
+ m_wallet_selector_label_action->setVisible(false);
+ m_wallet_selector_action->setVisible(false);
#endif
}
}
@@ -556,16 +511,29 @@ bool BitcoinGUI::addWallet(WalletModel *walletModel)
setWalletActionsEnabled(true);
m_wallet_selector->addItem(display_name, name);
if (m_wallet_selector->count() == 2) {
- m_wallet_selector_label = new QLabel();
- m_wallet_selector_label->setText(tr("Wallet:") + " ");
- m_wallet_selector_label->setBuddy(m_wallet_selector);
- appToolBar->addWidget(m_wallet_selector_label);
- appToolBar->addWidget(m_wallet_selector);
+ m_wallet_selector_label_action->setVisible(true);
+ m_wallet_selector_action->setVisible(true);
}
rpcConsole->addWallet(walletModel);
return walletFrame->addWallet(walletModel);
}
+bool BitcoinGUI::removeWallet(WalletModel* walletModel)
+{
+ if (!walletFrame) return false;
+ QString name = walletModel->getWalletName();
+ int index = m_wallet_selector->findData(name);
+ m_wallet_selector->removeItem(index);
+ if (m_wallet_selector->count() == 0) {
+ setWalletActionsEnabled(false);
+ } else if (m_wallet_selector->count() == 1) {
+ m_wallet_selector_label_action->setVisible(false);
+ m_wallet_selector_action->setVisible(false);
+ }
+ rpcConsole->removeWallet(walletModel);
+ return walletFrame->removeWallet(name);
+}
+
bool BitcoinGUI::setCurrentWallet(const QString& name)
{
if(!walletFrame)
diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h
index 89c1c73a79..964e04f848 100644
--- a/src/qt/bitcoingui.h
+++ b/src/qt/bitcoingui.h
@@ -70,9 +70,10 @@ public:
functionality.
*/
bool addWallet(WalletModel *walletModel);
+ bool removeWallet(WalletModel* walletModel);
void removeAllWallets();
#endif // ENABLE_WALLET
- bool enableWallet;
+ bool enableWallet = false;
protected:
void changeEvent(QEvent *e);
@@ -86,56 +87,58 @@ private:
interfaces::Node& m_node;
std::unique_ptr<interfaces::Handler> m_handler_message_box;
std::unique_ptr<interfaces::Handler> m_handler_question;
- ClientModel *clientModel;
- WalletFrame *walletFrame;
-
- UnitDisplayStatusBarControl *unitDisplayControl;
- QLabel *labelWalletEncryptionIcon;
- QLabel *labelWalletHDStatusIcon;
- QLabel *labelProxyIcon;
- QLabel *connectionsControl;
- QLabel *labelBlocksIcon;
- QLabel *progressBarLabel;
- QProgressBar *progressBar;
- QProgressDialog *progressDialog;
-
- QMenuBar *appMenuBar;
- QToolBar *appToolBar;
- QAction *overviewAction;
- QAction *historyAction;
- QAction *quitAction;
- QAction *sendCoinsAction;
- QAction *sendCoinsMenuAction;
- QAction *usedSendingAddressesAction;
- QAction *usedReceivingAddressesAction;
- QAction *signMessageAction;
- QAction *verifyMessageAction;
- QAction *aboutAction;
- QAction *receiveCoinsAction;
- QAction *receiveCoinsMenuAction;
- QAction *optionsAction;
- QAction *toggleHideAction;
- QAction *encryptWalletAction;
- QAction *backupWalletAction;
- QAction *changePassphraseAction;
- QAction *aboutQtAction;
- QAction *openRPCConsoleAction;
- QAction *openAction;
- QAction *showHelpMessageAction;
-
- QLabel *m_wallet_selector_label;
- QComboBox *m_wallet_selector;
-
- QSystemTrayIcon *trayIcon;
- QMenu *trayIconMenu;
- Notificator *notificator;
- RPCConsole *rpcConsole;
- HelpMessageDialog *helpMessageDialog;
- ModalOverlay *modalOverlay;
+ ClientModel* clientModel = nullptr;
+ WalletFrame* walletFrame = nullptr;
+
+ UnitDisplayStatusBarControl* unitDisplayControl = nullptr;
+ QLabel* labelWalletEncryptionIcon = nullptr;
+ QLabel* labelWalletHDStatusIcon = nullptr;
+ QLabel* labelProxyIcon = nullptr;
+ QLabel* connectionsControl = nullptr;
+ QLabel* labelBlocksIcon = nullptr;
+ QLabel* progressBarLabel = nullptr;
+ QProgressBar* progressBar = nullptr;
+ QProgressDialog* progressDialog = nullptr;
+
+ QMenuBar* appMenuBar = nullptr;
+ QToolBar* appToolBar = nullptr;
+ QAction* overviewAction = nullptr;
+ QAction* historyAction = nullptr;
+ QAction* quitAction = nullptr;
+ QAction* sendCoinsAction = nullptr;
+ QAction* sendCoinsMenuAction = nullptr;
+ QAction* usedSendingAddressesAction = nullptr;
+ QAction* usedReceivingAddressesAction = nullptr;
+ QAction* signMessageAction = nullptr;
+ QAction* verifyMessageAction = nullptr;
+ QAction* aboutAction = nullptr;
+ QAction* receiveCoinsAction = nullptr;
+ QAction* receiveCoinsMenuAction = nullptr;
+ QAction* optionsAction = nullptr;
+ QAction* toggleHideAction = nullptr;
+ QAction* encryptWalletAction = nullptr;
+ QAction* backupWalletAction = nullptr;
+ QAction* changePassphraseAction = nullptr;
+ QAction* aboutQtAction = nullptr;
+ QAction* openRPCConsoleAction = nullptr;
+ QAction* openAction = nullptr;
+ QAction* showHelpMessageAction = nullptr;
+ QAction* m_wallet_selector_label_action = nullptr;
+ QAction* m_wallet_selector_action = nullptr;
+
+ QLabel *m_wallet_selector_label = nullptr;
+ QComboBox* m_wallet_selector = nullptr;
+
+ QSystemTrayIcon* trayIcon = nullptr;
+ QMenu* trayIconMenu = nullptr;
+ Notificator* notificator = nullptr;
+ RPCConsole* rpcConsole = nullptr;
+ HelpMessageDialog* helpMessageDialog = nullptr;
+ ModalOverlay* modalOverlay = nullptr;
/** Keep track of previous number of blocks, to detect progress */
- int prevBlocks;
- int spinnerFrame;
+ int prevBlocks = 0;
+ int spinnerFrame = 0;
const PlatformStyle *platformStyle;
diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp
index b08de27041..9b6480a915 100644
--- a/src/qt/coincontroldialog.cpp
+++ b/src/qt/coincontroldialog.cpp
@@ -109,11 +109,7 @@ CoinControlDialog::CoinControlDialog(const PlatformStyle *_platformStyle, QWidge
connect(ui->treeWidget, SIGNAL(itemChanged(QTreeWidgetItem*, int)), this, SLOT(viewItemChanged(QTreeWidgetItem*, int)));
// click on header
-#if QT_VERSION < 0x050000
- ui->treeWidget->header()->setClickable(true);
-#else
ui->treeWidget->header()->setSectionsClickable(true);
-#endif
connect(ui->treeWidget->header(), SIGNAL(sectionClicked(int)), this, SLOT(headerSectionClicked(int)));
// ok button
@@ -122,10 +118,6 @@ CoinControlDialog::CoinControlDialog(const PlatformStyle *_platformStyle, QWidge
// (un)select all
connect(ui->pushButtonSelectAll, SIGNAL(clicked()), this, SLOT(buttonSelectAllClicked()));
- // change coin control first column label due Qt4 bug.
- // see https://github.com/bitcoin/bitcoin/issues/5716
- ui->treeWidget->headerItem()->setText(COLUMN_CHECKBOX, QString());
-
ui->treeWidget->setColumnWidth(COLUMN_CHECKBOX, 84);
ui->treeWidget->setColumnWidth(COLUMN_AMOUNT, 110);
ui->treeWidget->setColumnWidth(COLUMN_LABEL, 190);
@@ -392,13 +384,11 @@ void CoinControlDialog::viewItemChanged(QTreeWidgetItem* item, int column)
// TODO: Remove this temporary qt5 fix after Qt5.3 and Qt5.4 are no longer used.
// Fixed in Qt5.5 and above: https://bugreports.qt.io/browse/QTBUG-43473
-#if QT_VERSION >= 0x050000
else if (column == COLUMN_CHECKBOX && item->childCount() > 0)
{
if (item->checkState(COLUMN_CHECKBOX) == Qt::PartiallyChecked && item->child(0)->checkState(COLUMN_CHECKBOX) == Qt::PartiallyChecked)
item->setCheckState(COLUMN_CHECKBOX, Qt::Checked);
}
-#endif
}
// shows count of locked unspent outputs
diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp
index 563f930dec..acd9f7b35c 100644
--- a/src/qt/guiutil.cpp
+++ b/src/qt/guiutil.cpp
@@ -53,13 +53,9 @@
#include <QSettings>
#include <QTextDocument> // for Qt::mightBeRichText
#include <QThread>
+#include <QUrlQuery>
#include <QMouseEvent>
-#if QT_VERSION < 0x050000
-#include <QUrl>
-#else
-#include <QUrlQuery>
-#endif
#if QT_VERSION >= 0x50200
#include <QFontDatabase>
@@ -95,11 +91,7 @@ QFont fixedPitchFont()
return QFontDatabase::systemFont(QFontDatabase::FixedFont);
#else
QFont font("Monospace");
-#if QT_VERSION >= 0x040800
font.setStyleHint(QFont::Monospace);
-#else
- font.setStyleHint(QFont::TypeWriter);
-#endif
return font;
#endif
}
@@ -127,12 +119,10 @@ void setupAddressWidget(QValidatedLineEdit *widget, QWidget *parent)
parent->setFocusProxy(widget);
widget->setFont(fixedPitchFont());
-#if QT_VERSION >= 0x040700
// We don't want translators to use own addresses in translations
// and this is the only place, where this address is supplied.
widget->setPlaceholderText(QObject::tr("Enter a Bitcoin address (e.g. %1)").arg(
QString::fromStdString(DummyAddress(Params()))));
-#endif
widget->setValidator(new BitcoinAddressEntryValidator(parent));
widget->setCheckValidator(new BitcoinAddressCheckValidator(parent));
}
@@ -151,12 +141,8 @@ bool parseBitcoinURI(const QUrl &uri, SendCoinsRecipient *out)
}
rv.amount = 0;
-#if QT_VERSION < 0x050000
- QList<QPair<QString, QString> > items = uri.queryItems();
-#else
QUrlQuery uriQuery(uri);
QList<QPair<QString, QString> > items = uriQuery.queryItems();
-#endif
for (QList<QPair<QString, QString> >::iterator i = items.begin(); i != items.end(); i++)
{
bool fShouldReturnFalse = false;
@@ -242,11 +228,7 @@ bool isDust(interfaces::Node& node, const QString& address, const CAmount& amoun
QString HtmlEscape(const QString& str, bool fMultiLine)
{
-#if QT_VERSION < 0x050000
- QString escaped = Qt::escape(str);
-#else
QString escaped = str.toHtmlEscaped();
-#endif
if(fMultiLine)
{
escaped = escaped.replace("\n", "<br>\n");
@@ -287,11 +269,7 @@ QString getSaveFileName(QWidget *parent, const QString &caption, const QString &
QString myDir;
if(dir.isEmpty()) // Default to user documents location
{
-#if QT_VERSION < 0x050000
- myDir = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation);
-#else
myDir = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
-#endif
}
else
{
@@ -337,11 +315,7 @@ QString getOpenFileName(QWidget *parent, const QString &caption, const QString &
QString myDir;
if(dir.isEmpty()) // Default to user documents location
{
-#if QT_VERSION < 0x050000
- myDir = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation);
-#else
myDir = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
-#endif
}
else
{
@@ -495,11 +469,7 @@ void TableViewLastColumnResizingFixer::disconnectViewHeadersSignals()
// Refactored here for readability.
void TableViewLastColumnResizingFixer::setViewHeaderResizeMode(int logicalIndex, QHeaderView::ResizeMode resizeMode)
{
-#if QT_VERSION < 0x050000
- tableView->horizontalHeader()->setResizeMode(logicalIndex, resizeMode);
-#else
tableView->horizontalHeader()->setSectionResizeMode(logicalIndex, resizeMode);
-#endif
}
void TableViewLastColumnResizingFixer::resizeColumn(int nColumnIndex, int width)
diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h
index 4a26964098..e965a91d18 100644
--- a/src/qt/guiutil.h
+++ b/src/qt/guiutil.h
@@ -233,7 +233,7 @@ namespace GUIUtil
void mouseReleaseEvent(QMouseEvent *event);
};
-#if defined(Q_OS_MAC) && QT_VERSION >= 0x050000
+#if defined(Q_OS_MAC)
// workaround for Qt OSX Bug:
// https://bugreports.qt-project.org/browse/QTBUG-15631
// QProgressBar uses around 10% CPU even when app is in background
diff --git a/src/qt/macdockiconhandler.mm b/src/qt/macdockiconhandler.mm
index 9e7de0f98f..a0b62ae000 100644
--- a/src/qt/macdockiconhandler.mm
+++ b/src/qt/macdockiconhandler.mm
@@ -14,10 +14,6 @@
#include <objc/objc.h>
#include <objc/message.h>
-#if QT_VERSION < 0x050000
-extern void qt_mac_set_dock_menu(QMenu *);
-#endif
-
static MacDockIconHandler *s_instance = nullptr;
bool dockClickHandler(id self,SEL _cmd,...) {
@@ -54,9 +50,7 @@ MacDockIconHandler::MacDockIconHandler() : QObject()
this->m_dummyWidget = new QWidget();
this->m_dockMenu = new QMenu(this->m_dummyWidget);
this->setMainWindow(nullptr);
-#if QT_VERSION < 0x050000
- qt_mac_set_dock_menu(this->m_dockMenu);
-#elif QT_VERSION >= 0x050200
+#if QT_VERSION >= 0x050200
this->m_dockMenu->setAsDockMenu();
#endif
[pool release];
diff --git a/src/qt/networkstyle.cpp b/src/qt/networkstyle.cpp
index 2816633b0f..c4b732e3e0 100644
--- a/src/qt/networkstyle.cpp
+++ b/src/qt/networkstyle.cpp
@@ -68,11 +68,7 @@ NetworkStyle::NetworkStyle(const QString &_appName, const int iconColorHueShift,
}
//convert back to QPixmap
-#if QT_VERSION >= 0x040700
pixmap.convertFromImage(img);
-#else
- pixmap = QPixmap::fromImage(img);
-#endif
}
appIcon = QIcon(pixmap);
diff --git a/src/qt/openuridialog.cpp b/src/qt/openuridialog.cpp
index 751cfa8b43..d211f908c8 100644
--- a/src/qt/openuridialog.cpp
+++ b/src/qt/openuridialog.cpp
@@ -15,9 +15,7 @@ OpenURIDialog::OpenURIDialog(QWidget *parent) :
ui(new Ui::OpenURIDialog)
{
ui->setupUi(this);
-#if QT_VERSION >= 0x040700
ui->uriEdit->setPlaceholderText("bitcoin:");
-#endif
}
OpenURIDialog::~OpenURIDialog()
diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp
index 108aa4f99c..3ff6f59c25 100644
--- a/src/qt/optionsdialog.cpp
+++ b/src/qt/optionsdialog.cpp
@@ -97,28 +97,16 @@ OptionsDialog::OptionsDialog(QWidget *parent, bool enableWallet) :
/** check if the locale name consists of 2 parts (language_country) */
if(langStr.contains("_"))
{
-#if QT_VERSION >= 0x040800
/** display language strings as "native language - native country (locale name)", e.g. "Deutsch - Deutschland (de)" */
ui->lang->addItem(locale.nativeLanguageName() + QString(" - ") + locale.nativeCountryName() + QString(" (") + langStr + QString(")"), QVariant(langStr));
-#else
- /** display language strings as "language - country (locale name)", e.g. "German - Germany (de)" */
- ui->lang->addItem(QLocale::languageToString(locale.language()) + QString(" - ") + QLocale::countryToString(locale.country()) + QString(" (") + langStr + QString(")"), QVariant(langStr));
-#endif
}
else
{
-#if QT_VERSION >= 0x040800
/** display language strings as "native language (locale name)", e.g. "Deutsch (de)" */
ui->lang->addItem(locale.nativeLanguageName() + QString(" (") + langStr + QString(")"), QVariant(langStr));
-#else
- /** display language strings as "language (locale name)", e.g. "German (de)" */
- ui->lang->addItem(QLocale::languageToString(locale.language()) + QString(" (") + langStr + QString(")"), QVariant(langStr));
-#endif
}
}
-#if QT_VERSION >= 0x040700
ui->thirdPartyTxUrls->setPlaceholderText("https://example.com/tx/%s");
-#endif
ui->unit->setModel(new BitcoinUnits(this));
diff --git a/src/qt/paymentrequestplus.cpp b/src/qt/paymentrequestplus.cpp
index b0ef475b35..dfeb70d669 100644
--- a/src/qt/paymentrequestplus.cpp
+++ b/src/qt/paymentrequestplus.cpp
@@ -97,12 +97,10 @@ bool PaymentRequestPlus::getMerchant(X509_STORE* certStore, QString& merchant) c
qWarning() << "PaymentRequestPlus::getMerchant: Payment request: certificate expired or not yet active: " << qCert;
return false;
}
-#if QT_VERSION >= 0x050000
if (qCert.isBlacklisted()) {
qWarning() << "PaymentRequestPlus::getMerchant: Payment request: certificate blacklisted: " << qCert;
return false;
}
-#endif
const unsigned char *data = (const unsigned char *)certChain.certificate(i).data();
X509 *cert = d2i_X509(nullptr, &data, certChain.certificate(i).size());
if (cert)
diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp
index 59bb5d5bb6..e5e6430959 100644
--- a/src/qt/paymentserver.cpp
+++ b/src/qt/paymentserver.cpp
@@ -41,12 +41,7 @@
#include <QSslSocket>
#include <QStringList>
#include <QTextDocument>
-
-#if QT_VERSION < 0x050000
-#include <QUrl>
-#else
#include <QUrlQuery>
-#endif
const int BITCOIN_IPC_CONNECT_TIMEOUT = 1000; // milliseconds
const QString BITCOIN_IPC_PREFIX("bitcoin:");
@@ -100,11 +95,7 @@ static QList<QString> savedPaymentRequests;
static void ReportInvalidCertificate(const QSslCertificate& cert)
{
-#if QT_VERSION < 0x050000
- qDebug() << QString("%1: Payment server found an invalid certificate: ").arg(__func__) << cert.serialNumber() << cert.subjectInfo(QSslCertificate::CommonName) << cert.subjectInfo(QSslCertificate::OrganizationalUnitName);
-#else
qDebug() << QString("%1: Payment server found an invalid certificate: ").arg(__func__) << cert.serialNumber() << cert.subjectInfo(QSslCertificate::CommonName) << cert.subjectInfo(QSslCertificate::DistinguishedNameQualifier) << cert.subjectInfo(QSslCertificate::OrganizationalUnitName);
-#endif
}
//
@@ -157,13 +148,11 @@ void PaymentServer::LoadRootCAs(X509_STORE* _store)
continue;
}
-#if QT_VERSION >= 0x050000
// Blacklisted certificate
if (cert.isBlacklisted()) {
ReportInvalidCertificate(cert);
continue;
}
-#endif
QByteArray certData = cert.toDer();
const unsigned char *data = (const unsigned char *)certData.data();
@@ -413,11 +402,7 @@ void PaymentServer::handleURIOrFile(const QString& s)
}
else if (s.startsWith(BITCOIN_IPC_PREFIX, Qt::CaseInsensitive)) // bitcoin: URI
{
-#if QT_VERSION < 0x050000
- QUrl uri(s);
-#else
QUrlQuery uri((QUrl(s)));
-#endif
if (uri.hasQueryItem("r")) // payment request URI
{
QByteArray temp;
diff --git a/src/qt/peertablemodel.cpp b/src/qt/peertablemodel.cpp
index 7e318e3035..0ca9d48bf6 100644
--- a/src/qt/peertablemodel.cpp
+++ b/src/qt/peertablemodel.cpp
@@ -64,9 +64,7 @@ public:
interfaces::Node::NodesStats nodes_stats;
node.getNodesStats(nodes_stats);
-#if QT_VERSION >= 0x040700
cachedNodeStats.reserve(nodes_stats.size());
-#endif
for (auto& node_stats : nodes_stats)
{
CNodeCombinedStats stats;
diff --git a/src/qt/platformstyle.cpp b/src/qt/platformstyle.cpp
index fce71f661a..a3a10aac18 100644
--- a/src/qt/platformstyle.cpp
+++ b/src/qt/platformstyle.cpp
@@ -46,7 +46,7 @@ void MakeSingleColorImage(QImage& img, const QColor& colorbase)
QIcon ColorizeIcon(const QIcon& ico, const QColor& colorbase)
{
QIcon new_ico;
- for (const QSize sz : ico.availableSizes())
+ for (const QSize& sz : ico.availableSizes())
{
QImage img(ico.pixmap(sz).toImage());
MakeSingleColorImage(img, colorbase);
diff --git a/src/qt/receiverequestdialog.cpp b/src/qt/receiverequestdialog.cpp
index 75146e2214..f9610f2d3b 100644
--- a/src/qt/receiverequestdialog.cpp
+++ b/src/qt/receiverequestdialog.cpp
@@ -16,9 +16,6 @@
#include <QMimeData>
#include <QMouseEvent>
#include <QPixmap>
-#if QT_VERSION < 0x050000
-#include <QUrl>
-#endif
#if defined(HAVE_CONFIG_H)
#include <config/bitcoin-config.h> /* for USE_QRCODE */
diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp
index 4550ae9396..f222357f27 100644
--- a/src/qt/rpcconsole.cpp
+++ b/src/qt/rpcconsole.cpp
@@ -40,10 +40,6 @@
#include <QTimer>
#include <QStringList>
-#if QT_VERSION < 0x050000
-#include <QUrl>
-#endif
-
// TODO: add a scrollback limit, as there is currently none
// TODO: make it possible to filter out categories (esp debug messages when implemented)
// TODO: receive errors and debug messages through ClientModel
@@ -713,6 +709,16 @@ void RPCConsole::addWallet(WalletModel * const walletModel)
ui->WalletSelectorLabel->setVisible(true);
}
}
+
+void RPCConsole::removeWallet(WalletModel * const walletModel)
+{
+ const QString name = walletModel->getWalletName();
+ ui->WalletSelector->removeItem(ui->WalletSelector->findData(name));
+ if (ui->WalletSelector->count() == 2) {
+ ui->WalletSelector->setVisible(false);
+ ui->WalletSelectorLabel->setVisible(false);
+ }
+}
#endif
static QString categoryClass(int category)
diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h
index a53c4c24f9..0a1a469934 100644
--- a/src/qt/rpcconsole.h
+++ b/src/qt/rpcconsole.h
@@ -48,6 +48,7 @@ public:
void setClientModel(ClientModel *model);
void addWallet(WalletModel * const walletModel);
+ void removeWallet(WalletModel* const walletModel);
enum MessageClass {
MC_ERROR,
diff --git a/src/qt/sendcoinsentry.cpp b/src/qt/sendcoinsentry.cpp
index 977425f7e3..e8c85bc2a1 100644
--- a/src/qt/sendcoinsentry.cpp
+++ b/src/qt/sendcoinsentry.cpp
@@ -32,9 +32,7 @@ SendCoinsEntry::SendCoinsEntry(const PlatformStyle *_platformStyle, QWidget *par
if (platformStyle->getUseExtraSpacing())
ui->payToLayout->setSpacing(4);
-#if QT_VERSION >= 0x040700
ui->addAsLabel->setPlaceholderText(tr("Enter a label for this address to add it to your address book"));
-#endif
// normal bitcoin address field
GUIUtil::setupAddressWidget(ui->payTo, this);
diff --git a/src/qt/signverifymessagedialog.cpp b/src/qt/signverifymessagedialog.cpp
index 94a3ad7987..c8e694e658 100644
--- a/src/qt/signverifymessagedialog.cpp
+++ b/src/qt/signverifymessagedialog.cpp
@@ -37,9 +37,7 @@ SignVerifyMessageDialog::SignVerifyMessageDialog(const PlatformStyle *_platformS
ui->verifyMessageButton_VM->setIcon(platformStyle->SingleColorIcon(":/icons/transaction_0"));
ui->clearButton_VM->setIcon(platformStyle->SingleColorIcon(":/icons/remove"));
-#if QT_VERSION >= 0x040700
ui->signatureOut_SM->setPlaceholderText(tr("Click \"Sign Message\" to generate signature"));
-#endif
GUIUtil::setupAddressWidget(ui->addressIn_SM, this);
GUIUtil::setupAddressWidget(ui->addressIn_VM, this);
diff --git a/src/qt/test/test_main.cpp b/src/qt/test/test_main.cpp
index 56d4d3e457..f0ac43a58c 100644
--- a/src/qt/test/test_main.cpp
+++ b/src/qt/test/test_main.cpp
@@ -26,12 +26,6 @@
#if defined(QT_STATICPLUGIN)
#include <QtPlugin>
-#if QT_VERSION < 0x050000
-Q_IMPORT_PLUGIN(qcncodecs)
-Q_IMPORT_PLUGIN(qjpcodecs)
-Q_IMPORT_PLUGIN(qtwcodecs)
-Q_IMPORT_PLUGIN(qkrcodecs)
-#else
#if defined(QT_QPA_PLATFORM_MINIMAL)
Q_IMPORT_PLUGIN(QMinimalIntegrationPlugin);
#endif
@@ -43,7 +37,6 @@ Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin);
Q_IMPORT_PLUGIN(QCocoaIntegrationPlugin);
#endif
#endif
-#endif
extern void noui_connect();
diff --git a/src/qt/test/wallettests.cpp b/src/qt/test/wallettests.cpp
index 33c49dc7cb..c314dadde4 100644
--- a/src/qt/test/wallettests.cpp
+++ b/src/qt/test/wallettests.cpp
@@ -87,17 +87,6 @@ QModelIndex FindTx(const QAbstractItemModel& model, const uint256& txid)
return {};
}
-//! Request context menu (call method that is public in qt5, but protected in qt4).
-void RequestContextMenu(QWidget* widget)
-{
- class Qt4Hack : public QWidget
- {
- public:
- using QWidget::customContextMenuRequested;
- };
- static_cast<Qt4Hack*>(widget)->customContextMenuRequested({});
-}
-
//! Invoke bumpfee on txid and check results.
void BumpFee(TransactionView& view, const uint256& txid, bool expectDisabled, std::string expectError, bool cancel)
{
@@ -110,7 +99,7 @@ void BumpFee(TransactionView& view, const uint256& txid, bool expectDisabled, st
QAction* action = view.findChild<QAction*>("bumpFeeAction");
table->selectionModel()->select(index, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
action->setEnabled(expectDisabled);
- RequestContextMenu(table);
+ table->customContextMenuRequested({});
QCOMPARE(action->isEnabled(), !expectDisabled);
action->setEnabled(true);
diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp
index aa6444245a..e60a387934 100644
--- a/src/qt/transactionview.cpp
+++ b/src/qt/transactionview.cpp
@@ -95,15 +95,11 @@ TransactionView::TransactionView(const PlatformStyle *platformStyle, QWidget *pa
hlayout->addWidget(typeWidget);
search_widget = new QLineEdit(this);
-#if QT_VERSION >= 0x040700
search_widget->setPlaceholderText(tr("Enter address, transaction id, or label to search"));
-#endif
hlayout->addWidget(search_widget);
amountWidget = new QLineEdit(this);
-#if QT_VERSION >= 0x040700
amountWidget->setPlaceholderText(tr("Min amount"));
-#endif
if (platformStyle->getUseExtraSpacing()) {
amountWidget->setFixedWidth(97);
} else {
diff --git a/src/qt/walletframe.cpp b/src/qt/walletframe.cpp
index eb0eba21ef..c5a13f61f4 100644
--- a/src/qt/walletframe.cpp
+++ b/src/qt/walletframe.cpp
@@ -94,6 +94,7 @@ bool WalletFrame::removeWallet(const QString &name)
WalletView *walletView = mapWalletViews.take(name);
walletStack->removeWidget(walletView);
+ delete walletView;
return true;
}
diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp
index 3418b1f1a9..389acf0a95 100644
--- a/src/qt/walletmodel.cpp
+++ b/src/qt/walletmodel.cpp
@@ -364,6 +364,12 @@ bool WalletModel::changePassphrase(const SecureString &oldPass, const SecureStri
}
// Handlers for core signals
+static void NotifyUnload(WalletModel* walletModel)
+{
+ qDebug() << "NotifyUnload";
+ QMetaObject::invokeMethod(walletModel, "unload", Qt::QueuedConnection);
+}
+
static void NotifyKeyStoreStatusChanged(WalletModel *walletmodel)
{
qDebug() << "NotifyKeyStoreStatusChanged";
@@ -411,6 +417,7 @@ static void NotifyWatchonlyChanged(WalletModel *walletmodel, bool fHaveWatchonly
void WalletModel::subscribeToCoreSignals()
{
// Connect signals to wallet
+ m_handler_unload = m_wallet->handleUnload(boost::bind(&NotifyUnload, this));
m_handler_status_changed = m_wallet->handleStatusChanged(boost::bind(&NotifyKeyStoreStatusChanged, this));
m_handler_address_book_changed = m_wallet->handleAddressBookChanged(boost::bind(NotifyAddressBookChanged, this, _1, _2, _3, _4, _5));
m_handler_transaction_changed = m_wallet->handleTransactionChanged(boost::bind(NotifyTransactionChanged, this, _1, _2));
@@ -421,6 +428,7 @@ void WalletModel::subscribeToCoreSignals()
void WalletModel::unsubscribeFromCoreSignals()
{
// Disconnect signals from wallet
+ m_handler_unload->disconnect();
m_handler_status_changed->disconnect();
m_handler_address_book_changed->disconnect();
m_handler_transaction_changed->disconnect();
diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h
index 9173fcae52..35ededb121 100644
--- a/src/qt/walletmodel.h
+++ b/src/qt/walletmodel.h
@@ -208,6 +208,7 @@ public:
AddressTableModel* getAddressTableModel() const { return addressTableModel; }
private:
std::unique_ptr<interfaces::Wallet> m_wallet;
+ std::unique_ptr<interfaces::Handler> m_handler_unload;
std::unique_ptr<interfaces::Handler> m_handler_status_changed;
std::unique_ptr<interfaces::Handler> m_handler_address_book_changed;
std::unique_ptr<interfaces::Handler> m_handler_transaction_changed;
@@ -261,6 +262,9 @@ Q_SIGNALS:
// Watch-only address added
void notifyWatchonlyChanged(bool fHaveWatchonly);
+ // Signal that wallet is about to be removed
+ void unload();
+
public Q_SLOTS:
/* Wallet status might have changed */
void updateStatus();
diff --git a/src/qt/winshutdownmonitor.cpp b/src/qt/winshutdownmonitor.cpp
index 1e7a76efc0..6190a74598 100644
--- a/src/qt/winshutdownmonitor.cpp
+++ b/src/qt/winshutdownmonitor.cpp
@@ -4,7 +4,7 @@
#include <qt/winshutdownmonitor.h>
-#if defined(Q_OS_WIN) && QT_VERSION >= 0x050000
+#if defined(Q_OS_WIN)
#include <init.h>
#include <util.h>
diff --git a/src/qt/winshutdownmonitor.h b/src/qt/winshutdownmonitor.h
index 0bed55a2c6..c8a523a538 100644
--- a/src/qt/winshutdownmonitor.h
+++ b/src/qt/winshutdownmonitor.h
@@ -9,7 +9,6 @@
#include <QByteArray>
#include <QString>
-#if QT_VERSION >= 0x050000
#include <windef.h> // for HWND
#include <QAbstractNativeEventFilter>
@@ -24,6 +23,5 @@ public:
static void registerShutdownBlockReason(const QString& strReason, const HWND& mainWinId);
};
#endif
-#endif
#endif // BITCOIN_QT_WINSHUTDOWNMONITOR_H
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index 68279d7ffd..d9d803ac7d 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -853,7 +853,7 @@ static void ApplyStats(CCoinsStats &stats, CHashWriter& ss, const uint256& hash,
ss << hash;
ss << VARINT(outputs.begin()->second.nHeight * 2 + outputs.begin()->second.fCoinBase ? 1u : 0u);
stats.nTransactions++;
- for (const auto output : outputs) {
+ for (const auto& output : outputs) {
ss << VARINT(output.first + 1);
ss << output.second.out.scriptPubKey;
ss << VARINT(output.second.out.nValue, VarIntMode::NONNEGATIVE_SIGNED);
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index 1c6dba0c9c..8090172e3f 100644
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -69,12 +69,12 @@ void CTxMemPool::UpdateForDescendants(txiter updateIt, cacheMap &cachedDescendan
setAllDescendants.insert(cit);
stageEntries.erase(cit);
const setEntries &setChildren = GetMemPoolChildren(cit);
- for (const txiter childEntry : setChildren) {
+ for (txiter childEntry : setChildren) {
cacheMap::iterator cacheIt = cachedDescendants.find(childEntry);
if (cacheIt != cachedDescendants.end()) {
// We've already calculated this one, just add the entries for this set
// but don't traverse again.
- for (const txiter cacheEntry : cacheIt->second) {
+ for (txiter cacheEntry : cacheIt->second) {
setAllDescendants.insert(cacheEntry);
}
} else if (!setAllDescendants.count(childEntry)) {
diff --git a/src/validation.cpp b/src/validation.cpp
index baf083b153..3b8118b036 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -651,7 +651,7 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
view.SetBackend(viewMemPool);
// do all inputs exist?
- for (const CTxIn txin : tx.vin) {
+ for (const CTxIn& txin : tx.vin) {
if (!pcoinsTip->HaveCoinInCache(txin.prevout)) {
coins_to_uncache.push_back(txin.prevout);
}
@@ -957,7 +957,7 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
}
// Remove conflicting transactions from the mempool
- for (const CTxMemPool::txiter it : allConflicting)
+ for (CTxMemPool::txiter it : allConflicting)
{
LogPrint(BCLog::MEMPOOL, "replacing tx %s with %s for %s BTC additional fees, %d delta bytes\n",
it->GetTx().GetHash().ToString(),
diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp
index 410dd5009f..01b8eacccb 100644
--- a/src/wallet/db.cpp
+++ b/src/wallet/db.cpp
@@ -694,8 +694,10 @@ void BerkeleyEnvironment::Flush(bool fShutdown)
if (mapFileUseCount.empty()) {
dbenv->log_archive(&listp, DB_ARCH_REMOVE);
Close();
- if (!fMockDb)
+ if (!fMockDb) {
fs::remove_all(fs::path(strPath) / "database");
+ }
+ g_dbenvs.erase(strPath);
}
}
}
@@ -794,5 +796,6 @@ void BerkeleyDatabase::Flush(bool shutdown)
{
if (!IsDummy()) {
env->Flush(shutdown);
+ if (shutdown) env = nullptr;
}
}
diff --git a/src/wallet/init.cpp b/src/wallet/init.cpp
index daeff1d0e8..74312b7124 100644
--- a/src/wallet/init.cpp
+++ b/src/wallet/init.cpp
@@ -200,7 +200,7 @@ bool WalletInit::Verify() const
// Keep track of each wallet absolute path to detect duplicates.
std::set<fs::path> wallet_paths;
- for (const auto wallet_file : wallet_files) {
+ for (const auto& wallet_file : wallet_files) {
fs::path wallet_path = fs::absolute(wallet_file, GetWalletDir());
if (!wallet_paths.insert(wallet_path).second) {
diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp
index d09af1dbd1..882ddbbe4e 100644
--- a/src/wallet/rpcdump.cpp
+++ b/src/wallet/rpcdump.cpp
@@ -441,7 +441,7 @@ UniValue importpubkey(const JSONRPCRequest& request)
return NullUniValue;
}
- if (request.fHelp || request.params.size() < 1 || request.params.size() > 4)
+ if (request.fHelp || request.params.size() < 1 || request.params.size() > 3)
throw std::runtime_error(
"importpubkey \"pubkey\" ( \"label\" rescan )\n"
"\nAdds a public key (in hex) that can be watched as if it were in your wallet but cannot be used to spend. Requires a new wallet backup.\n"
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index fd9e23cb64..3f2255d042 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -40,12 +40,21 @@
static const std::string WALLET_ENDPOINT_BASE = "/wallet/";
-std::shared_ptr<CWallet> GetWalletForJSONRPCRequest(const JSONRPCRequest& request)
+bool GetWalletNameFromJSONRPCRequest(const JSONRPCRequest& request, std::string& wallet_name)
{
if (request.URI.substr(0, WALLET_ENDPOINT_BASE.size()) == WALLET_ENDPOINT_BASE) {
// wallet endpoint was used
- std::string requestedWallet = urlDecode(request.URI.substr(WALLET_ENDPOINT_BASE.size()));
- std::shared_ptr<CWallet> pwallet = GetWallet(requestedWallet);
+ wallet_name = urlDecode(request.URI.substr(WALLET_ENDPOINT_BASE.size()));
+ return true;
+ }
+ return false;
+}
+
+std::shared_ptr<CWallet> GetWalletForJSONRPCRequest(const JSONRPCRequest& request)
+{
+ std::string wallet_name;
+ if (GetWalletNameFromJSONRPCRequest(request, wallet_name)) {
+ std::shared_ptr<CWallet> pwallet = GetWallet(wallet_name);
if (!pwallet) throw JSONRPCError(RPC_WALLET_NOT_FOUND, "Requested wallet does not exist or is not loaded");
return pwallet;
}
@@ -66,11 +75,6 @@ bool EnsureWalletIsAvailable(CWallet * const pwallet, bool avoidException)
if (pwallet) return true;
if (avoidException) return false;
if (!HasWallets()) {
- // Note: It isn't currently possible to trigger this error because
- // wallet RPC methods aren't registered unless a wallet is loaded. But
- // this error is being kept as a precaution, because it's possible in
- // the future that wallet RPC methods might get or remain registered
- // when no wallets are loaded.
throw JSONRPCError(
RPC_METHOD_NOT_FOUND, "Method not found (wallet method is disabled because no wallet is loaded)");
}
@@ -3053,7 +3057,7 @@ static UniValue listwallets(const JSONRPCRequest& request)
return obj;
}
-UniValue loadwallet(const JSONRPCRequest& request)
+static UniValue loadwallet(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 1)
throw std::runtime_error(
@@ -3100,7 +3104,7 @@ UniValue loadwallet(const JSONRPCRequest& request)
return obj;
}
-UniValue createwallet(const JSONRPCRequest& request)
+static UniValue createwallet(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 1) {
throw std::runtime_error(
@@ -3147,6 +3151,55 @@ UniValue createwallet(const JSONRPCRequest& request)
return obj;
}
+static UniValue unloadwallet(const JSONRPCRequest& request)
+{
+ if (request.fHelp || request.params.size() > 1) {
+ throw std::runtime_error(
+ "unloadwallet ( \"wallet_name\" )\n"
+ "Unloads the wallet referenced by the request endpoint otherwise unloads the wallet specified in the argument.\n"
+ "Specifying the wallet name on a wallet endpoint is invalid."
+ "\nArguments:\n"
+ "1. \"wallet_name\" (string, optional) The name of the wallet to unload.\n"
+ "\nExamples:\n"
+ + HelpExampleCli("unloadwallet", "wallet_name")
+ + HelpExampleRpc("unloadwallet", "wallet_name")
+ );
+ }
+
+ std::string wallet_name;
+ if (GetWalletNameFromJSONRPCRequest(request, wallet_name)) {
+ if (!request.params[0].isNull()) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot unload the requested wallet");
+ }
+ } else {
+ wallet_name = request.params[0].get_str();
+ }
+
+ std::shared_ptr<CWallet> wallet = GetWallet(wallet_name);
+ if (!wallet) {
+ throw JSONRPCError(RPC_WALLET_NOT_FOUND, "Requested wallet does not exist or is not loaded");
+ }
+
+ // Release the "main" shared pointer and prevent further notifications.
+ // Note that any attempt to load the same wallet would fail until the wallet
+ // is destroyed (see CheckUniqueFileid).
+ 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.
+
+ return NullUniValue;
+}
+
static UniValue resendwallettransactions(const JSONRPCRequest& request)
{
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
@@ -4382,6 +4435,7 @@ static const CRPCCommand commands[] =
{ "wallet", "settxfee", &settxfee, {"amount"} },
{ "wallet", "signmessage", &signmessage, {"address","message"} },
{ "wallet", "signrawtransactionwithwallet", &signrawtransactionwithwallet, {"hexstring","prevtxs","sighashtype"} },
+ { "wallet", "unloadwallet", &unloadwallet, {"wallet_name"} },
{ "wallet", "walletlock", &walletlock, {} },
{ "wallet", "walletpassphrasechange", &walletpassphrasechange, {"oldpassphrase","newpassphrase"} },
{ "wallet", "walletpassphrase", &walletpassphrase, {"passphrase","timeout"} },
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index ca785298fd..842516bb0e 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -79,6 +79,15 @@ std::shared_ptr<CWallet> GetWallet(const std::string& name)
return nullptr;
}
+// Custom deleter for shared_ptr<CWallet>.
+static void ReleaseWallet(CWallet* wallet)
+{
+ LogPrintf("Releasing wallet %s\n", wallet->GetName());
+ wallet->BlockUntilSyncedToCurrentChain();
+ wallet->Flush();
+ delete wallet;
+}
+
const uint32_t BIP32_HARDENED_KEY_LIMIT = 0x80000000;
const uint256 CMerkleTx::ABANDON_HASH(uint256S("0000000000000000000000000000000000000000000000000000000000000001"));
@@ -600,6 +609,8 @@ void CWallet::AddToSpends(const COutPoint& outpoint, const uint256& wtxid)
{
mapTxSpends.insert(std::make_pair(outpoint, wtxid));
+ setLockedCoins.erase(outpoint);
+
std::pair<TxSpends::iterator, TxSpends::iterator> range;
range = mapTxSpends.equal_range(outpoint);
SyncMetaData(range);
@@ -1296,7 +1307,7 @@ void CWallet::BlockUntilSyncedToCurrentChain() {
LOCK(cs_main);
const CBlockIndex* initialChainTip = chainActive.Tip();
- if (m_last_block_processed->GetAncestor(initialChainTip->nHeight) == initialChainTip) {
+ if (m_last_block_processed && m_last_block_processed->GetAncestor(initialChainTip->nHeight) == initialChainTip) {
return;
}
}
@@ -4066,7 +4077,9 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(const std::string& name,
int64_t nStart = GetTimeMillis();
bool fFirstRun = true;
- std::shared_ptr<CWallet> walletInstance = std::make_shared<CWallet>(name, WalletDatabase::Create(path));
+ // TODO: Can't use std::make_shared because we need a custom deleter but
+ // should be possible to use std::allocate_shared.
+ std::shared_ptr<CWallet> walletInstance(new CWallet(name, WalletDatabase::Create(path)), ReleaseWallet);
DBErrors nLoadWalletRet = walletInstance->LoadWallet(fFirstRun);
if (nLoadWalletRet != DBErrors::LOAD_OK)
{
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index aacbdf81d6..b829394847 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -1100,6 +1100,9 @@ public:
//! Flush wallet (bitdb flush)
void Flush(bool shutdown=false);
+ /** Wallet is about to be unloaded */
+ boost::signals2::signal<void ()> NotifyUnload;
+
/**
* Address book entry changed.
* @note called with lock cs_wallet held.
diff --git a/test/functional/feature_assumevalid.py b/test/functional/feature_assumevalid.py
index 5a09142412..a925c70783 100755
--- a/test/functional/feature_assumevalid.py
+++ b/test/functional/feature_assumevalid.py
@@ -68,12 +68,12 @@ class AssumeValidTest(BitcoinTestFramework):
def send_blocks_until_disconnected(self, p2p_conn):
"""Keep sending blocks to the node until we're disconnected."""
for i in range(len(self.blocks)):
- if p2p_conn.state != "connected":
+ if not p2p_conn.is_connected:
break
try:
p2p_conn.send_message(msg_block(self.blocks[i]))
except IOError as e:
- assert str(e) == 'Not connected, no pushbuf'
+ assert not p2p_conn.is_connected
break
def assert_blockchain_height(self, node, height):
diff --git a/test/functional/p2p_compactblocks.py b/test/functional/p2p_compactblocks.py
index cb4c9867a3..37849e9213 100755
--- a/test/functional/p2p_compactblocks.py
+++ b/test/functional/p2p_compactblocks.py
@@ -87,7 +87,7 @@ class TestP2PConn(P2PInterface):
This is used when we want to send a message into the node that we expect
will get us disconnected, eg an invalid block."""
self.send_message(message)
- wait_until(lambda: self.state != "connected", timeout=timeout, lock=mininode_lock)
+ wait_until(lambda: not self.is_connected, timeout=timeout, lock=mininode_lock)
class CompactBlocksTest(BitcoinTestFramework):
def set_test_params(self):
diff --git a/test/functional/p2p_leak.py b/test/functional/p2p_leak.py
index 198dcc1490..dca5ea39de 100755
--- a/test/functional/p2p_leak.py
+++ b/test/functional/p2p_leak.py
@@ -118,11 +118,11 @@ class P2PLeakTest(BitcoinTestFramework):
time.sleep(5)
#This node should have been banned
- assert no_version_bannode.state != "connected"
+ assert not no_version_bannode.is_connected
# These nodes should have been disconnected
- assert unsupported_service_bit5_node.state != "connected"
- assert unsupported_service_bit7_node.state != "connected"
+ assert not unsupported_service_bit5_node.is_connected
+ assert not unsupported_service_bit7_node.is_connected
self.nodes[0].disconnect_p2ps()
diff --git a/test/functional/p2p_timeouts.py b/test/functional/p2p_timeouts.py
index 6a21b693b4..e958536cf9 100755
--- a/test/functional/p2p_timeouts.py
+++ b/test/functional/p2p_timeouts.py
@@ -47,9 +47,9 @@ class TimeoutsTest(BitcoinTestFramework):
sleep(1)
- assert no_verack_node.connected
- assert no_version_node.connected
- assert no_send_node.connected
+ assert no_verack_node.is_connected
+ assert no_version_node.is_connected
+ assert no_send_node.is_connected
no_verack_node.send_message(msg_ping())
no_version_node.send_message(msg_ping())
@@ -58,18 +58,18 @@ class TimeoutsTest(BitcoinTestFramework):
assert "version" in no_verack_node.last_message
- assert no_verack_node.connected
- assert no_version_node.connected
- assert no_send_node.connected
+ assert no_verack_node.is_connected
+ assert no_version_node.is_connected
+ assert no_send_node.is_connected
no_verack_node.send_message(msg_ping())
no_version_node.send_message(msg_ping())
sleep(31)
- assert not no_verack_node.connected
- assert not no_version_node.connected
- assert not no_send_node.connected
+ assert not no_verack_node.is_connected
+ assert not no_version_node.is_connected
+ assert not no_send_node.is_connected
if __name__ == '__main__':
TimeoutsTest().main()
diff --git a/test/functional/test_framework/mininode.py b/test/functional/test_framework/mininode.py
index 7c2125a177..5859f108a4 100755
--- a/test/functional/test_framework/mininode.py
+++ b/test/functional/test_framework/mininode.py
@@ -77,6 +77,12 @@ class P2PConnection(asyncore.dispatcher):
super().__init__(map=mininode_socket_map)
+ self._conn_open = False
+
+ @property
+ def is_connected(self):
+ return self._conn_open
+
def peer_connect(self, dstaddr, dstport, net="regtest"):
self.dstaddr = dstaddr
self.dstport = dstport
@@ -84,7 +90,7 @@ class P2PConnection(asyncore.dispatcher):
self.socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
self.sendbuf = b""
self.recvbuf = b""
- self.state = "connecting"
+ self._asyncore_pre_connection = True
self.network = net
self.disconnect = False
@@ -97,22 +103,23 @@ class P2PConnection(asyncore.dispatcher):
def peer_disconnect(self):
# Connection could have already been closed by other end.
- if self.state == "connected":
- self.disconnect_node()
+ if self.is_connected:
+ self.disconnect = True # Signal asyncore to disconnect
# Connection and disconnection methods
def handle_connect(self):
"""asyncore callback when a connection is opened."""
- if self.state != "connected":
+ if not self.is_connected:
logger.debug("Connected & Listening: %s:%d" % (self.dstaddr, self.dstport))
- self.state = "connected"
+ self._conn_open = True
+ self._asyncore_pre_connection = False
self.on_open()
def handle_close(self):
"""asyncore callback when a connection is closed."""
logger.debug("Closing connection to: %s:%d" % (self.dstaddr, self.dstport))
- self.state = "closed"
+ self._conn_open = False
self.recvbuf = b""
self.sendbuf = b""
try:
@@ -121,13 +128,6 @@ class P2PConnection(asyncore.dispatcher):
pass
self.on_close()
- def disconnect_node(self):
- """Disconnect the p2p connection.
-
- Called by the test logic thread. Causes the p2p connection
- to be disconnected on the next iteration of the asyncore loop."""
- self.disconnect = True
-
# Socket read methods
def handle_read(self):
@@ -182,9 +182,8 @@ class P2PConnection(asyncore.dispatcher):
def writable(self):
"""asyncore method to determine whether the handle_write() callback should be called on the next loop."""
with mininode_lock:
- pre_connection = self.state == "connecting"
length = len(self.sendbuf)
- return (length > 0 or pre_connection)
+ return length > 0 or self._asyncore_pre_connection
def handle_write(self):
"""asyncore callback when data should be written to the socket."""
@@ -192,7 +191,7 @@ class P2PConnection(asyncore.dispatcher):
# asyncore does not expose socket connection, only the first read/write
# event, thus we must check connection manually here to know when we
# actually connect
- if self.state == "connecting":
+ if self._asyncore_pre_connection:
self.handle_connect()
if not self.writable():
return
@@ -204,26 +203,17 @@ class P2PConnection(asyncore.dispatcher):
return
self.sendbuf = self.sendbuf[sent:]
- def send_message(self, message, pushbuf=False):
+ def send_message(self, message):
"""Send a P2P message over the socket.
This method takes a P2P payload, builds the P2P header and adds
the message to the send buffer to be sent over the socket."""
- if self.state != "connected" and not pushbuf:
- raise IOError('Not connected, no pushbuf')
+ if not self.is_connected:
+ raise IOError('Not connected')
self._log_message("send", message)
- command = message.command
- data = message.serialize()
- tmsg = MAGIC_BYTES[self.network]
- tmsg += command
- tmsg += b"\x00" * (12 - len(command))
- tmsg += struct.pack("<I", len(data))
- th = sha256(data)
- h = sha256(th)
- tmsg += h[:4]
- tmsg += data
+ tmsg = self._build_message(message)
with mininode_lock:
- if (len(self.sendbuf) == 0 and not pushbuf):
+ if len(self.sendbuf) == 0:
try:
sent = self.send(tmsg)
self.sendbuf = tmsg[sent:]
@@ -234,6 +224,20 @@ class P2PConnection(asyncore.dispatcher):
# Class utility methods
+ def _build_message(self, message):
+ """Build a serialized P2P message"""
+ command = message.command
+ data = message.serialize()
+ tmsg = MAGIC_BYTES[self.network]
+ tmsg += command
+ tmsg += b"\x00" * (12 - len(command))
+ tmsg += struct.pack("<I", len(data))
+ th = sha256(data)
+ h = sha256(th)
+ tmsg += h[:4]
+ tmsg += data
+ return tmsg
+
def _log_message(self, direction, msg):
"""Logs a message being sent or received over the connection."""
if direction == "send":
@@ -280,7 +284,7 @@ class P2PInterface(P2PConnection):
vt.addrTo.port = self.dstport
vt.addrFrom.ip = "0.0.0.0"
vt.addrFrom.port = 0
- self.send_message(vt, True)
+ self.sendbuf = self._build_message(vt) # Will be sent right after handle_connect
# Message receiving methods
@@ -348,7 +352,7 @@ class P2PInterface(P2PConnection):
# Connection helper methods
def wait_for_disconnect(self, timeout=60):
- test_function = lambda: self.state != "connected"
+ test_function = lambda: not self.is_connected
wait_until(test_function, timeout=timeout, lock=mininode_lock)
# Message receiving helper methods
diff --git a/test/functional/wallet_basic.py b/test/functional/wallet_basic.py
index 9c58b84819..d6a64eaefb 100755
--- a/test/functional/wallet_basic.py
+++ b/test/functional/wallet_basic.py
@@ -129,6 +129,15 @@ class WalletTest(BitcoinTestFramework):
self.nodes[2].lockunspent, False,
[{"txid": unspent_0["txid"], "vout": 999}])
+ # An output should be unlocked when spent
+ unspent_0 = self.nodes[1].listunspent()[0]
+ self.nodes[1].lockunspent(False, [unspent_0])
+ tx = self.nodes[1].createrawtransaction([unspent_0], { self.nodes[1].getnewaddress() : 1 })
+ tx = self.nodes[1].fundrawtransaction(tx)['hex']
+ tx = self.nodes[1].signrawtransactionwithwallet(tx)["hex"]
+ self.nodes[1].sendrawtransaction(tx)
+ assert_equal(len(self.nodes[1].listlockunspent()), 0)
+
# Have node1 generate 100 blocks (so node0 can recover the fee)
self.nodes[1].generate(100)
self.sync_all([self.nodes[0:3]])
diff --git a/test/functional/wallet_multiwallet.py b/test/functional/wallet_multiwallet.py
index a0fbc4a754..3cefd83459 100755
--- a/test/functional/wallet_multiwallet.py
+++ b/test/functional/wallet_multiwallet.py
@@ -234,5 +234,32 @@ class MultiWalletTest(BitcoinTestFramework):
assert new_wallet_name in self.nodes[0].listwallets()
+ self.log.info("Test dynamic wallet unloading")
+
+ # Test `unloadwallet` errors
+ assert_raises_rpc_error(-1, "JSON value is not a string as expected", self.nodes[0].unloadwallet)
+ assert_raises_rpc_error(-18, "Requested wallet does not exist or is not loaded", self.nodes[0].unloadwallet, "dummy")
+ assert_raises_rpc_error(-18, "Requested wallet does not exist or is not loaded", node.get_wallet_rpc("dummy").unloadwallet)
+ assert_raises_rpc_error(-8, "Cannot unload the requested wallet", w1.unloadwallet, "w2"),
+
+ # Successfully unload the specified wallet name
+ self.nodes[0].unloadwallet("w1")
+ assert 'w1' not in self.nodes[0].listwallets()
+
+ # Successfully unload the wallet referenced by the request endpoint
+ w2.unloadwallet()
+ assert 'w2' not in self.nodes[0].listwallets()
+
+ # Successfully unload all wallets
+ for wallet_name in self.nodes[0].listwallets():
+ self.nodes[0].unloadwallet(wallet_name)
+ assert_equal(self.nodes[0].listwallets(), [])
+ assert_raises_rpc_error(-32601, "Method not found (wallet method is disabled because no wallet is loaded)", self.nodes[0].getwalletinfo)
+
+ # Successfully load a previously unloaded wallet
+ self.nodes[0].loadwallet('w1')
+ assert_equal(self.nodes[0].listwallets(), ['w1'])
+ assert_equal(w1.getwalletinfo()['walletname'], 'w1')
+
if __name__ == '__main__':
MultiWalletTest().main()
diff --git a/test/lint/lint-all.sh b/test/lint/lint-all.sh
index c9d4ec7199..7c4f96cb3b 100755
--- a/test/lint/lint-all.sh
+++ b/test/lint/lint-all.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
#
# Copyright (c) 2017 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
diff --git a/test/lint/lint-filenames.sh b/test/lint/lint-filenames.sh
index 61e978fe79..5391e43d91 100755
--- a/test/lint/lint-filenames.sh
+++ b/test/lint/lint-filenames.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
#
# Copyright (c) 2018 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
@@ -10,7 +10,10 @@
export LC_ALL=C
EXIT_CODE=0
-OUTPUT=$(git ls-files -- "*.cpp" "*.h" "*.py" "*.sh" | grep -vE '^[a-z0-9_./-]+$' | grep -vE 'src/(secp256k1|univalue)/')
+OUTPUT=$(git ls-files --full-name -- "*.[cC][pP][pP]" "*.[hH]" "*.[pP][yY]" "*.[sS][hH]" | \
+ grep -vE '^[a-z0-9_./-]+$' | \
+ grep -vE '^src/(secp256k1|univalue)/')
+
if [[ ${OUTPUT} != "" ]]; then
echo "Use only lowercase alphanumerics (a-z0-9), underscores (_), hyphens (-) and dots (.)"
echo "in source code filenames:"
diff --git a/test/lint/lint-include-guards.sh b/test/lint/lint-include-guards.sh
index ea791b0176..464969794b 100755
--- a/test/lint/lint-include-guards.sh
+++ b/test/lint/lint-include-guards.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
#
# Copyright (c) 2018 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
diff --git a/test/lint/lint-includes.sh b/test/lint/lint-includes.sh
index 03350576a7..fdc3f5bd35 100755
--- a/test/lint/lint-includes.sh
+++ b/test/lint/lint-includes.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
#
# Copyright (c) 2018 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
diff --git a/test/lint/lint-locale-dependence.sh b/test/lint/lint-locale-dependence.sh
index 98814ce4b9..cbe1143bd0 100755
--- a/test/lint/lint-locale-dependence.sh
+++ b/test/lint/lint-locale-dependence.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
export LC_ALL=C
KNOWN_VIOLATIONS=(
diff --git a/test/lint/lint-logs.sh b/test/lint/lint-logs.sh
index 89e7fb8764..1afd4cfc1a 100755
--- a/test/lint/lint-logs.sh
+++ b/test/lint/lint-logs.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
#
# Copyright (c) 2018 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
diff --git a/test/lint/lint-python-shebang.sh b/test/lint/lint-python-shebang.sh
index 031487a91a..4ff87f0bf7 100755
--- a/test/lint/lint-python-shebang.sh
+++ b/test/lint/lint-python-shebang.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# Shebang must use python3 (not python or python2)
export LC_ALL=C
diff --git a/test/lint/lint-python-utf8-encoding.sh b/test/lint/lint-python-utf8-encoding.sh
index d0ff38ea0a..14183a5ccf 100755
--- a/test/lint/lint-python-utf8-encoding.sh
+++ b/test/lint/lint-python-utf8-encoding.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
#
# Copyright (c) 2018 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
diff --git a/test/lint/lint-shell-locale.sh b/test/lint/lint-shell-locale.sh
index d78bac2d47..242b27c763 100755
--- a/test/lint/lint-shell-locale.sh
+++ b/test/lint/lint-shell-locale.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
#
# Copyright (c) 2018 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
diff --git a/test/lint/lint-shell.sh b/test/lint/lint-shell.sh
index bf56db90c6..e2ccdb5165 100755
--- a/test/lint/lint-shell.sh
+++ b/test/lint/lint-shell.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
#
# Copyright (c) 2018 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
diff --git a/test/lint/lint-tests.sh b/test/lint/lint-tests.sh
index 9d83547df4..35d11023eb 100755
--- a/test/lint/lint-tests.sh
+++ b/test/lint/lint-tests.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
#
# Copyright (c) 2018 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
diff --git a/test/lint/lint-whitespace.sh b/test/lint/lint-whitespace.sh
index 128aa10da5..beb7ec42f4 100755
--- a/test/lint/lint-whitespace.sh
+++ b/test/lint/lint-whitespace.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
#
# Copyright (c) 2017 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying