aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cirrus.yml14
-rw-r--r--Makefile.am13
-rw-r--r--build_msvc/bitcoin_config.h3
-rw-r--r--build_msvc/test_bitcoin-qt/test_bitcoin-qt.vcxproj3
-rwxr-xr-xci/test/00_setup_env.sh6
-rw-r--r--ci/test/00_setup_env_android.sh25
-rwxr-xr-xci/test/05_before_script.sh9
-rwxr-xr-xci/test/06_script_a.sh8
-rw-r--r--configure.ac18
-rw-r--r--depends/packages/miniupnpc.mk10
-rw-r--r--depends/packages/qt.mk6
-rw-r--r--depends/patches/miniupnpc/dont_leak_info.patch32
-rw-r--r--depends/patches/miniupnpc/dont_use_wingen.patch26
-rw-r--r--depends/patches/qt/fix_android_pch.patch10
-rw-r--r--depends/patches/qt/fix_bigsur_drawing.patch31
-rw-r--r--doc/README.md1
-rw-r--r--doc/build-android.md12
-rw-r--r--doc/dependencies.md2
-rw-r--r--doc/release-notes.md8
-rw-r--r--share/qt/Info.plist.in3
-rw-r--r--src/Makefile.qt.include14
-rw-r--r--src/Makefile.qttest.include3
-rw-r--r--src/init.cpp2
-rw-r--r--src/net_processing.cpp5
-rw-r--r--src/node/coinstats.cpp1
-rw-r--r--src/qt/Makefile2
-rw-r--r--src/qt/android/AndroidManifest.xml38
-rw-r--r--src/qt/android/build.gradle52
-rw-r--r--src/qt/android/gradle.properties4
-rw-r--r--src/qt/android/res/drawable-hdpi/bitcoin.pngbin0 -> 4536 bytes
-rw-r--r--src/qt/android/res/drawable-ldpi/bitcoin.pngbin0 -> 1697 bytes
-rw-r--r--src/qt/android/res/drawable-mdpi/bitcoin.pngbin0 -> 2558 bytes
-rw-r--r--src/qt/android/res/drawable-xhdpi/bitcoin.pngbin0 -> 6832 bytes
-rw-r--r--src/qt/android/res/drawable-xxhdpi/bitcoin.pngbin0 -> 11479 bytes
-rw-r--r--src/qt/android/res/drawable-xxxhdpi/bitcoin.pngbin0 -> 17034 bytes
-rw-r--r--src/qt/android/src/org/bitcoincore/qt/BitcoinQtActivity.java29
-rw-r--r--src/qt/bitcoin.cpp6
-rw-r--r--src/qt/createwalletdialog.cpp6
-rw-r--r--src/qt/guiutil.cpp12
-rw-r--r--src/qt/paymentserver.cpp12
-rw-r--r--src/qt/platformstyle.cpp2
-rw-r--r--src/qt/rpcconsole.cpp2
-rw-r--r--src/qt/test/compattests.cpp25
-rw-r--r--src/qt/test/compattests.h19
-rw-r--r--src/qt/test/test_main.cpp5
-rw-r--r--src/qt/trafficgraphwidget.cpp10
-rw-r--r--src/rpc/blockchain.cpp6
-rw-r--r--src/test/bswap_tests.cpp1
-rw-r--r--src/test/fuzz/pow.cpp8
-rw-r--r--src/test/fuzz/process_message.cpp4
-rw-r--r--src/test/fuzz/process_messages.cpp6
-rw-r--r--src/test/fuzz/tx_pool.cpp21
-rw-r--r--src/test/fuzz/util.h2
-rw-r--r--src/test/fuzz/versionbits.cpp42
-rw-r--r--src/test/net_tests.cpp54
-rw-r--r--src/wallet/load.cpp2
-rwxr-xr-xtest/functional/feature_anchors.py85
-rwxr-xr-xtest/functional/feature_utxo_set_hash.py30
-rwxr-xr-xtest/functional/p2p_feefilter.py14
-rwxr-xr-xtest/functional/test_framework/messages.py12
-rw-r--r--test/functional/test_framework/wallet.py3
-rwxr-xr-xtest/functional/test_runner.py1
62 files changed, 580 insertions, 200 deletions
diff --git a/.cirrus.yml b/.cirrus.yml
index 691582239e..b3d58461e0 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -35,8 +35,6 @@ global_task_template: &GLOBAL_TASK_TEMPLATE
folder: "/tmp/cirrus-ci-build/depends/built"
depends_sdk_cache:
folder: "/tmp/cirrus-ci-build/depends/sdk-sources"
- depends_releases_cache:
- folder: "/tmp/cirrus-ci-build/releases"
ci_script:
- ./ci/test_run_all.sh
@@ -103,6 +101,8 @@ task:
# For faster CI feedback, immediately schedule a task that compiles most modules
<< : *CREDITS_TEMPLATE
<< : *GLOBAL_TASK_TEMPLATE
+ depends_releases_cache:
+ folder: "/tmp/cirrus-ci-build/releases"
container:
image: ubuntu:bionic
env:
@@ -180,3 +180,13 @@ task:
CI_USE_APT_INSTALL: "no"
PACKAGE_MANAGER_INSTALL: "echo" # Nothing to do
FILE_ENV: "./ci/test/00_setup_env_mac_host.sh"
+
+task:
+ name: 'ARM64 Android APK [focal]'
+ depends_sources_cache:
+ folder: "/tmp/cirrus-ci-build/depends/sources"
+ << : *GLOBAL_TASK_TEMPLATE
+ container:
+ image: ubuntu:focal
+ env:
+ FILE_ENV: "./ci/test/00_setup_env_android.sh"
diff --git a/Makefile.am b/Makefile.am
index 66be768277..be62c3e6a9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -78,6 +78,7 @@ COVERAGE_INFO = $(COV_TOOL_WRAPPER) baseline.info \
dist-hook:
-$(GIT) archive --format=tar HEAD -- src/clientversion.cpp | $(AMTAR) -C $(top_distdir) -xf -
+if TARGET_WINDOWS
$(BITCOIN_WIN_INSTALLER): all-recursive
$(MKDIR_P) $(top_builddir)/release
STRIPPROG="$(STRIP)" $(INSTALL_STRIP_PROGRAM) $(BITCOIND_BIN) $(top_builddir)/release
@@ -90,6 +91,10 @@ $(BITCOIN_WIN_INSTALLER): all-recursive
echo error: could not build $@
@echo built $@
+deploy: $(BITCOIN_WIN_INSTALLER)
+endif
+
+if TARGET_DARWIN
$(OSX_APP)/Contents/PkgInfo:
$(MKDIR_P) $(@D)
@echo "APPL????" > $@
@@ -133,7 +138,7 @@ $(OSX_BACKGROUND_IMAGE): $(OSX_BACKGROUND_IMAGE).png $(OSX_BACKGROUND_IMAGE)@2x.
tiffutil -cathidpicheck $^ -out $@
deploydir: $(OSX_DMG)
-else
+else !BUILD_DARWIN
APP_DIST_DIR=$(top_builddir)/dist
APP_DIST_EXTRAS=$(APP_DIST_DIR)/.background/$(OSX_BACKGROUND_IMAGE) $(APP_DIST_DIR)/.DS_Store $(APP_DIST_DIR)/Applications
@@ -160,15 +165,11 @@ $(APP_DIST_DIR)/$(OSX_APP)/Contents/MacOS/Bitcoin-Qt: $(OSX_APP_BUILT) $(OSX_PAC
INSTALLNAMETOOL=$(INSTALLNAMETOOL) OTOOL=$(OTOOL) STRIP=$(STRIP) $(PYTHON) $(OSX_DEPLOY_SCRIPT) $(OSX_APP) $(OSX_VOLNAME) -translations-dir=$(QT_TRANSLATION_DIR)
deploydir: $(APP_DIST_EXTRAS)
-endif
+endif !BUILD_DARWIN
-if TARGET_DARWIN
appbundle: $(OSX_APP_BUILT)
deploy: $(OSX_DMG)
endif
-if TARGET_WINDOWS
-deploy: $(BITCOIN_WIN_INSTALLER)
-endif
$(BITCOIN_QT_BIN): FORCE
$(MAKE) -C src qt/$(@F)
diff --git a/build_msvc/bitcoin_config.h b/build_msvc/bitcoin_config.h
index dd01cb29eb..aba5607eb6 100644
--- a/build_msvc/bitcoin_config.h
+++ b/build_msvc/bitcoin_config.h
@@ -181,9 +181,6 @@
/* Define to 1 if you have the <miniupnpc/miniupnpc.h> header file. */
#define HAVE_MINIUPNPC_MINIUPNPC_H 1
-/* Define to 1 if you have the <miniupnpc/miniwget.h> header file. */
-#define HAVE_MINIUPNPC_MINIWGET_H 1
-
/* Define to 1 if you have the <miniupnpc/upnpcommands.h> header file. */
#define HAVE_MINIUPNPC_UPNPCOMMANDS_H 1
diff --git a/build_msvc/test_bitcoin-qt/test_bitcoin-qt.vcxproj b/build_msvc/test_bitcoin-qt/test_bitcoin-qt.vcxproj
index 1ddd62edf2..1d2c86b7ac 100644
--- a/build_msvc/test_bitcoin-qt/test_bitcoin-qt.vcxproj
+++ b/build_msvc/test_bitcoin-qt/test_bitcoin-qt.vcxproj
@@ -11,7 +11,6 @@
<ClCompile Include="..\..\src\test\util\setup_common.cpp" />
<ClCompile Include="..\..\src\qt\test\addressbooktests.cpp" />
<ClCompile Include="..\..\src\qt\test\apptests.cpp" />
- <ClCompile Include="..\..\src\qt\test\compattests.cpp" />
<ClCompile Include="..\..\src\qt\test\rpcnestedtests.cpp" />
<ClCompile Include="..\..\src\qt\test\test_main.cpp" />
<ClCompile Include="..\..\src\qt\test\uritests.cpp" />
@@ -20,7 +19,6 @@
<ClCompile Include="..\..\src\wallet\test\wallet_test_fixture.cpp" />
<ClCompile Include="$(GeneratedFilesOutDir)\moc\moc_addressbooktests.cpp" />
<ClCompile Include="$(GeneratedFilesOutDir)\moc\moc_apptests.cpp" />
- <ClCompile Include="$(GeneratedFilesOutDir)\moc\moc_compattests.cpp" />
<ClCompile Include="$(GeneratedFilesOutDir)\moc\moc_rpcnestedtests.cpp" />
<ClCompile Include="$(GeneratedFilesOutDir)\moc\moc_uritests.cpp" />
<ClCompile Include="$(GeneratedFilesOutDir)\moc\moc_wallettests.cpp" />
@@ -89,7 +87,6 @@
<ItemGroup>
<MocTestFiles Include="..\..\src\qt\test\addressbooktests.h" />
<MocTestFiles Include="..\..\src\qt\test\apptests.h" />
- <MocTestFiles Include="..\..\src\qt\test\compattests.h" />
<MocTestFiles Include="..\..\src\qt\test\rpcnestedtests.h" />
<MocTestFiles Include="..\..\src\qt\test\uritests.h" />
<MocTestFiles Include="..\..\src\qt\test\wallettests.h" />
diff --git a/ci/test/00_setup_env.sh b/ci/test/00_setup_env.sh
index 87cf8538f6..e6aec723bc 100755
--- a/ci/test/00_setup_env.sh
+++ b/ci/test/00_setup_env.sh
@@ -11,6 +11,9 @@ export LC_ALL=C.UTF-8
# This is where the depends build is done.
BASE_ROOT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )"/../../ >/dev/null 2>&1 && pwd )
export BASE_ROOT_DIR
+# The depends dir.
+# This folder exists on the ci host and ci guest. Changes are propagated back and forth.
+export DEPENDS_DIR=${DEPENDS_DIR:-$BASE_ROOT_DIR/depends}
echo "Setting specific values in env"
if [ -n "${FILE_ENV}" ]; then
@@ -56,9 +59,6 @@ export CCACHE_COMPRESS=${CCACHE_COMPRESS:-1}
# The cache dir.
# This folder exists on the ci host and ci guest. Changes are propagated back and forth.
export CCACHE_DIR=${CCACHE_DIR:-$BASE_SCRATCH_DIR/.ccache}
-# The depends dir.
-# This folder exists on the ci host and ci guest. Changes are propagated back and forth.
-export DEPENDS_DIR=${DEPENDS_DIR:-$BASE_ROOT_DIR/depends}
# Folder where the build result is put (bin and lib).
export BASE_OUTDIR=${BASE_OUTDIR:-$BASE_SCRATCH_DIR/out/$HOST}
# Folder where the build is done (dist and out-of-tree build).
diff --git a/ci/test/00_setup_env_android.sh b/ci/test/00_setup_env_android.sh
new file mode 100644
index 0000000000..f78a84eeac
--- /dev/null
+++ b/ci/test/00_setup_env_android.sh
@@ -0,0 +1,25 @@
+#!/usr/bin/env bash
+#
+# Copyright (c) 2019-2020 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+export LC_ALL=C.UTF-8
+
+export HOST=aarch64-linux-android
+export PACKAGES="clang llvm unzip openjdk-8-jdk gradle"
+export CONTAINER_NAME=ci_android
+export DOCKER_NAME_TAG="ubuntu:focal"
+
+export RUN_UNIT_TESTS=false
+export RUN_FUNCTIONAL_TESTS=false
+
+export ANDROID_API_LEVEL=28
+export ANDROID_BUILD_TOOLS_VERSION=28.0.3
+export ANDROID_NDK_VERSION=21.1.6352462
+export ANDROID_TOOLS_URL=https://dl.google.com/android/repository/commandlinetools-linux-6609375_latest.zip
+export ANDROID_HOME="${DEPENDS_DIR}/SDKs/android"
+export ANDROID_NDK_HOME="${ANDROID_HOME}/ndk/${ANDROID_NDK_VERSION}"
+export DEP_OPTS="ANDROID_SDK=${ANDROID_HOME} ANDROID_NDK=${ANDROID_NDK_HOME} ANDROID_API_LEVEL=${ANDROID_API_LEVEL} ANDROID_TOOLCHAIN_BIN=${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/bin/"
+
+export BITCOIN_CONFIG="--disable-ccache"
diff --git a/ci/test/05_before_script.sh b/ci/test/05_before_script.sh
index f69afd8a26..8dd489d7f8 100755
--- a/ci/test/05_before_script.sh
+++ b/ci/test/05_before_script.sh
@@ -22,6 +22,15 @@ if [ -n "$XCODE_VERSION" ] && [ ! -f "$OSX_SDK_PATH" ]; then
DOCKER_EXEC curl --location --fail "${SDK_URL}/${OSX_SDK_BASENAME}" -o "$OSX_SDK_PATH"
fi
+if [ -n "$ANDROID_TOOLS_URL" ]; then
+ ANDROID_TOOLS_PATH=$DEPENDS_DIR/sdk-sources/android-tools.zip
+
+ DOCKER_EXEC curl --location --fail "${ANDROID_TOOLS_URL}" -o "$ANDROID_TOOLS_PATH"
+ DOCKER_EXEC mkdir -p "${ANDROID_HOME}/cmdline-tools"
+ DOCKER_EXEC unzip -o "$ANDROID_TOOLS_PATH" -d "${ANDROID_HOME}/cmdline-tools"
+ DOCKER_EXEC "yes | ${ANDROID_HOME}/cmdline-tools/tools/bin/sdkmanager --install \"build-tools;${ANDROID_BUILD_TOOLS_VERSION}\" \"platform-tools\" \"platforms;android-${ANDROID_API_LEVEL}\" \"ndk;${ANDROID_NDK_VERSION}\""
+fi
+
if [[ ${USE_MEMORY_SANITIZER} == "true" ]]; then
# Use BDB compiled using install_db4.sh script to work around linking issue when using BDB
# from depends. See https://github.com/bitcoin/bitcoin/pull/18288#discussion_r433189350 for
diff --git a/ci/test/06_script_a.sh b/ci/test/06_script_a.sh
index 7986f7665a..a42cd6cee1 100755
--- a/ci/test/06_script_a.sh
+++ b/ci/test/06_script_a.sh
@@ -6,6 +6,14 @@
export LC_ALL=C.UTF-8
+if [ -n "$ANDROID_TOOLS_URL" ]; then
+ DOCKER_EXEC make distclean || true
+ DOCKER_EXEC ./autogen.sh
+ DOCKER_EXEC ./configure $BITCOIN_CONFIG --prefix=$DEPENDS_DIR/aarch64-linux-android || ( (DOCKER_EXEC cat config.log) && false)
+ DOCKER_EXEC "cd src/qt && make $MAKEJOBS && ANDROID_HOME=${ANDROID_HOME} ANDROID_NDK_HOME=${ANDROID_NDK_HOME} make apk"
+ exit 0
+fi
+
BITCOIN_CONFIG_ALL="--enable-suppress-external-warnings --disable-dependency-tracking --prefix=$DEPENDS_DIR/$HOST --bindir=$BASE_OUTDIR/bin --libdir=$BASE_OUTDIR/lib"
if [ -z "$NO_WERROR" ]; then
BITCOIN_CONFIG_ALL="${BITCOIN_CONFIG_ALL} --enable-werror"
diff --git a/configure.ac b/configure.ac
index 6815cefdbb..9ac2643374 100644
--- a/configure.ac
+++ b/configure.ac
@@ -734,6 +734,21 @@ case $host in
*android*)
dnl make sure android stays above linux for hosts like *linux-android*
TARGET_OS=android
+ case $host in
+ *x86_64*)
+ ANDROID_ARCH=x86_64
+ ;;
+ *aarch64*)
+ ANDROID_ARCH=arm64-v8a
+ ;;
+ *armv7a*)
+ ANDROID_ARCH=armeabi-v7a
+ ;;
+ *i686*)
+ ANDROID_ARCH=i686
+ ;;
+ *) AC_MSG_ERROR("Could not determine Android arch") ;;
+ esac
;;
*linux*)
TARGET_OS=linux
@@ -1351,7 +1366,7 @@ fi
dnl Check for libminiupnpc (optional)
if test x$use_upnp != xno; then
AC_CHECK_HEADERS(
- [miniupnpc/miniwget.h miniupnpc/miniupnpc.h miniupnpc/upnpcommands.h miniupnpc/upnperrors.h],
+ [miniupnpc/miniupnpc.h miniupnpc/upnpcommands.h miniupnpc/upnperrors.h],
[AC_CHECK_LIB([miniupnpc], [upnpDiscover], [MINIUPNPC_LIBS=-lminiupnpc], [have_miniupnpc=no])],
[have_miniupnpc=no]
)
@@ -1849,6 +1864,7 @@ AC_SUBST(HAVE_BUILTIN_PREFETCH)
AC_SUBST(HAVE_MM_PREFETCH)
AC_SUBST(HAVE_STRONG_GETAUXVAL)
AC_SUBST(HAVE_WEAK_GETAUXVAL)
+AC_SUBST(ANDROID_ARCH)
AC_CONFIG_FILES([Makefile src/Makefile doc/man/Makefile share/setup.nsi share/qt/Info.plist test/config.ini])
AC_CONFIG_FILES([contrib/devtools/split-debug.sh],[chmod +x contrib/devtools/split-debug.sh])
AM_COND_IF([HAVE_DOXYGEN], [AC_CONFIG_FILES([doc/Doxyfile])])
diff --git a/depends/packages/miniupnpc.mk b/depends/packages/miniupnpc.mk
index 49a584e462..99f5b0a8db 100644
--- a/depends/packages/miniupnpc.mk
+++ b/depends/packages/miniupnpc.mk
@@ -1,9 +1,9 @@
package=miniupnpc
-$(package)_version=2.0.20180203
+$(package)_version=2.2.2
$(package)_download_path=https://miniupnp.tuxfamily.org/files/
$(package)_file_name=$(package)-$($(package)_version).tar.gz
-$(package)_sha256_hash=90dda8c7563ca6cd4a83e23b3c66dbbea89603a1675bfdb852897c2c9cc220b7
-$(package)_patches=dont_use_wingen.patch
+$(package)_sha256_hash=888fb0976ba61518276fe1eda988589c700a3f2a69d71089260d75562afd3687
+$(package)_patches=dont_leak_info.patch
define $(package)_set_vars
$(package)_build_opts=CC="$($(package)_cc)"
@@ -13,9 +13,7 @@ $(package)_build_env+=CFLAGS="$($(package)_cflags) $($(package)_cppflags)" AR="$
endef
define $(package)_preprocess_cmds
- mkdir dll && \
- sed -e 's|MINIUPNPC_VERSION_STRING \"version\"|MINIUPNPC_VERSION_STRING \"$($(package)_version)\"|' -e 's|OS/version|$(host)|' miniupnpcstrings.h.in > miniupnpcstrings.h && \
- patch -p1 < $($(package)_patch_dir)/dont_use_wingen.patch
+ patch -p1 < $($(package)_patch_dir)/dont_leak_info.patch
endef
define $(package)_build_cmds
diff --git a/depends/packages/qt.mk b/depends/packages/qt.mk
index 7d96197221..ee6796e2ad 100644
--- a/depends/packages/qt.mk
+++ b/depends/packages/qt.mk
@@ -9,7 +9,8 @@ $(package)_qt_libs=corelib network widgets gui plugins testlib
$(package)_patches=fix_qt_pkgconfig.patch mac-qmake.conf fix_no_printer.patch no-xlib.patch
$(package)_patches+= fix_android_qmake_conf.patch fix_android_jni_static.patch dont_hardcode_pwd.patch
$(package)_patches+= drop_lrelease_dependency.patch no_sdk_version_check.patch
-$(package)_patches+= fix_qpainter_non_determinism.patch fix_lib_paths.patch
+$(package)_patches+= fix_qpainter_non_determinism.patch fix_lib_paths.patch fix_android_pch.patch
+$(package)_patches+= fix_bigsur_drawing.patch
$(package)_qttranslations_file_name=qttranslations-$($(package)_suffix)
$(package)_qttranslations_sha256_hash=e1de58ed108b7e0a138815ea60fd46a2c4e1fc31396a707e5630e92de79c53de
@@ -165,6 +166,7 @@ $(package)_config_opts_android += -no-fontconfig
$(package)_config_opts_android += -L $(host_prefix)/lib
$(package)_config_opts_android += -I $(host_prefix)/include
$(package)_config_opts_android += -pch
+$(package)_config_opts_android += -no-feature-vulkan
$(package)_config_opts_aarch64_android += -android-arch arm64-v8a
$(package)_config_opts_armv7a_android += -android-arch armeabi-v7a
@@ -224,10 +226,12 @@ define $(package)_preprocess_cmds
patch -p1 -i $($(package)_patch_dir)/fix_no_printer.patch && \
patch -p1 -i $($(package)_patch_dir)/fix_android_qmake_conf.patch && \
patch -p1 -i $($(package)_patch_dir)/fix_android_jni_static.patch && \
+ patch -p1 -i $($(package)_patch_dir)/fix_android_pch.patch && \
patch -p1 -i $($(package)_patch_dir)/no-xlib.patch && \
patch -p1 -i $($(package)_patch_dir)/fix_qpainter_non_determinism.patch &&\
patch -p1 -i $($(package)_patch_dir)/no_sdk_version_check.patch && \
patch -p1 -i $($(package)_patch_dir)/fix_lib_paths.patch && \
+ patch -p1 -i $($(package)_patch_dir)/fix_bigsur_drawing.patch && \
sed -i.old "s|updateqm.commands = \$$$$\$$$$LRELEASE|updateqm.commands = $($(package)_extract_dir)/qttools/bin/lrelease|" qttranslations/translations/translations.pro && \
mkdir -p qtbase/mkspecs/macx-clang-linux &&\
cp -f qtbase/mkspecs/macx-clang/qplatformdefs.h qtbase/mkspecs/macx-clang-linux/ &&\
diff --git a/depends/patches/miniupnpc/dont_leak_info.patch b/depends/patches/miniupnpc/dont_leak_info.patch
new file mode 100644
index 0000000000..512f9c50ea
--- /dev/null
+++ b/depends/patches/miniupnpc/dont_leak_info.patch
@@ -0,0 +1,32 @@
+commit 8815452257437ba36607d0e2381c01142d1c7bb0
+Author: fanquake <fanquake@gmail.com>
+Date: Thu Nov 19 10:51:19 2020 +0800
+
+ Don't leak OS and miniupnpc version info in User-Agent
+
+diff --git a//minisoap.c b/minisoap.c
+index 7860667..775580b 100644
+--- a/minisoap.c
++++ b/minisoap.c
+@@ -90,7 +90,7 @@ int soapPostSubmit(SOCKET fd,
+ headerssize = snprintf(headerbuf, sizeof(headerbuf),
+ "POST %s HTTP/%s\r\n"
+ "Host: %s%s\r\n"
+- "User-Agent: " OS_STRING ", " UPNP_VERSION_STRING ", MiniUPnPc/" MINIUPNPC_VERSION_STRING "\r\n"
++ "User-Agent: " UPNP_VERSION_STRING "\r\n"
+ "Content-Length: %d\r\n"
+ "Content-Type: text/xml\r\n"
+ "SOAPAction: \"%s\"\r\n"
+diff --git a/miniwget.c b/miniwget.c
+index d5b7970..05aeb9c 100644
+--- a/miniwget.c
++++ b/miniwget.c
+@@ -444,7 +444,7 @@ miniwget3(const char * host,
+ "GET %s HTTP/%s\r\n"
+ "Host: %s:%d\r\n"
+ "Connection: Close\r\n"
+- "User-Agent: " OS_STRING ", " UPNP_VERSION_STRING ", MiniUPnPc/" MINIUPNPC_VERSION_STRING "\r\n"
++ "User-Agent: " UPNP_VERSION_STRING "\r\n"
+
+ "\r\n",
+ path, httpversion, host, port);
diff --git a/depends/patches/miniupnpc/dont_use_wingen.patch b/depends/patches/miniupnpc/dont_use_wingen.patch
deleted file mode 100644
index a1cc9b50d1..0000000000
--- a/depends/patches/miniupnpc/dont_use_wingen.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-commit e8077044df239bcf0d9e9980b0e1afb9f1f5c446
-Author: fanquake <fanquake@gmail.com>
-Date: Tue Aug 18 20:50:19 2020 +0800
-
- Don't use wingenminiupnpcstrings when generating miniupnpcstrings.h
-
- The wingenminiupnpcstrings tool is used on Windows to generate version
- information. This information is irrelevant for us, and trying to use
- wingenminiupnpcstrings would cause builds to fail, so just don't use it.
-
- We should be able to drop this once we are using 2.1 or later. See
- upstream commit: 9663c55c61408fdcc39a82987d2243f816b22932.
-
-diff --git a/Makefile.mingw b/Makefile.mingw
-index 574720e..fcc17bb 100644
---- a/Makefile.mingw
-+++ b/Makefile.mingw
-@@ -74,7 +74,7 @@ wingenminiupnpcstrings: wingenminiupnpcstrings.o
-
- wingenminiupnpcstrings.o: wingenminiupnpcstrings.c
-
--miniupnpcstrings.h: miniupnpcstrings.h.in wingenminiupnpcstrings
-+miniupnpcstrings.h: miniupnpcstrings.h.in
- wingenminiupnpcstrings $< $@
-
- minixml.o: minixml.c minixml.h
diff --git a/depends/patches/qt/fix_android_pch.patch b/depends/patches/qt/fix_android_pch.patch
new file mode 100644
index 0000000000..bed6e4bb63
--- /dev/null
+++ b/depends/patches/qt/fix_android_pch.patch
@@ -0,0 +1,10 @@
+--- old/qtbase/mkspecs/common/android-base-head.conf
++++ new/qtbase/mkspecs/common/android-base-head.conf
+@@ -73,6 +73,6 @@ CROSS_COMPILE = $$NDK_TOOLCHAIN_PATH/bin/$$NDK_TOOLS_PREFIX-
+ QMAKE_PCH_OUTPUT_EXT = .gch
+
+ QMAKE_CFLAGS_PRECOMPILE = -x c-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT}
+-QMAKE_CFLAGS_USE_PRECOMPILE = -include ${QMAKE_PCH_OUTPUT_BASE}
++QMAKE_CFLAGS_USE_PRECOMPILE = -include-pch ${QMAKE_PCH_OUTPUT}
+ QMAKE_CXXFLAGS_PRECOMPILE = -x c++-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT}
+ QMAKE_CXXFLAGS_USE_PRECOMPILE = $$QMAKE_CFLAGS_USE_PRECOMPILE
diff --git a/depends/patches/qt/fix_bigsur_drawing.patch b/depends/patches/qt/fix_bigsur_drawing.patch
new file mode 100644
index 0000000000..98c0c6be30
--- /dev/null
+++ b/depends/patches/qt/fix_bigsur_drawing.patch
@@ -0,0 +1,31 @@
+Fix GUI stuck on Big Sur
+
+See:
+ - https://github.com/bitcoin-core/gui/issues/249
+ - https://github.com/bitcoin/bitcoin/pull/21495
+ - https://bugreports.qt.io/browse/QTBUG-87014
+
+We should be able to drop this once we are using one of the following versions:
+ - Qt 5.12.11 or later, see upstream commit: c5d904639dbd690a36306e2b455610029704d821
+ - Qt 5.15.3 or later, see upstream commit: 2cae34354bd41ae286258c7a6b3653b746e786ae
+
+--- a/qtbase/src/plugins/platforms/cocoa/qnsview_drawing.mm
++++ b/qtbase/src/plugins/platforms/cocoa/qnsview_drawing.mm
+@@ -95,8 +95,15 @@
+ // by AppKit at a point where we've already set up other parts of the platform plugin
+ // based on the presence of layers or not. Once we've rewritten these parts to support
+ // dynamically picking up layer enablement we can let AppKit do its thing.
+- return QMacVersion::buildSDK() >= QOperatingSystemVersion::MacOSMojave
+- && QMacVersion::currentRuntime() >= QOperatingSystemVersion::MacOSMojave;
++
++ if (QMacVersion::currentRuntime() >= QOperatingSystemVersion::MacOSBigSur)
++ return true; // Big Sur always enables layer-backing, regardless of SDK
++
++ if (QMacVersion::currentRuntime() >= QOperatingSystemVersion::MacOSMojave
++ && QMacVersion::buildSDK() >= QOperatingSystemVersion::MacOSMojave)
++ return true; // Mojave and Catalina enable layers based on the app's SDK
++
++ return false; // Prior versions needed explicitly enabled layer backing
+ }
+
+ - (BOOL)layerExplicitlyRequested
diff --git a/doc/README.md b/doc/README.md
index 19d8204d83..f32600d009 100644
--- a/doc/README.md
+++ b/doc/README.md
@@ -44,6 +44,7 @@ The following are developer notes on how to build Bitcoin Core on your native pl
- [FreeBSD Build Notes](build-freebsd.md)
- [OpenBSD Build Notes](build-openbsd.md)
- [NetBSD Build Notes](build-netbsd.md)
+- [Android Build Notes](build-android.md)
- [Gitian Building Guide (External Link)](https://github.com/bitcoin-core/docs/blob/master/gitian-building.md)
Development
diff --git a/doc/build-android.md b/doc/build-android.md
new file mode 100644
index 0000000000..7a8a9e6a65
--- /dev/null
+++ b/doc/build-android.md
@@ -0,0 +1,12 @@
+ANDROID BUILD NOTES
+======================
+
+This guide describes how to build and package the `bitcoin-qt` GUI for Android on Linux and macOS.
+
+## Preparation
+
+You will need to get the Android NDK and build dependencies for Android as described in [depends/README.md](../depends/README.md).
+
+## Building and packaging
+
+After the depends are built configure with one of the resulting prefixes and run `make && make apk` in `src/qt`. \ No newline at end of file
diff --git a/doc/dependencies.md b/doc/dependencies.md
index 1397fe9d0c..22161856ce 100644
--- a/doc/dependencies.md
+++ b/doc/dependencies.md
@@ -17,7 +17,7 @@ These are the dependencies currently used by Bitcoin Core. You can find instruct
| libnatpmp | git commit [4536032...](https://github.com/miniupnp/libnatpmp/tree/4536032ae32268a45c073a4d5e91bbab4534773a) | | No | | |
| libpng | | | | | [Yes](https://github.com/bitcoin/bitcoin/blob/master/depends/packages/qt.mk) |
| librsvg | | | | | |
-| MiniUPnPc | [2.0.20180203](https://miniupnp.tuxfamily.org/files) | | No | | |
+| MiniUPnPc | [2.2.2](https://miniupnp.tuxfamily.org/files) | | No | | |
| PCRE | | | | | [Yes](https://github.com/bitcoin/bitcoin/blob/master/depends/packages/qt.mk) |
| Python (tests) | | [3.6](https://www.python.org/downloads) | | | |
| qrencode | [3.4.4](https://fukuchi.org/works/qrencode) | | No | | |
diff --git a/doc/release-notes.md b/doc/release-notes.md
index f049aaa4af..e46380b38f 100644
--- a/doc/release-notes.md
+++ b/doc/release-notes.md
@@ -51,9 +51,7 @@ Core should also work on most other Unix-like systems but is not as
frequently tested on them. It is not recommended to use Bitcoin Core on
unsupported systems.
-From Bitcoin Core 0.22.0 onwards, macOS versions earlier than 10.14 are no
-longer supported. Additionally, Bitcoin Core does not yet change appearance
-when macOS "dark mode" is activated.
+From Bitcoin Core 22.0 onwards, macOS versions earlier than 10.14 are no longer supported.
Notable changes
===============
@@ -120,6 +118,10 @@ Low-level changes
RPC
---
+- The RPC server can process a limited number of simultaneous RPC requests.
+ Previously, if this limit was exceeded, `bitcoind` would respond with
+ [status code 500 (`HTTP_INTERNAL_SERVER_ERROR`)](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#5xx_server_errors).
+ Now it returns status code 503 (`HTTP_SERVICE_UNAVAILABLE`). (#18335)
Tests
-----
diff --git a/share/qt/Info.plist.in b/share/qt/Info.plist.in
index 207d60aca3..da10dbb3be 100644
--- a/share/qt/Info.plist.in
+++ b/share/qt/Info.plist.in
@@ -60,9 +60,6 @@
<key>NSHighResolutionCapable</key>
<string>True</string>
- <key>NSRequiresAquaSystemAppearance</key>
- <string>True</string>
-
<key>LSApplicationCategoryType</key>
<string>public.app-category.finance</string>
</dict>
diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include
index 59cfdb9839..399a8430ef 100644
--- a/src/Makefile.qt.include
+++ b/src/Makefile.qt.include
@@ -378,6 +378,20 @@ bitcoin_qt_clean: FORCE
bitcoin_qt : qt/bitcoin-qt$(EXEEXT)
+APK_LIB_DIR = qt/android/libs/$(ANDROID_ARCH)
+QT_BASE_PATH = $(shell find ../depends/sources/ -maxdepth 1 -type f -regex ".*qtbase.*\.tar.xz")
+QT_BASE_TLD = $(shell tar tf $(QT_BASE_PATH) --exclude='*/*')
+
+bitcoin_qt_apk: FORCE
+ mkdir -p $(APK_LIB_DIR)
+ cp $(dir $(CC))../sysroot/usr/lib/$(host_alias)/libc++_shared.so $(APK_LIB_DIR)
+ tar xf $(QT_BASE_PATH) -C qt/android/src/ $(QT_BASE_TLD)src/android/jar/src --strip-components=5
+ tar xf $(QT_BASE_PATH) -C qt/android/src/ $(QT_BASE_TLD)src/android/java/src --strip-components=5
+ tar xf $(QT_BASE_PATH) -C qt/android/res/ $(QT_BASE_TLD)src/android/java/res --strip-components=5
+ cp qt/bitcoin-qt $(APK_LIB_DIR)/libbitcoin-qt.so
+ cd qt/android && gradle wrapper --gradle-version=6.6.1
+ cd qt/android && ./gradlew build
+
ui_%.h: %.ui
@test -f $(UIC)
@$(MKDIR_P) $(@D)
diff --git a/src/Makefile.qttest.include b/src/Makefile.qttest.include
index a6a857d952..91a5e9fd9b 100644
--- a/src/Makefile.qttest.include
+++ b/src/Makefile.qttest.include
@@ -7,7 +7,6 @@ TESTS += qt/test/test_bitcoin-qt
TEST_QT_MOC_CPP = \
qt/test/moc_apptests.cpp \
- qt/test/moc_compattests.cpp \
qt/test/moc_rpcnestedtests.cpp \
qt/test/moc_uritests.cpp
@@ -20,7 +19,6 @@ endif # ENABLE_WALLET
TEST_QT_H = \
qt/test/addressbooktests.h \
qt/test/apptests.h \
- qt/test/compattests.h \
qt/test/rpcnestedtests.h \
qt/test/uritests.h \
qt/test/util.h \
@@ -31,7 +29,6 @@ qt_test_test_bitcoin_qt_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(BITCOIN_
qt_test_test_bitcoin_qt_SOURCES = \
qt/test/apptests.cpp \
- qt/test/compattests.cpp \
qt/test/rpcnestedtests.cpp \
qt/test/test_main.cpp \
qt/test/uritests.cpp \
diff --git a/src/init.cpp b/src/init.cpp
index 7d5420e3be..f4b7699233 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -1308,7 +1308,7 @@ bool AppInitMain(const util::Ref& context, NodeContext& node, interfaces::BlockA
LogPrintf("Config file: %s\n", config_file_path.string());
} else if (args.IsArgSet("-conf")) {
// Warn if no conf file exists at path provided by user
- InitWarning(strprintf(_("The specified config file %s does not exist\n"), config_file_path.string()));
+ InitWarning(strprintf(_("The specified config file %s does not exist"), config_file_path.string()));
} else {
// Not categorizing as "Warning" because it's the default behavior
LogPrintf("Config file: %s (not found, skipping)\n", config_file_path.string());
diff --git a/src/net_processing.cpp b/src/net_processing.cpp
index e561f02c4a..d327a69a93 100644
--- a/src/net_processing.cpp
+++ b/src/net_processing.cpp
@@ -4689,7 +4689,10 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
//
// Message: feefilter
//
- if (pto->m_tx_relay != nullptr && pto->GetCommonVersion() >= FEEFILTER_VERSION && gArgs.GetBoolArg("-feefilter", DEFAULT_FEEFILTER) &&
+ if (pto->m_tx_relay != nullptr &&
+ !m_ignore_incoming_txs &&
+ pto->GetCommonVersion() >= FEEFILTER_VERSION &&
+ gArgs.GetBoolArg("-feefilter", DEFAULT_FEEFILTER) &&
!pto->HasPermission(PF_FORCERELAY) // peers with the forcerelay permission should not filter txs to us
) {
CAmount currentFilter = m_mempool.GetMinFee(gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000).GetFeePerK();
diff --git a/src/node/coinstats.cpp b/src/node/coinstats.cpp
index 88bdba5953..268580c6e6 100644
--- a/src/node/coinstats.cpp
+++ b/src/node/coinstats.cpp
@@ -15,6 +15,7 @@
#include <map>
+// Database-independent metric indicating the UTXO set size
static uint64_t GetBogoSize(const CScript& scriptPubKey)
{
return 32 /* txid */ +
diff --git a/src/qt/Makefile b/src/qt/Makefile
index b9dcf0c599..3bd6199059 100644
--- a/src/qt/Makefile
+++ b/src/qt/Makefile
@@ -7,3 +7,5 @@ check: FORCE
$(MAKE) -C .. test_bitcoin_qt_check
bitcoin-qt bitcoin-qt.exe: FORCE
$(MAKE) -C .. bitcoin_qt
+apk: FORCE
+ $(MAKE) -C .. bitcoin_qt_apk
diff --git a/src/qt/android/AndroidManifest.xml b/src/qt/android/AndroidManifest.xml
new file mode 100644
index 0000000000..abb88fe89d
--- /dev/null
+++ b/src/qt/android/AndroidManifest.xml
@@ -0,0 +1,38 @@
+<?xml version='1.0' encoding='utf-8'?>
+<manifest package="org.bitcoincore.qt" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="1.0" android:versionCode="1" android:installLocation="auto">
+ <uses-sdk android:targetSdkVersion="24"/>
+
+ <uses-permission android:name="android.permission.INTERNET" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+
+ <uses-feature android:glEsVersion="0x00020000" android:required="true" />
+
+ <supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>
+
+ <application android:hardwareAccelerated="true" android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="Bitcoin Core">
+ <activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation|mcc|mnc|density"
+ android:name="org.bitcoincore.qt.BitcoinQtActivity"
+ android:label="Bitcoin Core"
+ android:icon="@drawable/bitcoin"
+ android:screenOrientation="unspecified"
+ android:launchMode="singleTop">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+
+ <meta-data android:name="android.app.arguments" android:value="-testnet"/>
+ <meta-data android:name="android.app.lib_name" android:value="bitcoin-qt"/>
+ <meta-data android:name="android.app.repository" android:value="default"/>
+ <meta-data android:name="android.app.bundle_local_qt_libs" android:value="1"/>
+ <meta-data android:name="android.app.use_local_qt_libs" android:value="1"/>
+ <meta-data android:name="android.app.libs_prefix" android:value="/data/local/tmp/qt/"/>
+ <meta-data android:name="android.app.system_libs_prefix" android:value="/system/lib/"/>
+ <meta-data android:name="android.app.background_running" android:value="true"/>
+ <meta-data android:name="android.app.auto_screen_scale_factor" android:value="true"/>
+ <meta-data android:name="android.app.extract_android_style" android:value="default"/>
+ </activity>
+
+ </application>
+</manifest>
diff --git a/src/qt/android/build.gradle b/src/qt/android/build.gradle
new file mode 100644
index 0000000000..4c36e79db8
--- /dev/null
+++ b/src/qt/android/build.gradle
@@ -0,0 +1,52 @@
+buildscript {
+ repositories {
+ google()
+ jcenter()
+ }
+
+ dependencies {
+ classpath 'com.android.tools.build:gradle:3.1.0'
+ }
+}
+
+repositories {
+ google()
+ jcenter()
+}
+
+apply plugin: 'com.android.application'
+
+dependencies {
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
+}
+
+android {
+ compileSdkVersion androidCompileSdkVersion.toInteger()
+
+ buildToolsVersion androidBuildToolsVersion
+
+ sourceSets {
+ main {
+ manifest.srcFile 'AndroidManifest.xml'
+ java.srcDirs = [qt5AndroidDir + '/src', 'src', 'java']
+ aidl.srcDirs = [qt5AndroidDir + '/src', 'src', 'aidl']
+ res.srcDirs = [qt5AndroidDir + '/res', 'res']
+ resources.srcDirs = ['src']
+ renderscript.srcDirs = ['src']
+ assets.srcDirs = ['assets']
+ jniLibs.srcDirs = ['libs']
+ }
+ }
+
+ lintOptions {
+ abortOnError false
+ }
+
+ dexOptions {
+ javaMaxHeapSize '4g'
+ }
+
+ defaultConfig {
+ minSdkVersion 24
+ }
+}
diff --git a/src/qt/android/gradle.properties b/src/qt/android/gradle.properties
new file mode 100644
index 0000000000..838870f62d
--- /dev/null
+++ b/src/qt/android/gradle.properties
@@ -0,0 +1,4 @@
+androidBuildToolsVersion=28.0.3
+androidCompileSdkVersion=28
+qt5AndroidDir=new File(".").absolutePath
+org.gradle.jvmargs=-Xmx4608M
diff --git a/src/qt/android/res/drawable-hdpi/bitcoin.png b/src/qt/android/res/drawable-hdpi/bitcoin.png
new file mode 100644
index 0000000000..31a556a35f
--- /dev/null
+++ b/src/qt/android/res/drawable-hdpi/bitcoin.png
Binary files differ
diff --git a/src/qt/android/res/drawable-ldpi/bitcoin.png b/src/qt/android/res/drawable-ldpi/bitcoin.png
new file mode 100644
index 0000000000..76d80d4196
--- /dev/null
+++ b/src/qt/android/res/drawable-ldpi/bitcoin.png
Binary files differ
diff --git a/src/qt/android/res/drawable-mdpi/bitcoin.png b/src/qt/android/res/drawable-mdpi/bitcoin.png
new file mode 100644
index 0000000000..c2aeab851a
--- /dev/null
+++ b/src/qt/android/res/drawable-mdpi/bitcoin.png
Binary files differ
diff --git a/src/qt/android/res/drawable-xhdpi/bitcoin.png b/src/qt/android/res/drawable-xhdpi/bitcoin.png
new file mode 100644
index 0000000000..2bd5e3defc
--- /dev/null
+++ b/src/qt/android/res/drawable-xhdpi/bitcoin.png
Binary files differ
diff --git a/src/qt/android/res/drawable-xxhdpi/bitcoin.png b/src/qt/android/res/drawable-xxhdpi/bitcoin.png
new file mode 100644
index 0000000000..d236cf2132
--- /dev/null
+++ b/src/qt/android/res/drawable-xxhdpi/bitcoin.png
Binary files differ
diff --git a/src/qt/android/res/drawable-xxxhdpi/bitcoin.png b/src/qt/android/res/drawable-xxxhdpi/bitcoin.png
new file mode 100644
index 0000000000..bb1dbc3554
--- /dev/null
+++ b/src/qt/android/res/drawable-xxxhdpi/bitcoin.png
Binary files differ
diff --git a/src/qt/android/src/org/bitcoincore/qt/BitcoinQtActivity.java b/src/qt/android/src/org/bitcoincore/qt/BitcoinQtActivity.java
new file mode 100644
index 0000000000..cf3b4f6668
--- /dev/null
+++ b/src/qt/android/src/org/bitcoincore/qt/BitcoinQtActivity.java
@@ -0,0 +1,29 @@
+package org.bitcoincore.qt;
+
+import android.os.Bundle;
+import android.system.ErrnoException;
+import android.system.Os;
+
+import org.qtproject.qt5.android.bindings.QtActivity;
+
+import java.io.File;
+
+public class BitcoinQtActivity extends QtActivity
+{
+ @Override
+ public void onCreate(Bundle savedInstanceState)
+ {
+ final File bitcoinDir = new File(getFilesDir().getAbsolutePath() + "/.bitcoin");
+ if (!bitcoinDir.exists()) {
+ bitcoinDir.mkdir();
+ }
+
+ try {
+ Os.setenv("QT_QPA_PLATFORM", "android", true);
+ } catch (ErrnoException e) {
+ e.printStackTrace();
+ }
+
+ super.onCreate(savedInstanceState);
+ }
+}
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp
index 791a29f7a0..fc6d0febc2 100644
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -466,6 +466,12 @@ int GuiMain(int argc, char* argv[])
QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+#if defined(QT_QPA_PLATFORM_ANDROID)
+ QApplication::setAttribute(Qt::AA_DontUseNativeMenuBar);
+ QApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
+ QApplication::setAttribute(Qt::AA_DontUseNativeDialogs);
+#endif
+
BitcoinApplication app;
QFontDatabase::addApplicationFont(":/fonts/monospace");
diff --git a/src/qt/createwalletdialog.cpp b/src/qt/createwalletdialog.cpp
index 1467801522..113bd30a0c 100644
--- a/src/qt/createwalletdialog.cpp
+++ b/src/qt/createwalletdialog.cpp
@@ -53,6 +53,12 @@ CreateWalletDialog::CreateWalletDialog(QWidget* parent) :
}
});
+ connect(ui->blank_wallet_checkbox, &QCheckBox::toggled, [this](bool checked) {
+ if (!checked) {
+ ui->disable_privkeys_checkbox->setChecked(false);
+ }
+ });
+
#ifndef USE_SQLITE
ui->descriptor_checkbox->setToolTip(tr("Compiled without sqlite support (required for descriptor wallets)"));
ui->descriptor_checkbox->setEnabled(false);
diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp
index 32890ed0fe..b4afdbcc22 100644
--- a/src/qt/guiutil.cpp
+++ b/src/qt/guiutil.cpp
@@ -759,14 +759,14 @@ QString formatNiceTimeOffset(qint64 secs)
QString formatBytes(uint64_t bytes)
{
- if(bytes < 1024)
+ if (bytes < 1'000)
return QObject::tr("%1 B").arg(bytes);
- if(bytes < 1024 * 1024)
- return QObject::tr("%1 KB").arg(bytes / 1024);
- if(bytes < 1024 * 1024 * 1024)
- return QObject::tr("%1 MB").arg(bytes / 1024 / 1024);
+ if (bytes < 1'000'000)
+ return QObject::tr("%1 kB").arg(bytes / 1'000);
+ if (bytes < 1'000'000'000)
+ return QObject::tr("%1 MB").arg(bytes / 1'000'000);
- return QObject::tr("%1 GB").arg(bytes / 1024 / 1024 / 1024);
+ return QObject::tr("%1 GB").arg(bytes / 1'000'000'000);
}
qreal calculateIdealFontSize(int width, const QString& text, QFont font, qreal minPointSize, qreal font_size) {
diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp
index 96f6202874..58f6c14e7a 100644
--- a/src/qt/paymentserver.cpp
+++ b/src/qt/paymentserver.cpp
@@ -235,9 +235,9 @@ void PaymentServer::handleURIOrFile(const QString& s)
if (!IsValidDestinationString(recipient.address.toStdString())) {
if (uri.hasQueryItem("r")) { // payment request
Q_EMIT message(tr("URI handling"),
- tr("Cannot process payment request because BIP70 is not supported.")+
- tr("Due to widespread security flaws in BIP70 it's strongly recommended that any merchant instructions to switch wallets be ignored.")+
- tr("If you are receiving this error you should request the merchant provide a BIP21 compatible URI."),
+ tr("Cannot process payment request because BIP70 is not supported.\n"
+ "Due to widespread security flaws in BIP70 it's strongly recommended that any merchant instructions to switch wallets be ignored.\n"
+ "If you are receiving this error you should request the merchant provide a BIP21 compatible URI."),
CClientUIInterface::ICON_WARNING);
}
Q_EMIT message(tr("URI handling"), tr("Invalid payment address %1").arg(recipient.address),
@@ -258,9 +258,9 @@ void PaymentServer::handleURIOrFile(const QString& s)
if (QFile::exists(s)) // payment request file
{
Q_EMIT message(tr("Payment request file handling"),
- tr("Cannot process payment request because BIP70 is not supported.")+
- tr("Due to widespread security flaws in BIP70 it's strongly recommended that any merchant instructions to switch wallets be ignored.")+
- tr("If you are receiving this error you should request the merchant provide a BIP21 compatible URI."),
+ tr("Cannot process payment request because BIP70 is not supported.\n"
+ "Due to widespread security flaws in BIP70 it's strongly recommended that any merchant instructions to switch wallets be ignored.\n"
+ "If you are receiving this error you should request the merchant provide a BIP21 compatible URI."),
CClientUIInterface::ICON_WARNING);
}
}
diff --git a/src/qt/platformstyle.cpp b/src/qt/platformstyle.cpp
index aab8d8e4af..1d0605c903 100644
--- a/src/qt/platformstyle.cpp
+++ b/src/qt/platformstyle.cpp
@@ -18,7 +18,7 @@ static const struct {
/** Extra padding/spacing in transactionview */
const bool useExtraSpacing;
} platform_styles[] = {
- {"macosx", false, false, true},
+ {"macosx", false, true, true},
{"windows", true, false, false},
/* Other: linux, unix, ... */
{"other", true, true, false}
diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp
index b258219894..34d055e5a5 100644
--- a/src/qt/rpcconsole.cpp
+++ b/src/qt/rpcconsole.cpp
@@ -608,7 +608,6 @@ void RPCConsole::setClientModel(ClientModel *model, int bestblock_height, int64_
// set up peer table
ui->peerWidget->setModel(model->getPeerTableModel());
ui->peerWidget->verticalHeader()->hide();
- ui->peerWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
ui->peerWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
ui->peerWidget->setSelectionMode(QAbstractItemView::ExtendedSelection);
ui->peerWidget->setContextMenuPolicy(Qt::CustomContextMenu);
@@ -651,7 +650,6 @@ void RPCConsole::setClientModel(ClientModel *model, int bestblock_height, int64_
// set up ban table
ui->banlistWidget->setModel(model->getBanTableModel());
ui->banlistWidget->verticalHeader()->hide();
- ui->banlistWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
ui->banlistWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
ui->banlistWidget->setSelectionMode(QAbstractItemView::SingleSelection);
ui->banlistWidget->setContextMenuPolicy(Qt::CustomContextMenu);
diff --git a/src/qt/test/compattests.cpp b/src/qt/test/compattests.cpp
deleted file mode 100644
index c76dee5091..0000000000
--- a/src/qt/test/compattests.cpp
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) 2016-2019 The Bitcoin Core developers
-// Distributed under the MIT software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-#if defined(HAVE_CONFIG_H)
-#include <config/bitcoin-config.h>
-#endif
-
-#include <qt/test/compattests.h>
-
-#include <compat/byteswap.h>
-
-void CompatTests::bswapTests()
-{
- // Sibling in bitcoin/src/test/bswap_tests.cpp
- uint16_t u1 = 0x1234;
- uint32_t u2 = 0x56789abc;
- uint64_t u3 = 0xdef0123456789abc;
- uint16_t e1 = 0x3412;
- uint32_t e2 = 0xbc9a7856;
- uint64_t e3 = 0xbc9a78563412f0de;
- QVERIFY(bswap_16(u1) == e1);
- QVERIFY(bswap_32(u2) == e2);
- QVERIFY(bswap_64(u3) == e3);
-}
diff --git a/src/qt/test/compattests.h b/src/qt/test/compattests.h
deleted file mode 100644
index 1af97696b2..0000000000
--- a/src/qt/test/compattests.h
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (c) 2009-2016 The Bitcoin Core developers
-// Distributed under the MIT software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-#ifndef BITCOIN_QT_TEST_COMPATTESTS_H
-#define BITCOIN_QT_TEST_COMPATTESTS_H
-
-#include <QObject>
-#include <QTest>
-
-class CompatTests : public QObject
-{
- Q_OBJECT
-
-private Q_SLOTS:
- void bswapTests();
-};
-
-#endif // BITCOIN_QT_TEST_COMPATTESTS_H
diff --git a/src/qt/test/test_main.cpp b/src/qt/test/test_main.cpp
index a1baf6a402..eb86f027ef 100644
--- a/src/qt/test/test_main.cpp
+++ b/src/qt/test/test_main.cpp
@@ -11,7 +11,6 @@
#include <qt/test/apptests.h>
#include <qt/test/rpcnestedtests.h>
#include <qt/test/uritests.h>
-#include <qt/test/compattests.h>
#include <test/util/setup_common.h>
#ifdef ENABLE_WALLET
@@ -92,10 +91,6 @@ int main(int argc, char* argv[])
if (QTest::qExec(&test3) != 0) {
fInvalid = true;
}
- CompatTests test4;
- if (QTest::qExec(&test4) != 0) {
- fInvalid = true;
- }
#ifdef ENABLE_WALLET
WalletTests test5(app.node());
if (QTest::qExec(&test5) != 0) {
diff --git a/src/qt/trafficgraphwidget.cpp b/src/qt/trafficgraphwidget.cpp
index dabdf9d887..7e12410c80 100644
--- a/src/qt/trafficgraphwidget.cpp
+++ b/src/qt/trafficgraphwidget.cpp
@@ -79,7 +79,7 @@ void TrafficGraphWidget::paintEvent(QPaintEvent *)
int base = floor(log10(fMax));
float val = pow(10.0f, base);
- const QString units = tr("KB/s");
+ const QString units = tr("kB/s");
const float yMarginText = 2.0;
// draw lines
@@ -128,10 +128,10 @@ void TrafficGraphWidget::updateRates()
quint64 bytesIn = clientModel->node().getTotalBytesRecv(),
bytesOut = clientModel->node().getTotalBytesSent();
- float inRate = (bytesIn - nLastBytesIn) / 1024.0f * 1000 / timer->interval();
- float outRate = (bytesOut - nLastBytesOut) / 1024.0f * 1000 / timer->interval();
- vSamplesIn.push_front(inRate);
- vSamplesOut.push_front(outRate);
+ float in_rate_kilobytes_per_sec = static_cast<float>(bytesIn - nLastBytesIn) / timer->interval();
+ float out_rate_kilobytes_per_sec = static_cast<float>(bytesOut - nLastBytesOut) / timer->interval();
+ vSamplesIn.push_front(in_rate_kilobytes_per_sec);
+ vSamplesOut.push_front(out_rate_kilobytes_per_sec);
nLastBytesIn = bytesIn;
nLastBytesOut = bytesOut;
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index 2618776b02..f0ad141fa9 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -1050,15 +1050,15 @@ static RPCHelpMan gettxoutsetinfo()
RPCResult{
RPCResult::Type::OBJ, "", "",
{
- {RPCResult::Type::NUM, "height", "The current block height (index)"},
- {RPCResult::Type::STR_HEX, "bestblock", "The hash of the block at the tip of the chain"},
+ {RPCResult::Type::NUM, "height", "The block height (index) of the returned statistics"},
+ {RPCResult::Type::STR_HEX, "bestblock", "The hash of the block at which these statistics are calculated"},
{RPCResult::Type::NUM, "transactions", "The number of transactions with unspent outputs"},
{RPCResult::Type::NUM, "txouts", "The number of unspent transaction outputs"},
{RPCResult::Type::NUM, "bogosize", "A meaningless metric for UTXO set size"},
{RPCResult::Type::STR_HEX, "hash_serialized_2", /* optional */ true, "The serialized hash (only present if 'hash_serialized_2' hash_type is chosen)"},
{RPCResult::Type::STR_HEX, "muhash", /* optional */ true, "The serialized hash (only present if 'muhash' hash_type is chosen)"},
{RPCResult::Type::NUM, "disk_size", "The estimated size of the chainstate on disk"},
- {RPCResult::Type::STR_AMOUNT, "total_amount", "The total amount"},
+ {RPCResult::Type::STR_AMOUNT, "total_amount", "The total amount of coins in the UTXO set"},
}},
RPCExamples{
HelpExampleCli("gettxoutsetinfo", "")
diff --git a/src/test/bswap_tests.cpp b/src/test/bswap_tests.cpp
index c89cb5488d..2dbca4e8b6 100644
--- a/src/test/bswap_tests.cpp
+++ b/src/test/bswap_tests.cpp
@@ -11,7 +11,6 @@ BOOST_FIXTURE_TEST_SUITE(bswap_tests, BasicTestingSetup)
BOOST_AUTO_TEST_CASE(bswap_tests)
{
- // Sibling in bitcoin/src/qt/test/compattests.cpp
uint16_t u1 = 0x1234;
uint32_t u2 = 0x56789abc;
uint64_t u3 = 0xdef0123456789abc;
diff --git a/src/test/fuzz/pow.cpp b/src/test/fuzz/pow.cpp
index 53726ca893..47b4323e81 100644
--- a/src/test/fuzz/pow.cpp
+++ b/src/test/fuzz/pow.cpp
@@ -34,7 +34,7 @@ FUZZ_TARGET_INIT(pow, initialize_pow)
}
CBlockIndex current_block{*block_header};
{
- CBlockIndex* previous_block = !blocks.empty() ? &blocks[fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, blocks.size() - 1)] : nullptr;
+ CBlockIndex* previous_block = blocks.empty() ? nullptr : &PickValue(fuzzed_data_provider, blocks);
const int current_height = (previous_block != nullptr && previous_block->nHeight != std::numeric_limits<int>::max()) ? previous_block->nHeight + 1 : 0;
if (fuzzed_data_provider.ConsumeBool()) {
current_block.pprev = previous_block;
@@ -66,9 +66,9 @@ FUZZ_TARGET_INIT(pow, initialize_pow)
}
}
{
- const CBlockIndex* to = &blocks[fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, blocks.size() - 1)];
- const CBlockIndex* from = &blocks[fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, blocks.size() - 1)];
- const CBlockIndex* tip = &blocks[fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, blocks.size() - 1)];
+ const CBlockIndex* to = &PickValue(fuzzed_data_provider, blocks);
+ const CBlockIndex* from = &PickValue(fuzzed_data_provider, blocks);
+ const CBlockIndex* tip = &PickValue(fuzzed_data_provider, blocks);
try {
(void)GetBlockProofEquivalentTime(*to, *from, *tip, consensus_params);
} catch (const uint_error&) {
diff --git a/src/test/fuzz/process_message.cpp b/src/test/fuzz/process_message.cpp
index 04fc6da9b1..96e1cfa08f 100644
--- a/src/test/fuzz/process_message.cpp
+++ b/src/test/fuzz/process_message.cpp
@@ -68,8 +68,8 @@ void fuzz_target(FuzzBufferType buffer, const std::string& LIMIT_TO_MESSAGE_TYPE
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
- ConnmanTestMsg& connman = *(ConnmanTestMsg*)g_setup->m_node.connman.get();
- TestChainState& chainstate = *(TestChainState*)&g_setup->m_node.chainman->ActiveChainstate();
+ ConnmanTestMsg& connman = *static_cast<ConnmanTestMsg*>(g_setup->m_node.connman.get());
+ TestChainState& chainstate = *static_cast<TestChainState*>(&g_setup->m_node.chainman->ActiveChainstate());
SetMockTime(1610000000); // any time to successfully reset ibd
chainstate.ResetIbd();
diff --git a/src/test/fuzz/process_messages.cpp b/src/test/fuzz/process_messages.cpp
index ee402dba38..203c0ef8e1 100644
--- a/src/test/fuzz/process_messages.cpp
+++ b/src/test/fuzz/process_messages.cpp
@@ -35,8 +35,8 @@ FUZZ_TARGET_INIT(process_messages, initialize_process_messages)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
- ConnmanTestMsg& connman = *(ConnmanTestMsg*)g_setup->m_node.connman.get();
- TestChainState& chainstate = *(TestChainState*)&g_setup->m_node.chainman->ActiveChainstate();
+ ConnmanTestMsg& connman = *static_cast<ConnmanTestMsg*>(g_setup->m_node.connman.get());
+ TestChainState& chainstate = *static_cast<TestChainState*>(&g_setup->m_node.chainman->ActiveChainstate());
SetMockTime(1610000000); // any time to successfully reset ibd
chainstate.ResetIbd();
@@ -65,7 +65,7 @@ FUZZ_TARGET_INIT(process_messages, initialize_process_messages)
net_msg.m_type = random_message_type;
net_msg.data = ConsumeRandomLengthByteVector(fuzzed_data_provider);
- CNode& random_node = *peers.at(fuzzed_data_provider.ConsumeIntegralInRange<int>(0, peers.size() - 1));
+ CNode& random_node = *PickValue(fuzzed_data_provider, peers);
(void)connman.ReceiveMsgFrom(random_node, net_msg);
random_node.fPauseSend = false;
diff --git a/src/test/fuzz/tx_pool.cpp b/src/test/fuzz/tx_pool.cpp
index 2a9363a7c3..f84d6702a7 100644
--- a/src/test/fuzz/tx_pool.cpp
+++ b/src/test/fuzz/tx_pool.cpp
@@ -16,7 +16,8 @@
namespace {
const TestingSetup* g_setup;
-std::vector<COutPoint> g_outpoints_coinbase_init;
+std::vector<COutPoint> g_outpoints_coinbase_init_mature;
+std::vector<COutPoint> g_outpoints_coinbase_init_immature;
struct MockedTxPool : public CTxMemPool {
void RollingFeeUpdate()
@@ -34,7 +35,10 @@ void initialize_tx_pool()
for (int i = 0; i < 2 * COINBASE_MATURITY; ++i) {
CTxIn in = MineBlock(g_setup->m_node, P2WSH_OP_TRUE);
// Remember the txids to avoid expensive disk acess later on
- g_outpoints_coinbase_init.push_back(in.prevout);
+ auto& outpoints = i < COINBASE_MATURITY ?
+ g_outpoints_coinbase_init_mature :
+ g_outpoints_coinbase_init_immature;
+ outpoints.push_back(in.prevout);
}
SyncWithValidationInterfaceQueue();
}
@@ -86,9 +90,8 @@ FUZZ_TARGET_INIT(tx_pool_standard, initialize_tx_pool)
std::set<COutPoint> outpoints_rbf;
// All outpoints counting toward the total supply (subset of outpoints_rbf)
std::set<COutPoint> outpoints_supply;
- for (const auto& outpoint : g_outpoints_coinbase_init) {
+ for (const auto& outpoint : g_outpoints_coinbase_init_mature) {
Assert(outpoints_supply.insert(outpoint).second);
- if (outpoints_supply.size() >= COINBASE_MATURITY) break;
}
outpoints_rbf = outpoints_supply;
@@ -96,14 +99,13 @@ FUZZ_TARGET_INIT(tx_pool_standard, initialize_tx_pool)
constexpr CAmount SUPPLY_TOTAL{COINBASE_MATURITY * 50 * COIN};
CTxMemPool tx_pool_{/* estimator */ nullptr, /* check_ratio */ 1};
- MockedTxPool& tx_pool = *(MockedTxPool*)&tx_pool_;
+ MockedTxPool& tx_pool = *static_cast<MockedTxPool*>(&tx_pool_);
// Helper to query an amount
const CCoinsViewMemPool amount_view{WITH_LOCK(::cs_main, return &chainstate.CoinsTip()), tx_pool};
const auto GetAmount = [&](const COutPoint& outpoint) {
Coin c;
- amount_view.GetCoin(outpoint, c);
- Assert(!c.IsSpent());
+ Assert(amount_view.GetCoin(outpoint, c));
return c.out.nValue;
};
@@ -254,13 +256,12 @@ FUZZ_TARGET_INIT(tx_pool, initialize_tx_pool)
const auto& node = g_setup->m_node;
std::vector<uint256> txids;
- for (const auto& outpoint : g_outpoints_coinbase_init) {
+ for (const auto& outpoint : g_outpoints_coinbase_init_mature) {
txids.push_back(outpoint.hash);
- if (txids.size() >= COINBASE_MATURITY) break;
}
for (int i{0}; i <= 3; ++i) {
// Add some immature and non-existent outpoints
- txids.push_back(g_outpoints_coinbase_init.at(i).hash);
+ txids.push_back(g_outpoints_coinbase_init_immature.at(i).hash);
txids.push_back(ConsumeUInt256(fuzzed_data_provider));
}
diff --git a/src/test/fuzz/util.h b/src/test/fuzz/util.h
index df459fe60d..d5c54911c5 100644
--- a/src/test/fuzz/util.h
+++ b/src/test/fuzz/util.h
@@ -49,7 +49,7 @@ void CallOneOf(FuzzedDataProvider& fuzzed_data_provider, Callables... callables)
}
template <typename Collection>
-const auto& PickValue(FuzzedDataProvider& fuzzed_data_provider, const Collection& col)
+auto& PickValue(FuzzedDataProvider& fuzzed_data_provider, Collection& col)
{
const auto sz = col.size();
assert(sz >= 1);
diff --git a/src/test/fuzz/versionbits.cpp b/src/test/fuzz/versionbits.cpp
index a898e2782d..88c1a1a9cb 100644
--- a/src/test/fuzz/versionbits.cpp
+++ b/src/test/fuzz/versionbits.cpp
@@ -25,18 +25,18 @@ private:
const Consensus::Params dummy_params{};
public:
- const int64_t m_begin = 0;
- const int64_t m_end = 0;
- const int m_period = 0;
- const int m_threshold = 0;
- const int m_bit = 0;
+ const int64_t m_begin;
+ const int64_t m_end;
+ const int m_period;
+ const int m_threshold;
+ const int m_bit;
TestConditionChecker(int64_t begin, int64_t end, int period, int threshold, int bit)
: m_begin{begin}, m_end{end}, m_period{period}, m_threshold{threshold}, m_bit{bit}
{
assert(m_period > 0);
assert(0 <= m_threshold && m_threshold <= m_period);
- assert(0 <= m_bit && m_bit <= 32 && m_bit < VERSIONBITS_NUM_BITS);
+ assert(0 <= m_bit && m_bit < 32 && m_bit < VERSIONBITS_NUM_BITS);
}
bool Condition(const CBlockIndex* pindex, const Consensus::Params& params) const override { return Condition(pindex->nVersion); }
@@ -49,9 +49,10 @@ public:
int GetStateSinceHeightFor(const CBlockIndex* pindexPrev) const { return AbstractThresholdConditionChecker::GetStateSinceHeightFor(pindexPrev, dummy_params, m_cache); }
BIP9Stats GetStateStatisticsFor(const CBlockIndex* pindexPrev) const { return AbstractThresholdConditionChecker::GetStateStatisticsFor(pindexPrev, dummy_params); }
- bool Condition(int64_t version) const
+ bool Condition(int32_t version) const
{
- return ((version >> m_bit) & 1) != 0 && (version & VERSIONBITS_TOP_MASK) == VERSIONBITS_TOP_BITS;
+ uint32_t mask = ((uint32_t)1) << m_bit;
+ return (((version & VERSIONBITS_TOP_MASK) == VERSIONBITS_TOP_BITS) && (version & mask) != 0);
}
bool Condition(const CBlockIndex* pindex) const { return Condition(pindex->nVersion); }
@@ -94,18 +95,20 @@ public:
}
};
+std::unique_ptr<const CChainParams> g_params;
+
void initialize()
{
- SelectParams(CBaseChainParams::MAIN);
+ // this is actually comparatively slow, so only do it once
+ g_params = CreateChainParams(ArgsManager{}, CBaseChainParams::MAIN);
+ assert(g_params != nullptr);
}
-} // namespace
-constexpr uint32_t MAX_TIME = 4102444800; // 2100-01-01
+constexpr uint32_t MAX_START_TIME = 4102444800; // 2100-01-01
FUZZ_TARGET_INIT(versionbits, initialize)
{
- const CChainParams& params = Params();
-
+ const CChainParams& params = *g_params;
const int64_t interval = params.GetConsensus().nPowTargetSpacing;
assert(interval > 1); // need to be able to halve it
assert(interval < std::numeric_limits<int32_t>::max());
@@ -122,9 +125,9 @@ FUZZ_TARGET_INIT(versionbits, initialize)
// too many blocks at 10min each might cause uint32_t time to overflow if
// block_start_time is at the end of the range above
- assert(std::numeric_limits<uint32_t>::max() - MAX_TIME > interval * max_blocks);
+ assert(std::numeric_limits<uint32_t>::max() - MAX_START_TIME > interval * max_blocks);
- const int64_t block_start_time = fuzzed_data_provider.ConsumeIntegralInRange<uint32_t>(params.GenesisBlock().nTime, MAX_TIME);
+ const int64_t block_start_time = fuzzed_data_provider.ConsumeIntegralInRange<uint32_t>(params.GenesisBlock().nTime, MAX_START_TIME);
// what values for version will we use to signal / not signal?
const int32_t ver_signal = fuzzed_data_provider.ConsumeIntegral<int32_t>();
@@ -173,8 +176,10 @@ FUZZ_TARGET_INIT(versionbits, initialize)
if (checker.Condition(ver_nosignal)) return;
if (ver_nosignal < 0) return;
- // TOP_BITS should ensure version will be positive
+ // TOP_BITS should ensure version will be positive and meet min
+ // version requirement
assert(ver_signal > 0);
+ assert(ver_signal >= VERSIONBITS_LAST_OLD_BLOCK_VERSION);
// Now that we have chosen time and versions, setup to mine blocks
Blocks blocks(block_start_time, interval, ver_signal, ver_nosignal);
@@ -203,7 +208,7 @@ FUZZ_TARGET_INIT(versionbits, initialize)
}
// don't risk exceeding max_blocks or times may wrap around
- if (blocks.size() + period*2 > max_blocks) break;
+ if (blocks.size() + 2 * period > max_blocks) break;
}
// NOTE: fuzzed_data_provider may be fully consumed at this point and should not be used further
@@ -316,7 +321,7 @@ FUZZ_TARGET_INIT(versionbits, initialize)
assert(false);
}
- if (blocks.size() >= max_periods * period) {
+ if (blocks.size() >= period * max_periods) {
// we chose the timeout (and block times) so that by the time we have this many blocks it's all over
assert(state == ThresholdState::ACTIVE || state == ThresholdState::FAILED);
}
@@ -343,3 +348,4 @@ FUZZ_TARGET_INIT(versionbits, initialize)
}
}
}
+} // namespace
diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp
index c336705d50..858b90b8b2 100644
--- a/src/test/net_tests.cpp
+++ b/src/test/net_tests.cpp
@@ -396,6 +396,60 @@ BOOST_AUTO_TEST_CASE(cnetaddr_basic)
BOOST_CHECK(!addr.SetSpecial("totally bogus"));
}
+BOOST_AUTO_TEST_CASE(cnetaddr_tostring_canonical_ipv6)
+{
+ // Test that CNetAddr::ToString formats IPv6 addresses with zero compression as described in
+ // RFC 5952 ("A Recommendation for IPv6 Address Text Representation").
+ const std::map<std::string, std::string> canonical_representations_ipv6{
+ {"0000:0000:0000:0000:0000:0000:0000:0000", "::"},
+ {"000:0000:000:00:0:00:000:0000", "::"},
+ {"000:000:000:000:000:000:000:000", "::"},
+ {"00:00:00:00:00:00:00:00", "::"},
+ {"0:0:0:0:0:0:0:0", "::"},
+ {"0:0:0:0:0:0:0:1", "::1"},
+ {"2001:0:0:1:0:0:0:1", "2001:0:0:1::1"},
+ {"2001:0db8:0:0:1:0:0:1", "2001:db8::1:0:0:1"},
+ {"2001:0db8:85a3:0000:0000:8a2e:0370:7334", "2001:db8:85a3::8a2e:370:7334"},
+ {"2001:0db8::0001", "2001:db8::1"},
+ {"2001:0db8::0001:0000", "2001:db8::1:0"},
+ {"2001:0db8::1:0:0:1", "2001:db8::1:0:0:1"},
+ {"2001:db8:0000:0:1::1", "2001:db8::1:0:0:1"},
+ {"2001:db8:0000:1:1:1:1:1", "2001:db8:0:1:1:1:1:1"},
+ {"2001:db8:0:0:0:0:2:1", "2001:db8::2:1"},
+ {"2001:db8:0:0:0::1", "2001:db8::1"},
+ {"2001:db8:0:0:1:0:0:1", "2001:db8::1:0:0:1"},
+ {"2001:db8:0:0:1::1", "2001:db8::1:0:0:1"},
+ {"2001:DB8:0:0:1::1", "2001:db8::1:0:0:1"},
+ {"2001:db8:0:0::1", "2001:db8::1"},
+ {"2001:db8:0:0:aaaa::1", "2001:db8::aaaa:0:0:1"},
+ {"2001:db8:0:1:1:1:1:1", "2001:db8:0:1:1:1:1:1"},
+ {"2001:db8:0::1", "2001:db8::1"},
+ {"2001:db8:85a3:0:0:8a2e:370:7334", "2001:db8:85a3::8a2e:370:7334"},
+ {"2001:db8::0:1", "2001:db8::1"},
+ {"2001:db8::0:1:0:0:1", "2001:db8::1:0:0:1"},
+ {"2001:DB8::1", "2001:db8::1"},
+ {"2001:db8::1", "2001:db8::1"},
+ {"2001:db8::1:0:0:1", "2001:db8::1:0:0:1"},
+ {"2001:db8::1:1:1:1:1", "2001:db8:0:1:1:1:1:1"},
+ {"2001:db8::aaaa:0:0:1", "2001:db8::aaaa:0:0:1"},
+ {"2001:db8:aaaa:bbbb:cccc:dddd:0:1", "2001:db8:aaaa:bbbb:cccc:dddd:0:1"},
+ {"2001:db8:aaaa:bbbb:cccc:dddd::1", "2001:db8:aaaa:bbbb:cccc:dddd:0:1"},
+ {"2001:db8:aaaa:bbbb:cccc:dddd:eeee:0001", "2001:db8:aaaa:bbbb:cccc:dddd:eeee:1"},
+ {"2001:db8:aaaa:bbbb:cccc:dddd:eeee:001", "2001:db8:aaaa:bbbb:cccc:dddd:eeee:1"},
+ {"2001:db8:aaaa:bbbb:cccc:dddd:eeee:01", "2001:db8:aaaa:bbbb:cccc:dddd:eeee:1"},
+ {"2001:db8:aaaa:bbbb:cccc:dddd:eeee:1", "2001:db8:aaaa:bbbb:cccc:dddd:eeee:1"},
+ {"2001:db8:aaaa:bbbb:cccc:dddd:eeee:aaaa", "2001:db8:aaaa:bbbb:cccc:dddd:eeee:aaaa"},
+ {"2001:db8:aaaa:bbbb:cccc:dddd:eeee:AAAA", "2001:db8:aaaa:bbbb:cccc:dddd:eeee:aaaa"},
+ {"2001:db8:aaaa:bbbb:cccc:dddd:eeee:AaAa", "2001:db8:aaaa:bbbb:cccc:dddd:eeee:aaaa"},
+ };
+ for (const auto& [input_address, expected_canonical_representation_output] : canonical_representations_ipv6) {
+ CNetAddr net_addr;
+ BOOST_REQUIRE(LookupHost(input_address, net_addr, false));
+ BOOST_REQUIRE(net_addr.IsIPv6());
+ BOOST_CHECK_EQUAL(net_addr.ToString(), expected_canonical_representation_output);
+ }
+}
+
BOOST_AUTO_TEST_CASE(cnetaddr_serialize_v1)
{
CNetAddr addr;
diff --git a/src/wallet/load.cpp b/src/wallet/load.cpp
index 4543f6fb4c..6a59bc2b38 100644
--- a/src/wallet/load.cpp
+++ b/src/wallet/load.cpp
@@ -76,7 +76,7 @@ bool VerifyWallets(interfaces::Chain& chain)
bilingual_str error_string;
if (!MakeWalletDatabase(wallet_file, options, status, error_string)) {
if (status == DatabaseStatus::FAILED_NOT_FOUND) {
- chain.initWarning(Untranslated(strprintf("Skipping -wallet path that doesn't exist. %s\n", error_string.original)));
+ chain.initWarning(Untranslated(strprintf("Skipping -wallet path that doesn't exist. %s", error_string.original)));
} else {
chain.initError(error_string);
return false;
diff --git a/test/functional/feature_anchors.py b/test/functional/feature_anchors.py
new file mode 100755
index 0000000000..a60a723b3e
--- /dev/null
+++ b/test/functional/feature_anchors.py
@@ -0,0 +1,85 @@
+#!/usr/bin/env python3
+# Copyright (c) 2020 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+"""Test Anchors functionality"""
+
+import os
+
+from test_framework.p2p import P2PInterface
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import assert_equal
+
+
+def check_node_connections(*, node, num_in, num_out):
+ info = node.getnetworkinfo()
+ assert_equal(info["connections_in"], num_in)
+ assert_equal(info["connections_out"], num_out)
+
+
+class AnchorsTest(BitcoinTestFramework):
+ def set_test_params(self):
+ self.num_nodes = 1
+
+ def setup_network(self):
+ self.setup_nodes()
+
+ def run_test(self):
+ self.log.info("Add 2 block-relay-only connections to node 0")
+ for i in range(2):
+ self.log.debug(f"block-relay-only: {i}")
+ self.nodes[0].add_outbound_p2p_connection(
+ P2PInterface(), p2p_idx=i, connection_type="block-relay-only"
+ )
+
+ self.log.info("Add 5 inbound connections to node 0")
+ for i in range(5):
+ self.log.debug(f"inbound: {i}")
+ self.nodes[0].add_p2p_connection(P2PInterface())
+
+ self.log.info("Check node 0 connections")
+ check_node_connections(node=self.nodes[0], num_in=5, num_out=2)
+
+ # 127.0.0.1
+ ip = "7f000001"
+
+ # Since the ip is always 127.0.0.1 for this case,
+ # we store only the port to identify the peers
+ block_relay_nodes_port = []
+ inbound_nodes_port = []
+ for p in self.nodes[0].getpeerinfo():
+ addr_split = p["addr"].split(":")
+ if p["connection_type"] == "block-relay-only":
+ block_relay_nodes_port.append(hex(int(addr_split[1]))[2:])
+ else:
+ inbound_nodes_port.append(hex(int(addr_split[1]))[2:])
+
+ self.log.info("Stop node 0")
+ self.stop_node(0)
+
+ node0_anchors_path = os.path.join(
+ self.nodes[0].datadir, "regtest", "anchors.dat"
+ )
+
+ # It should contain only the block-relay-only addresses
+ self.log.info("Check the addresses in anchors.dat")
+
+ with open(node0_anchors_path, "rb") as file_handler:
+ anchors = file_handler.read().hex()
+
+ for port in block_relay_nodes_port:
+ ip_port = ip + port
+ assert ip_port in anchors
+ for port in inbound_nodes_port:
+ ip_port = ip + port
+ assert ip_port not in anchors
+
+ self.log.info("Start node 0")
+ self.start_node(0)
+
+ self.log.info("When node starts, check if anchors.dat doesn't exist anymore")
+ assert not os.path.exists(node0_anchors_path)
+
+
+if __name__ == "__main__":
+ AnchorsTest().main()
diff --git a/test/functional/feature_utxo_set_hash.py b/test/functional/feature_utxo_set_hash.py
index 6e6046d84d..ce00faffee 100755
--- a/test/functional/feature_utxo_set_hash.py
+++ b/test/functional/feature_utxo_set_hash.py
@@ -6,7 +6,6 @@
import struct
-from test_framework.blocktools import create_transaction
from test_framework.messages import (
CBlock,
COutPoint,
@@ -15,38 +14,30 @@ from test_framework.messages import (
from test_framework.muhash import MuHash3072
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal
+from test_framework.wallet import MiniWallet
class UTXOSetHashTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 1
self.setup_clean_chain = True
- def skip_test_if_missing_module(self):
- self.skip_if_no_wallet()
-
- def test_deterministic_hash_results(self):
- self.log.info("Test deterministic UTXO set hash results")
-
- # These depend on the setup_clean_chain option, the chain loaded from the cache
- assert_equal(self.nodes[0].gettxoutsetinfo()['hash_serialized_2'], "b32ec1dda5a53cd025b95387aad344a801825fe46a60ff952ce26528f01d3be8")
- assert_equal(self.nodes[0].gettxoutsetinfo("muhash")['muhash'], "dd5ad2a105c2d29495f577245c357409002329b9f4d6182c0af3dc2f462555c8")
-
def test_muhash_implementation(self):
self.log.info("Test MuHash implementation consistency")
node = self.nodes[0]
+ wallet = MiniWallet(node)
+ mocktime = node.getblockheader(node.getblockhash(0))['time'] + 1
+ node.setmocktime(mocktime)
# Generate 100 blocks and remove the first since we plan to spend its
# coinbase
- block_hashes = node.generate(100)
+ block_hashes = wallet.generate(1) + node.generate(99)
blocks = list(map(lambda block: FromHex(CBlock(), node.getblock(block, False)), block_hashes))
- spending = blocks.pop(0)
+ blocks.pop(0)
# Create a spending transaction and mine a block which includes it
- tx = create_transaction(node, spending.vtx[0].rehash(), node.getnewaddress(), amount=49)
- txid = node.sendrawtransaction(hexstring=tx.serialize_with_witness().hex(), maxfeerate=0)
-
- tx_block = node.generateblock(output=node.getnewaddress(), transactions=[txid])
+ txid = wallet.send_self_transfer(from_node=node)['txid']
+ tx_block = node.generateblock(output=wallet.get_address(), transactions=[txid])
blocks.append(FromHex(CBlock(), node.getblock(tx_block['hash'], False)))
# Serialize the outputs that should be in the UTXO set and add them to
@@ -77,8 +68,11 @@ class UTXOSetHashTest(BitcoinTestFramework):
assert_equal(finalized[::-1].hex(), node_muhash)
+ self.log.info("Test deterministic UTXO set hash results")
+ assert_equal(node.gettxoutsetinfo()['hash_serialized_2'], "5b1b44097406226c0eb8e1362cd17a1f346522cf9390a8175a57a5262cb1963f")
+ assert_equal(node.gettxoutsetinfo("muhash")['muhash'], "4b8803075d7151d06fad3e88b68ba726886794873fbfa841d12aefb2cc2b881b")
+
def run_test(self):
- self.test_deterministic_hash_results()
self.test_muhash_implementation()
diff --git a/test/functional/p2p_feefilter.py b/test/functional/p2p_feefilter.py
index a2a122b352..52dc4de3bd 100755
--- a/test/functional/p2p_feefilter.py
+++ b/test/functional/p2p_feefilter.py
@@ -61,6 +61,7 @@ class FeeFilterTest(BitcoinTestFramework):
def run_test(self):
self.test_feefilter_forcerelay()
self.test_feefilter()
+ self.test_feefilter_blocksonly()
def test_feefilter_forcerelay(self):
self.log.info('Check that peers without forcerelay permission (default) get a feefilter message')
@@ -119,6 +120,19 @@ class FeeFilterTest(BitcoinTestFramework):
conn.wait_for_invs_to_match(txids)
conn.clear_invs()
+ def test_feefilter_blocksonly(self):
+ """Test that we don't send fee filters to block-relay-only peers and when we're in blocksonly mode."""
+ self.log.info("Check that we don't send fee filters to block-relay-only peers.")
+ feefilter_peer = self.nodes[0].add_outbound_p2p_connection(FeefilterConn(), p2p_idx=0, connection_type="block-relay-only")
+ feefilter_peer.sync_with_ping()
+ feefilter_peer.assert_feefilter_received(False)
+
+ self.log.info("Check that we don't send fee filters when in blocksonly mode.")
+ self.restart_node(0, ["-blocksonly"])
+ feefilter_peer = self.nodes[0].add_p2p_connection(FeefilterConn())
+ feefilter_peer.sync_with_ping()
+ feefilter_peer.assert_feefilter_received(False)
+
if __name__ == '__main__':
FeeFilterTest().main()
diff --git a/test/functional/test_framework/messages.py b/test/functional/test_framework/messages.py
index a18a9ec109..5a9736a7a3 100755
--- a/test/functional/test_framework/messages.py
+++ b/test/functional/test_framework/messages.py
@@ -1045,13 +1045,11 @@ class msg_version:
self.nStartingHeight = struct.unpack("<i", f.read(4))[0]
- if self.nVersion >= 70001:
- # Relay field is optional for version 70001 onwards
- try:
- self.relay = struct.unpack("<b", f.read(1))[0]
- except:
- self.relay = 0
- else:
+ # Relay field is optional for version 70001 onwards
+ # But, unconditionally check it to match behaviour in bitcoind
+ try:
+ self.relay = struct.unpack("<b", f.read(1))[0]
+ except struct.error:
self.relay = 0
def serialize(self):
diff --git a/test/functional/test_framework/wallet.py b/test/functional/test_framework/wallet.py
index 38fbf3c1a6..a906a21dd0 100644
--- a/test/functional/test_framework/wallet.py
+++ b/test/functional/test_framework/wallet.py
@@ -49,6 +49,9 @@ class MiniWallet:
self._utxos.append({'txid': cb_tx['txid'], 'vout': 0, 'value': cb_tx['vout'][0]['value']})
return blocks
+ def get_address(self):
+ return self._address
+
def get_utxo(self, *, txid=''):
"""
Returns a utxo and marks it as spent (pops it from the internal list)
diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py
index defe334bd8..001d161612 100755
--- a/test/functional/test_runner.py
+++ b/test/functional/test_runner.py
@@ -279,6 +279,7 @@ BASE_SCRIPTS = [
'p2p_ping.py',
'rpc_scantxoutset.py',
'feature_logging.py',
+ 'feature_anchors.py',
'p2p_node_network_limited.py',
'p2p_permissions.py',
'feature_blocksdir.py',