diff options
94 files changed, 634 insertions, 449 deletions
diff --git a/.travis.yml b/.travis.yml index bb5e0a854c..780bc9944f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -66,7 +66,7 @@ jobs: - set -o errexit; source ./ci/lint/06_script.sh - stage: test - name: '32-bit + dash [GOAL: install] [CentOS 7] [gui]' + name: '32-bit + dash [GOAL: install] [CentOS 8] [gui]' env: >- FILE_ENV="./ci/test/00_setup_env_i686_centos.sh" diff --git a/build_msvc/bitcoin_config.h b/build_msvc/bitcoin_config.h index 2e6101a52e..53aead38b5 100644 --- a/build_msvc/bitcoin_config.h +++ b/build_msvc/bitcoin_config.h @@ -15,13 +15,10 @@ #define CLIENT_VERSION_IS_RELEASE false /* Major version */ -#define CLIENT_VERSION_MAJOR 0 +#define CLIENT_VERSION_MAJOR 21 /* Minor version */ -#define CLIENT_VERSION_MINOR 21 - -/* Build revision */ -#define CLIENT_VERSION_REVISION 99 +#define CLIENT_VERSION_MINOR 99 /* Copyright holder(s) before %s replacement */ #define COPYRIGHT_HOLDERS "The %s developers" @@ -259,7 +256,7 @@ #define PACKAGE_NAME "Bitcoin Core" /* Define to the full name and version of this package. */ -#define PACKAGE_STRING "Bitcoin Core 0.21.99" +#define PACKAGE_STRING "Bitcoin Core 21.99.0" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "bitcoin" @@ -268,7 +265,7 @@ #define PACKAGE_URL "https://bitcoincore.org/" /* Define to the version of this package. */ -#define PACKAGE_VERSION "0.21.99" +#define PACKAGE_VERSION "21.99.0" /* Define to necessary symbol if this constant uses a non-standard name on your system. */ diff --git a/ci/test/00_setup_env_i686_centos.sh b/ci/test/00_setup_env_i686_centos.sh index e58003ab19..52cdb75a0c 100644 --- a/ci/test/00_setup_env_i686_centos.sh +++ b/ci/test/00_setup_env_i686_centos.sh @@ -7,9 +7,10 @@ export LC_ALL=C.UTF-8 export HOST=i686-pc-linux-gnu -export CONTAINER_NAME=ci_i686_centos_7 -export DOCKER_NAME_TAG=centos:7 -export DOCKER_PACKAGES="gcc-c++ glibc-devel.x86_64 libstdc++-devel.x86_64 glibc-devel.i686 libstdc++-devel.i686 ccache libtool make git python3 python36-zmq which patch lbzip2 dash" +export CONTAINER_NAME=ci_i686_centos_8 +export DOCKER_NAME_TAG=centos:8 +export DOCKER_PACKAGES="gcc-c++ glibc-devel.x86_64 libstdc++-devel.x86_64 glibc-devel.i686 libstdc++-devel.i686 ccache libtool make git python3 python3-zmq which patch lbzip2 dash rsync coreutils" export GOAL="install" -export BITCOIN_CONFIG="--enable-zmq --with-gui=qt5 --enable-reduce-exports --with-boost-process" +export DEP_OPTS="NO_QT=1" # Gui disabled for now to avoid build failures +export BITCOIN_CONFIG="--enable-zmq --with-gui=no --enable-reduce-exports --with-boost-process" export CONFIG_SHELL="/bin/dash" diff --git a/ci/test/00_setup_env_native_nowallet.sh b/ci/test/00_setup_env_native_nowallet.sh index 0fe7d35435..7ff044c020 100644 --- a/ci/test/00_setup_env_native_nowallet.sh +++ b/ci/test/00_setup_env_native_nowallet.sh @@ -7,8 +7,8 @@ export LC_ALL=C.UTF-8 export CONTAINER_NAME=ci_native_nowallet -export DOCKER_NAME_TAG=ubuntu:18.04 # Use bionic to have one config run the tests in python3.6, see doc/dependencies.md (3.6 is not available in xenial/16.04) -export PACKAGES="python3-zmq clang-3.9 llvm-3.9" # Use clang-3.9 to test C++11 compatibility, see doc/dependencies.md (3.8 is not available in bionic) +export DOCKER_NAME_TAG=ubuntu:18.04 # Use bionic to have one config run the tests in python3.6, see doc/dependencies.md +export PACKAGES="python3-zmq clang-5.0 llvm-5.0" # Use clang-5 to test C++17 compatibility, see doc/dependencies.md export DEP_OPTS="NO_WALLET=1" export GOAL="install" -export BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports CC=clang-3.9 CXX=clang++-3.9 --with-boost-process" +export BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports CC=clang-5.0 CXX=clang++-5.0 --with-boost-process" diff --git a/ci/test/00_setup_env_native_qt5.sh b/ci/test/00_setup_env_native_qt5.sh index 8668662299..dc6b2aecb5 100644 --- a/ci/test/00_setup_env_native_qt5.sh +++ b/ci/test/00_setup_env_native_qt5.sh @@ -7,7 +7,7 @@ export LC_ALL=C.UTF-8 export CONTAINER_NAME=ci_native_qt5 -export DOCKER_NAME_TAG=ubuntu:18.04 # Check that bionic can compile our c++17 and run our functional tests in python3 +export DOCKER_NAME_TAG=ubuntu:18.04 # Check that bionic gcc-7 can compile our c++17 and run our functional tests in python3, see doc/dependencies.md export PACKAGES="python3-zmq qtbase5-dev qttools5-dev-tools libdbus-1-dev libharfbuzz-dev" export DEP_OPTS="NO_QT=1 NO_UPNP=1 DEBUG=1 ALLOW_HOST_PACKAGES=1" export TEST_RUNNER_EXTRA="--previous-releases --coverage --extended --exclude feature_dbcrash" # Run extended tests so that coverage does not fail, but exclude the very slow dbcrash @@ -16,4 +16,4 @@ export RUN_UNIT_TESTS_SEQUENTIAL="true" export RUN_UNIT_TESTS="false" export GOAL="install" export PREVIOUS_RELEASES_TO_DOWNLOAD="v0.15.2 v0.16.3 v0.17.2 v0.18.1 v0.19.1" -export BITCOIN_CONFIG="--enable-zmq --with-libs=no --with-gui=qt5 --enable-glibc-back-compat --enable-reduce-exports --enable-c++17 --enable-debug CFLAGS=\"-g0 -O2 -funsigned-char\" CXXFLAGS=\"-g0 -O2 -funsigned-char\" --with-boost-process" +export BITCOIN_CONFIG="--enable-zmq --with-libs=no --with-gui=qt5 --enable-glibc-back-compat --enable-reduce-exports --enable-debug CFLAGS=\"-g0 -O2 -funsigned-char\" CXXFLAGS=\"-g0 -O2 -funsigned-char\" --with-boost-process" diff --git a/ci/test/04_install.sh b/ci/test/04_install.sh index db74fe6569..cce0c7e49e 100755 --- a/ci/test/04_install.sh +++ b/ci/test/04_install.sh @@ -60,8 +60,8 @@ if [ -n "$DPKG_ADD_ARCH" ]; then fi if [[ $DOCKER_NAME_TAG == centos* ]]; then - ${CI_RETRY_EXE} DOCKER_EXEC yum -y install epel-release - ${CI_RETRY_EXE} DOCKER_EXEC yum -y install $DOCKER_PACKAGES $PACKAGES + ${CI_RETRY_EXE} DOCKER_EXEC dnf -y install epel-release + ${CI_RETRY_EXE} DOCKER_EXEC dnf -y --allowerasing install $DOCKER_PACKAGES $PACKAGES elif [ "$CI_USE_APT_INSTALL" != "no" ]; then ${CI_RETRY_EXE} DOCKER_EXEC apt-get update ${CI_RETRY_EXE} DOCKER_EXEC apt-get install --no-install-recommends --no-upgrade -y $PACKAGES $DOCKER_PACKAGES diff --git a/configure.ac b/configure.ac index 60a3b9f2c8..a512fce83e 100644 --- a/configure.ac +++ b/configure.ac @@ -1,14 +1,13 @@ AC_PREREQ([2.69]) -define(_CLIENT_VERSION_MAJOR, 0) -define(_CLIENT_VERSION_MINOR, 21) -define(_CLIENT_VERSION_REVISION, 99) +define(_CLIENT_VERSION_MAJOR, 21) +define(_CLIENT_VERSION_MINOR, 99) define(_CLIENT_VERSION_BUILD, 0) define(_CLIENT_VERSION_RC, 0) define(_CLIENT_VERSION_IS_RELEASE, false) define(_COPYRIGHT_YEAR, 2020) define(_COPYRIGHT_HOLDERS,[The %s developers]) define(_COPYRIGHT_HOLDERS_SUBSTITUTION,[[Bitcoin Core]]) -AC_INIT([Bitcoin Core],m4_join([.], _CLIENT_VERSION_MAJOR, _CLIENT_VERSION_MINOR, _CLIENT_VERSION_REVISION, m4_if(_CLIENT_VERSION_BUILD, [0], [], _CLIENT_VERSION_BUILD))m4_if(_CLIENT_VERSION_RC, [0], [], [rc]_CLIENT_VERSION_RC),[https://github.com/bitcoin/bitcoin/issues],[bitcoin],[https://bitcoincore.org/]) +AC_INIT([Bitcoin Core],m4_join([.], _CLIENT_VERSION_MAJOR, _CLIENT_VERSION_MINOR, _CLIENT_VERSION_BUILD)m4_if(_CLIENT_VERSION_RC, [0], [], [rc]_CLIENT_VERSION_RC),[https://github.com/bitcoin/bitcoin/issues],[bitcoin],[https://bitcoincore.org/]) AC_CONFIG_SRCDIR([src/validation.cpp]) AC_CONFIG_HEADERS([src/config/bitcoin-config.h]) AC_CONFIG_AUX_DIR([build-aux]) @@ -68,18 +67,8 @@ case $host in ;; esac -AC_ARG_ENABLE([c++17], - [AS_HELP_STRING([--enable-c++17], - [enable compilation in c++17 mode (disabled by default)])], - [use_cxx17=$enableval], - [use_cxx17=no]) - -dnl Require C++11 or C++17 compiler (no GNU extensions) -if test "x$use_cxx17" = xyes -o "x$enable_fuzz" = xyes ; then - AX_CXX_COMPILE_STDCXX([17], [noext], [mandatory]) -else - AX_CXX_COMPILE_STDCXX([11], [noext], [mandatory]) -fi +dnl Require C++17 compiler (no GNU extensions) +AX_CXX_COMPILE_STDCXX([17], [noext], [mandatory]) dnl Check if -latomic is required for <std::atomic> CHECK_ATOMIC @@ -1638,7 +1627,6 @@ AM_CONDITIONAL([WORDS_BIGENDIAN],[test x$ac_cv_c_bigendian = xyes]) AC_DEFINE(CLIENT_VERSION_MAJOR, _CLIENT_VERSION_MAJOR, [Major version]) AC_DEFINE(CLIENT_VERSION_MINOR, _CLIENT_VERSION_MINOR, [Minor version]) -AC_DEFINE(CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION, [Build revision]) AC_DEFINE(CLIENT_VERSION_BUILD, _CLIENT_VERSION_BUILD, [Version Build]) AC_DEFINE(CLIENT_VERSION_IS_RELEASE, _CLIENT_VERSION_IS_RELEASE, [Version is release]) AC_DEFINE(COPYRIGHT_YEAR, _COPYRIGHT_YEAR, [Copyright year]) @@ -1648,7 +1636,6 @@ define(_COPYRIGHT_HOLDERS_FINAL, [patsubst(_COPYRIGHT_HOLDERS, [%s], [_COPYRIGHT AC_DEFINE(COPYRIGHT_HOLDERS_FINAL, "_COPYRIGHT_HOLDERS_FINAL", [Copyright holder(s)]) AC_SUBST(CLIENT_VERSION_MAJOR, _CLIENT_VERSION_MAJOR) AC_SUBST(CLIENT_VERSION_MINOR, _CLIENT_VERSION_MINOR) -AC_SUBST(CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION) AC_SUBST(CLIENT_VERSION_BUILD, _CLIENT_VERSION_BUILD) AC_SUBST(CLIENT_VERSION_IS_RELEASE, _CLIENT_VERSION_IS_RELEASE) AC_SUBST(COPYRIGHT_YEAR, _COPYRIGHT_YEAR) diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml index f873742a6d..0e2c5be0fa 100644 --- a/contrib/gitian-descriptors/gitian-linux.yml +++ b/contrib/gitian-descriptors/gitian-linux.yml @@ -1,5 +1,5 @@ --- -name: "bitcoin-core-linux-0.22" +name: "bitcoin-core-linux-22" enable_cache: true distro: "ubuntu" suites: diff --git a/contrib/gitian-descriptors/gitian-osx.yml b/contrib/gitian-descriptors/gitian-osx.yml index 0479a49514..852207edbb 100644 --- a/contrib/gitian-descriptors/gitian-osx.yml +++ b/contrib/gitian-descriptors/gitian-osx.yml @@ -1,5 +1,5 @@ --- -name: "bitcoin-core-osx-0.22" +name: "bitcoin-core-osx-22" enable_cache: true distro: "ubuntu" suites: diff --git a/contrib/gitian-descriptors/gitian-win.yml b/contrib/gitian-descriptors/gitian-win.yml index 7900c7e07e..fc79745e69 100644 --- a/contrib/gitian-descriptors/gitian-win.yml +++ b/contrib/gitian-descriptors/gitian-win.yml @@ -1,5 +1,5 @@ --- -name: "bitcoin-core-win-0.22" +name: "bitcoin-core-win-22" enable_cache: true distro: "ubuntu" suites: diff --git a/contrib/macdeploy/custom_dsstore.py b/contrib/macdeploy/custom_dsstore.py index dc1c1882dd..7ab42ea5d4 100755 --- a/contrib/macdeploy/custom_dsstore.py +++ b/contrib/macdeploy/custom_dsstore.py @@ -2,7 +2,6 @@ # Copyright (c) 2013-2018 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. -import biplist from ds_store import DSStore from mac_alias import Alias import sys @@ -47,7 +46,7 @@ alias.volume.disk_image_alias.target.filename = package_name_ns + '.temp.dmg' alias.volume.disk_image_alias.target.carbon_path = 'Macintosh HD:Users:\x00bitcoinuser:\x00Documents:\x00bitcoin:\x00bitcoin:\x00' + package_name_ns + '.temp.dmg' alias.volume.disk_image_alias.target.posix_path = 'Users/bitcoinuser/Documents/bitcoin/bitcoin/' + package_name_ns + '.temp.dmg' alias.target.carbon_path = package_name_ns + ':.background:\x00background.tiff' -icvp['backgroundImageAlias'] = biplist.Data(alias.to_bytes()) +icvp['backgroundImageAlias'] = alias.to_bytes() ds['.']['icvp'] = icvp ds['.']['vSrn'] = ('long', 1) diff --git a/contrib/seeds/README.md b/contrib/seeds/README.md index 502c20d0d6..3bca094d3b 100644 --- a/contrib/seeds/README.md +++ b/contrib/seeds/README.md @@ -16,6 +16,12 @@ The seeds compiled into the release are created from sipa's DNS seed data, like ## Dependencies -Ubuntu: +Ubuntu, Debian: sudo apt-get install python3-dnspython + +and/or for other operating systems: + + pip install dnspython + +See https://dnspython.readthedocs.io/en/latest/installation.html for more information. diff --git a/contrib/seeds/makeseeds.py b/contrib/seeds/makeseeds.py index 6d9d49ad2f..9be6a690a6 100755 --- a/contrib/seeds/makeseeds.py +++ b/contrib/seeds/makeseeds.py @@ -136,7 +136,7 @@ def lookup_asn(net, ip): ipaddr = res.rstrip('.') # 2.0.0.1.4.8.6.0.b.0.0.2.0.0.2.3 prefix = '.origin6' - asn = int([x.to_text() for x in dns.resolver.query('.'.join( + asn = int([x.to_text() for x in dns.resolver.resolve('.'.join( reversed(ipaddr.split('.'))) + prefix + '.asn.cymru.com', 'TXT').response.answer][0].split('\"')[1].split(' ')[0]) return asn diff --git a/contrib/signet/README.md b/contrib/signet/README.md new file mode 100644 index 0000000000..c4aa5ae2f7 --- /dev/null +++ b/contrib/signet/README.md @@ -0,0 +1,19 @@ +Contents +======== +This directory contains tools related to Signet, both for running a Signet yourself and for using one. + +getcoins.py +=========== + +A script to call a faucet to get Signet coins. + +Syntax: `getcoins.py [-h|--help] [-c|--cmd=<bitcoin-cli path>] [-f|--faucet=<faucet URL>] [-a|--addr=<signet bech32 address>] [-p|--password=<faucet password>] [--] [<bitcoin-cli args>]` + +* `--cmd` lets you customize the bitcoin-cli path. By default it will look for it in the PATH +* `--faucet` lets you specify which faucet to use; the faucet is assumed to be compatible with https://github.com/kallewoof/bitcoin-faucet +* `--addr` lets you specify a Signet address; by default, the address must be a bech32 address. This and `--cmd` above complement each other (i.e. you do not need `bitcoin-cli` if you use `--addr`) +* `--password` lets you specify a faucet password; this is handy if you are in a classroom and set up your own faucet for your students; (above faucet does not limit by IP when password is enabled) + +If using the default network, invoking the script with no arguments should be sufficient under normal +circumstances, but if multiple people are behind the same IP address, the faucet will by default only +accept one claim per day. See `--password` above. diff --git a/contrib/signet/getcoins.py b/contrib/signet/getcoins.py new file mode 100755 index 0000000000..691f0bb1b6 --- /dev/null +++ b/contrib/signet/getcoins.py @@ -0,0 +1,36 @@ +#!/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. + +import argparse +import subprocess +import requests +import sys + +parser = argparse.ArgumentParser(description='Script to get coins from a faucet.', epilog='You may need to start with double-dash (--) when providing bitcoin-cli arguments.') +parser.add_argument('-c', '--cmd', dest='cmd', default='bitcoin-cli', help='bitcoin-cli command to use') +parser.add_argument('-f', '--faucet', dest='faucet', default='https://signetfaucet.com/claim', help='URL of the faucet') +parser.add_argument('-a', '--addr', dest='addr', default='', help='Bitcoin address to which the faucet should send') +parser.add_argument('-p', '--password', dest='password', default='', help='Faucet password, if any') +parser.add_argument('bitcoin_cli_args', nargs='*', help='Arguments to pass on to bitcoin-cli (default: -signet)') + +args = parser.parse_args() + +if args.addr == '': + if args.bitcoin_cli_args == []: + args.bitcoin_cli_args = ['-signet'] + # get address for receiving coins + try: + args.addr = subprocess.check_output([args.cmd] + args.bitcoin_cli_args + ['getnewaddress', 'faucet', 'bech32']).strip() + except FileNotFoundError: + print('The binary', args.cmd, 'could not be found.') + exit() + +data = {'address': args.addr, 'password': args.password} +try: + res = requests.post(args.faucet, data=data) +except: + print('Unexpected error when contacting faucet:', sys.exc_info()[0]) + exit() +print(res.text) diff --git a/depends/config.site.in b/depends/config.site.in index 87a3379303..f4531830c8 100644 --- a/depends/config.site.in +++ b/depends/config.site.in @@ -1,4 +1,14 @@ -depends_prefix="`dirname ${ac_site_file}`/.." +# shellcheck shell=sh disable=SC2034 # Many variables set will be used in + # ./configure but shellcheck doesn't know + # that, hence: disable=SC2034 + +true # Dummy command because shellcheck treats all directives before first + # command as file-wide, and we only want to disable for one line. + # + # See: https://github.com/koalaman/shellcheck/wiki/Directive + +# shellcheck disable=SC2154 +depends_prefix="$(cd "$(dirname ${ac_site_file})/.." && pwd)" cross_compiling=maybe host_alias=@HOST@ @@ -50,7 +60,7 @@ if test x@host_os@ = xdarwin; then fi PATH=$depends_prefix/native/bin:$PATH -PKG_CONFIG="`which pkg-config` --static" +PKG_CONFIG="$(which pkg-config) --static" # These two need to remain exported because pkg-config does not see them # otherwise. That means they must be unexported at the end of configure.ac to @@ -69,7 +79,7 @@ fi if test -n "@CXX@" -a -z "${CXX}"; then CXX="@CXX@" fi -PYTHONPATH=$depends_prefix/native/lib/python3/dist-packages:$PYTHONPATH +PYTHONPATH="${depends_prefix}/native/lib/python3/dist-packages${PYTHONPATH:+${PATH_SEPARATOR}}${PYTHONPATH}" if test -n "@AR@"; then AR=@AR@ diff --git a/depends/packages/native_biplist.mk b/depends/packages/native_biplist.mk deleted file mode 100644 index c3054cbd1a..0000000000 --- a/depends/packages/native_biplist.mk +++ /dev/null @@ -1,15 +0,0 @@ -package=native_biplist -$(package)_version=1.0.3 -$(package)_download_path=https://bitbucket.org/wooster/biplist/downloads -$(package)_file_name=biplist-$($(package)_version).tar.gz -$(package)_sha256_hash=4c0549764c5fe50b28042ec21aa2e14fe1a2224e239a1dae77d9e7f3932aa4c6 -$(package)_install_libdir=$(build_prefix)/lib/python3/dist-packages - -define $(package)_build_cmds - python3 setup.py build -endef - -define $(package)_stage_cmds - mkdir -p $($(package)_install_libdir) && \ - python3 setup.py install --root=$($(package)_staging_dir) --prefix=$(build_prefix) --install-lib=$($(package)_install_libdir) -endef diff --git a/depends/packages/native_ds_store.mk b/depends/packages/native_ds_store.mk index f99b689ecd..44108925a4 100644 --- a/depends/packages/native_ds_store.mk +++ b/depends/packages/native_ds_store.mk @@ -1,10 +1,9 @@ package=native_ds_store -$(package)_version=1.1.2 +$(package)_version=1.3.0 $(package)_download_path=https://github.com/al45tair/ds_store/archive/ $(package)_file_name=v$($(package)_version).tar.gz -$(package)_sha256_hash=3b3ecb7bf0a5157f5b6010bc3af7c141fb0ad3527084e63336220d22744bc20c +$(package)_sha256_hash=76b3280cd4e19e5179defa23fb594a9dd32643b0c80d774bd3108361d94fb46d $(package)_install_libdir=$(build_prefix)/lib/python3/dist-packages -$(package)_dependencies=native_biplist define $(package)_build_cmds python3 setup.py build diff --git a/depends/packages/packages.mk b/depends/packages/packages.mk index 4627acb521..ca06b6dd7e 100644 --- a/depends/packages/packages.mk +++ b/depends/packages/packages.mk @@ -20,7 +20,7 @@ upnp_packages=miniupnpc multiprocess_packages = libmultiprocess capnp multiprocess_native_packages = native_libmultiprocess native_capnp -darwin_native_packages = native_biplist native_ds_store native_mac_alias +darwin_native_packages = native_ds_store native_mac_alias ifneq ($(build_os),darwin) darwin_native_packages += native_cctools native_cdrkit native_libdmg-hfsplus diff --git a/depends/packages/qt.mk b/depends/packages/qt.mk index 083bc68d66..6c77dca8d5 100644 --- a/depends/packages/qt.mk +++ b/depends/packages/qt.mk @@ -12,6 +12,7 @@ $(package)_patches=fix_qt_pkgconfig.patch mac-qmake.conf fix_configure_mac.patch $(package)_patches+= fix_rcc_determinism.patch fix_riscv64_arch.patch xkb-default.patch no-xlib.patch $(package)_patches+= fix_android_qmake_conf.patch fix_android_jni_static.patch dont_hardcode_pwd.patch $(package)_patches+= freetype_back_compat.patch drop_lrelease_dependency.patch fix_powerpc_libpng.patch +$(package)_patches+= fix_mingw_cross_compile.patch # Update OSX_QT_TRANSLATIONS when this is updated $(package)_qttranslations_file_name=qttranslations-$($(package)_suffix) @@ -124,6 +125,7 @@ $(package)_config_opts_darwin += -device-option MAC_SDK_VERSION=$(OSX_SDK_VERSIO $(package)_config_opts_darwin += -device-option CROSS_COMPILE="$(host)-" $(package)_config_opts_darwin += -device-option MAC_MIN_VERSION=$(OSX_MIN_VERSION) $(package)_config_opts_darwin += -device-option MAC_TARGET=$(host) +$(package)_config_opts_darwin += -device-option XCODE_VERSION=$(XCODE_VERSION) endif $(package)_config_opts_linux = -qt-xkbcommon-x11 @@ -192,33 +194,52 @@ define $(package)_extract_cmds tar --no-same-owner --strip-components=1 -xf $($(package)_source_dir)/$($(package)_qttools_file_name) -C qttools endef +# Preprocessing steps work as follows: +# +# 1. Apply our patches to the extracted source. See each patch for more info. +# +# 2. Point to lrelease in qttools/bin/lrelease; otherwise Qt will look for it in +# $(host)/native/bin/lrelease and not find it. +# +# 3. Create a macOS-Clang-Linux mkspec using our mac-qmake.conf. +# +# 4. After making a copy of the mkspec for the linux-arm-gnueabi host, named +# bitcoin-linux-g++, replace instances of linux-arm-gnueabi with $(host). This +# way we can generically support hosts like riscv64-linux-gnu, which Qt doesn't +# ship a mkspec for. See it's usage in config_opts_* above. +# +# 5. Put our C, CXX and LD FLAGS into gcc-base.conf. Only used for non-host builds. +# +# 6. Do similar for the win32-g++ mkspec. +# +# 7. In clang.conf, swap out clang & clang++, for our compiler + flags. See #17466. +# +# 8. Adjust a regex in toolchain.prf, to accomodate Guix's usage of +# CROSS_LIBRARY_PATH. See #15277. define $(package)_preprocess_cmds patch -p1 -i $($(package)_patch_dir)/freetype_back_compat.patch && \ patch -p1 -i $($(package)_patch_dir)/fix_powerpc_libpng.patch && \ - sed -i.old "s|updateqm.commands = \$$$$\$$$$LRELEASE|updateqm.commands = $($(package)_extract_dir)/qttools/bin/lrelease|" qttranslations/translations/translations.pro && \ patch -p1 -i $($(package)_patch_dir)/drop_lrelease_dependency.patch && \ - patch -p1 -i $($(package)_patch_dir)/dont_hardcode_pwd.patch &&\ + patch -p1 -i $($(package)_patch_dir)/dont_hardcode_pwd.patch && \ + patch -p1 -i $($(package)_patch_dir)/fix_qt_pkgconfig.patch && \ + patch -p1 -i $($(package)_patch_dir)/fix_configure_mac.patch && \ + patch -p1 -i $($(package)_patch_dir)/fix_no_printer.patch && \ + patch -p1 -i $($(package)_patch_dir)/fix_rcc_determinism.patch && \ + patch -p1 -i $($(package)_patch_dir)/xkb-default.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_riscv64_arch.patch && \ + patch -p1 -i $($(package)_patch_dir)/no-xlib.patch && \ + patch -p1 -i $($(package)_patch_dir)/fix_mingw_cross_compile.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/Info.plist.lib qtbase/mkspecs/macx-clang-linux/ &&\ - cp -f qtbase/mkspecs/macx-clang/Info.plist.app qtbase/mkspecs/macx-clang-linux/ &&\ cp -f qtbase/mkspecs/macx-clang/qplatformdefs.h qtbase/mkspecs/macx-clang-linux/ &&\ cp -f $($(package)_patch_dir)/mac-qmake.conf qtbase/mkspecs/macx-clang-linux/qmake.conf && \ cp -r qtbase/mkspecs/linux-arm-gnueabi-g++ qtbase/mkspecs/bitcoin-linux-g++ && \ sed -i.old "s/arm-linux-gnueabi-/$(host)-/g" qtbase/mkspecs/bitcoin-linux-g++/qmake.conf && \ - patch -p1 -i $($(package)_patch_dir)/fix_qt_pkgconfig.patch &&\ - patch -p1 -i $($(package)_patch_dir)/fix_configure_mac.patch &&\ - patch -p1 -i $($(package)_patch_dir)/fix_no_printer.patch &&\ - patch -p1 -i $($(package)_patch_dir)/fix_rcc_determinism.patch &&\ - patch -p1 -i $($(package)_patch_dir)/xkb-default.patch &&\ - patch -p1 -i $($(package)_patch_dir)/fix_android_qmake_conf.patch &&\ - patch -p1 -i $($(package)_patch_dir)/fix_android_jni_static.patch &&\ echo "!host_build: QMAKE_CFLAGS += $($(package)_cflags) $($(package)_cppflags)" >> qtbase/mkspecs/common/gcc-base.conf && \ echo "!host_build: QMAKE_CXXFLAGS += $($(package)_cxxflags) $($(package)_cppflags)" >> qtbase/mkspecs/common/gcc-base.conf && \ echo "!host_build: QMAKE_LFLAGS += $($(package)_ldflags)" >> qtbase/mkspecs/common/gcc-base.conf && \ - patch -p1 -i $($(package)_patch_dir)/fix_riscv64_arch.patch &&\ - patch -p1 -i $($(package)_patch_dir)/no-xlib.patch &&\ - echo "QMAKE_LINK_OBJECT_MAX = 10" >> qtbase/mkspecs/win32-g++/qmake.conf &&\ - echo "QMAKE_LINK_OBJECT_SCRIPT = object_script" >> qtbase/mkspecs/win32-g++/qmake.conf &&\ sed -i.old "s|QMAKE_CFLAGS += |!host_build: QMAKE_CFLAGS = $($(package)_cflags) $($(package)_cppflags) |" qtbase/mkspecs/win32-g++/qmake.conf && \ sed -i.old "s|QMAKE_CXXFLAGS += |!host_build: QMAKE_CXXFLAGS = $($(package)_cxxflags) $($(package)_cppflags) |" qtbase/mkspecs/win32-g++/qmake.conf && \ sed -i.old "0,/^QMAKE_LFLAGS_/s|^QMAKE_LFLAGS_|!host_build: QMAKE_LFLAGS = $($(package)_ldflags)\n&|" qtbase/mkspecs/win32-g++/qmake.conf && \ diff --git a/depends/patches/qt/fix_mingw_cross_compile.patch b/depends/patches/qt/fix_mingw_cross_compile.patch new file mode 100644 index 0000000000..67f76f1d85 --- /dev/null +++ b/depends/patches/qt/fix_mingw_cross_compile.patch @@ -0,0 +1,25 @@ +commit 5a992a549adfe5a587bbcd6cd2b2cee47d236e27 +Author: fanquake <fanquake@gmail.com> +Date: Fri Sep 4 08:13:44 2020 +0800 + + Work around broken mingw cross-compilation + + See upstream issues: + https://bugreports.qt.io/browse/QTBUG-63637 + https://bugreports.qt.io/browse/QTBUG-63659 + https://codereview.qt-project.org/q/8bebded9 + + We should be able to drop this once we are building qt 5.10.1 or later. + + Added in #12971. + +diff --git a/qtbase/mkspecs/win32-g++/qmake.conf b/qtbase/mkspecs/win32-g++/qmake.conf +index e071a0d1..ad229b10 100644 +--- a/qtbase/mkspecs/win32-g++/qmake.conf ++++ b/qtbase/mkspecs/win32-g++/qmake.conf +@@ -87,3 +87,5 @@ QMAKE_NM = $${CROSS_COMPILE}nm -P + include(../common/angle.conf) + + load(qt_config) ++QMAKE_LINK_OBJECT_MAX = 10 ++QMAKE_LINK_OBJECT_SCRIPT = object_script diff --git a/depends/patches/qt/mac-qmake.conf b/depends/patches/qt/mac-qmake.conf index 4cd96df29f..0142667547 100644 --- a/depends/patches/qt/mac-qmake.conf +++ b/depends/patches/qt/mac-qmake.conf @@ -1,12 +1,12 @@ MAKEFILE_GENERATOR = UNIX -CONFIG += app_bundle incremental global_init_link_order lib_version_first plugin_no_soname absolute_library_soname +CONFIG += app_bundle incremental lib_version_first absolute_library_soname QMAKE_INCREMENTAL_STYLE = sublib include(../common/macx.conf) include(../common/gcc-base-mac.conf) include(../common/clang.conf) include(../common/clang-mac.conf) QMAKE_MAC_SDK_PATH=$${MAC_SDK_PATH} -QMAKE_XCODE_VERSION=4.3 +QMAKE_XCODE_VERSION = $${XCODE_VERSION} QMAKE_XCODE_DEVELOPER_PATH=/Developer QMAKE_MACOSX_DEPLOYMENT_TARGET = $${MAC_MIN_VERSION} QMAKE_MAC_SDK=macosx diff --git a/doc/dependencies.md b/doc/dependencies.md index faefcf758e..4df7c761da 100644 --- a/doc/dependencies.md +++ b/doc/dependencies.md @@ -7,11 +7,11 @@ These are the dependencies currently used by Bitcoin Core. You can find instruct | --- | --- | --- | --- | --- | --- | | Berkeley DB | [4.8.30](https://www.oracle.com/technetwork/database/database-technologies/berkeleydb/downloads/index.html) | 4.8.x | No | | | | Boost | [1.70.0](https://www.boost.org/users/download/) | [1.58.0](https://github.com/bitcoin/bitcoin/pull/19667) | No | | | -| Clang | | [3.3+](https://releases.llvm.org/download.html) (C++11 support) | | | | +| Clang | | [5.0+](https://releases.llvm.org/download.html) (C++17 support) | | | | | Expat | [2.2.7](https://libexpat.github.io/) | | No | Yes | | | fontconfig | [2.12.1](https://www.freedesktop.org/software/fontconfig/release/) | | No | Yes | | | FreeType | [2.7.1](https://download.savannah.gnu.org/releases/freetype) | | No | | [Yes](https://github.com/bitcoin/bitcoin/blob/master/depends/packages/qt.mk) (Android only) | -| GCC | | [4.8+](https://gcc.gnu.org/) (C++11 support) | | | | +| GCC | | [7+](https://gcc.gnu.org/) (C++17 support) | | | | | HarfBuzz-NG | | | | | [Yes](https://github.com/bitcoin/bitcoin/blob/master/depends/packages/qt.mk) | | libevent | [2.1.11-stable](https://github.com/libevent/libevent/releases) | [2.0.21](https://github.com/bitcoin/bitcoin/pull/18676) | No | | | | libpng | | | | | [Yes](https://github.com/bitcoin/bitcoin/blob/master/depends/packages/qt.mk) | diff --git a/doc/descriptors.md b/doc/descriptors.md index 181ff77e50..63acb9167f 100644 --- a/doc/descriptors.md +++ b/doc/descriptors.md @@ -50,7 +50,7 @@ Output descriptors currently support: - `wsh(multi(2,03a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7,03774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cb,03d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a))` describes a P2WSH *2-of-3* multisig output with keys in the specified order. - `sh(wsh(multi(1,03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8,03499fdf9e895e719cfd64e67f07d38e3226aa7b63678949e6e49b241a60e823e4,02d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e)))` describes a P2SH-P2WSH *1-of-3* multisig output with keys in the specified order. - `pk(xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8)` describes a P2PK output with the public key of the specified xpub. -- `pkh(xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw/1'/2)` describes a P2PKH output with child key *1'/2* of the specified xpub. +- `pkh(xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw/1/2)` describes a P2PKH output with child key *1/2* of the specified xpub. - `pkh([d34db33f/44'/0'/0']xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1/*)` describes a set of P2PKH outputs, but additionally specifies that the specified xpub is a child of a master with fingerprint `d34db33f`, and derived using path `44'/0'/0'`. - `wsh(multi(1,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/1/0/*,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/0/0/*))` describes a set of *1-of-2* P2WSH multisig outputs where the first multisig key is the *1/0/`i`* child of the first specified xpub and the second multisig key is the *0/0/`i`* child of the second specified xpub, and `i` is any number in a configurable range (`0-1000` by default). - `wsh(sortedmulti(1,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/1/0/*,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/0/0/*))` describes a set of *1-of-2* P2WSH multisig outputs where one multisig key is the *1/0/`i`* child of the first specified xpub and the other multisig key is the *0/0/`i`* child of the second specified xpub, and `i` is any number in a configurable range (`0-1000` by default). The order of public keys in the resulting witnessScripts is determined by the lexicographic order of the public keys at that index. diff --git a/doc/release-process.md b/doc/release-process.md index 8191c3034d..cedb36d51d 100644 --- a/doc/release-process.md +++ b/doc/release-process.md @@ -18,10 +18,11 @@ Release Process ### Before every major release * On both the master branch and the new release branch: - - update `CLIENT_VERSION_MINOR` in [`configure.ac`](../configure.ac) - - update `CLIENT_VERSION_MINOR`, `PACKAGE_VERSION`, and `PACKAGE_STRING` in [`build_msvc/bitcoin_config.h`](/build_msvc/bitcoin_config.h) + - update `CLIENT_VERSION_MAJOR` in [`configure.ac`](../configure.ac) + - update `CLIENT_VERSION_MAJOR`, `PACKAGE_VERSION`, and `PACKAGE_STRING` in [`build_msvc/bitcoin_config.h`](/build_msvc/bitcoin_config.h) * On the new release branch in [`configure.ac`](../configure.ac) and [`build_msvc/bitcoin_config.h`](/build_msvc/bitcoin_config.h) (see [this commit](https://github.com/bitcoin/bitcoin/commit/742f7dd)): - - set `CLIENT_VERSION_REVISION` to `0` + - set `CLIENT_VERSION_MINOR` to `0` + - set `CLIENT_VERSION_BUILD` to `0` - set `CLIENT_VERSION_IS_RELEASE` to `true` #### Before branch-off diff --git a/share/qt/Info.plist.in b/share/qt/Info.plist.in index 3befba3425..8c0eb22540 100644 --- a/share/qt/Info.plist.in +++ b/share/qt/Info.plist.in @@ -17,13 +17,13 @@ <string>APPL</string> <key>NSHumanReadableCopyright</key> - <string>@CLIENT_VERSION_MAJOR@.@CLIENT_VERSION_MINOR@.@CLIENT_VERSION_REVISION@.@CLIENT_VERSION_BUILD@, Copyright © 2009-@COPYRIGHT_YEAR@ @COPYRIGHT_HOLDERS_FINAL@</string> + <string>@CLIENT_VERSION_MAJOR@.@CLIENT_VERSION_MINOR@.@.@CLIENT_VERSION_BUILD@, Copyright © 2009-@COPYRIGHT_YEAR@ @COPYRIGHT_HOLDERS_FINAL@</string> <key>CFBundleShortVersionString</key> - <string>@CLIENT_VERSION_MAJOR@.@CLIENT_VERSION_MINOR@.@CLIENT_VERSION_REVISION@</string> + <string>@CLIENT_VERSION_MAJOR@.@CLIENT_VERSION_MINOR@.@CLIENT_VERSION_BUILD@</string> <key>CFBundleVersion</key> - <string>@CLIENT_VERSION_MAJOR@.@CLIENT_VERSION_MINOR@.@CLIENT_VERSION_REVISION@</string> + <string>@CLIENT_VERSION_MAJOR@.@CLIENT_VERSION_MINOR@.@CLIENT_VERSION_BUILD@</string> <key>CFBundleSignature</key> <string>????</string> diff --git a/share/setup.nsi.in b/share/setup.nsi.in index 5431909bb2..1c4dcf3842 100644 --- a/share/setup.nsi.in +++ b/share/setup.nsi.in @@ -56,7 +56,7 @@ CRCCheck on XPStyle on BrandingText " " ShowInstDetails show -VIProductVersion @CLIENT_VERSION_MAJOR@.@CLIENT_VERSION_MINOR@.@CLIENT_VERSION_REVISION@.@CLIENT_VERSION_BUILD@ +VIProductVersion @CLIENT_VERSION_MAJOR@.@CLIENT_VERSION_MINOR@.@.@CLIENT_VERSION_BUILD@ VIAddVersionKey ProductName "@PACKAGE_NAME@" VIAddVersionKey ProductVersion "@PACKAGE_VERSION@" VIAddVersionKey CompanyName "${COMPANY}" diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 9fc7533e0d..87166ecb79 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -294,6 +294,7 @@ if ENABLE_WALLET BITCOIN_TESTS += \ wallet/test/psbt_wallet_tests.cpp \ wallet/test/wallet_tests.cpp \ + wallet/test/walletdb_tests.cpp \ wallet/test/wallet_crypto_tests.cpp \ wallet/test/coinselector_tests.cpp \ wallet/test/init_tests.cpp \ diff --git a/src/addrman.h b/src/addrman.h index 04dd30b375..9ac67b7af6 100644 --- a/src/addrman.h +++ b/src/addrman.h @@ -281,8 +281,18 @@ protected: //! Select several addresses at once. void GetAddr_(std::vector<CAddress> &vAddr, size_t max_addresses, size_t max_pct) EXCLUSIVE_LOCKS_REQUIRED(cs); - //! Mark an entry as currently-connected-to. - void Connected_(const CService &addr, int64_t nTime) EXCLUSIVE_LOCKS_REQUIRED(cs); + /** We have successfully connected to this peer. Calling this function + * updates the CAddress's nTime, which is used in our IsTerrible() + * decisions and gossiped to peers. Callers should be careful that updating + * this information doesn't leak topology information to network spies. + * + * net_processing calls this function when it *disconnects* from a peer to + * not leak information about currently connected peers. + * + * @param[in] addr The address of the peer we were connected to + * @param[in] nTime The time that we were last connected to this peer + */ + void Connected_(const CService& addr, int64_t nTime) EXCLUSIVE_LOCKS_REQUIRED(cs); //! Update an entry's service bits. void SetServices_(const CService &addr, ServiceFlags nServices) EXCLUSIVE_LOCKS_REQUIRED(cs); @@ -704,7 +714,7 @@ public: return vAddr; } - //! Mark an entry as currently-connected-to. + //! Outer function for Connected_() void Connected(const CService &addr, int64_t nTime = GetAdjustedTime()) { LOCK(cs); diff --git a/src/bitcoin-cli-res.rc b/src/bitcoin-cli-res.rc index 58f8f1e8a2..405a302261 100644 --- a/src/bitcoin-cli-res.rc +++ b/src/bitcoin-cli-res.rc @@ -1,8 +1,8 @@ #include <windows.h> // needed for VERSIONINFO #include "clientversion.h" // holds the needed client version information -#define VER_PRODUCTVERSION CLIENT_VERSION_MAJOR,CLIENT_VERSION_MINOR,CLIENT_VERSION_REVISION,CLIENT_VERSION_BUILD -#define VER_PRODUCTVERSION_STR STRINGIZE(CLIENT_VERSION_MAJOR) "." STRINGIZE(CLIENT_VERSION_MINOR) "." STRINGIZE(CLIENT_VERSION_REVISION) "." STRINGIZE(CLIENT_VERSION_BUILD) +#define VER_PRODUCTVERSION CLIENT_VERSION_MAJOR,CLIENT_VERSION_MINOR,CLIENT_VERSION_BUILD +#define VER_PRODUCTVERSION_STR STRINGIZE(CLIENT_VERSION_MAJOR) "." STRINGIZE(CLIENT_VERSION_MINOR) "." STRINGIZE(CLIENT_VERSION_BUILD) #define VER_FILEVERSION VER_PRODUCTVERSION #define VER_FILEVERSION_STR VER_PRODUCTVERSION_STR diff --git a/src/bitcoin-tx-res.rc b/src/bitcoin-tx-res.rc index 3e49b820bc..b545ce9dbe 100644 --- a/src/bitcoin-tx-res.rc +++ b/src/bitcoin-tx-res.rc @@ -1,8 +1,8 @@ #include <windows.h> // needed for VERSIONINFO #include "clientversion.h" // holds the needed client version information -#define VER_PRODUCTVERSION CLIENT_VERSION_MAJOR,CLIENT_VERSION_MINOR,CLIENT_VERSION_REVISION,CLIENT_VERSION_BUILD -#define VER_PRODUCTVERSION_STR STRINGIZE(CLIENT_VERSION_MAJOR) "." STRINGIZE(CLIENT_VERSION_MINOR) "." STRINGIZE(CLIENT_VERSION_REVISION) "." STRINGIZE(CLIENT_VERSION_BUILD) +#define VER_PRODUCTVERSION CLIENT_VERSION_MAJOR,CLIENT_VERSION_MINOR,CLIENT_VERSION_BUILD +#define VER_PRODUCTVERSION_STR STRINGIZE(CLIENT_VERSION_MAJOR) "." STRINGIZE(CLIENT_VERSION_MINOR) "." STRINGIZE(CLIENT_VERSION_BUILD) #define VER_FILEVERSION VER_PRODUCTVERSION #define VER_FILEVERSION_STR VER_PRODUCTVERSION_STR diff --git a/src/bitcoin-wallet-res.rc b/src/bitcoin-wallet-res.rc index e9fa2dbb40..59346ab8f6 100644 --- a/src/bitcoin-wallet-res.rc +++ b/src/bitcoin-wallet-res.rc @@ -1,8 +1,8 @@ #include <windows.h> // needed for VERSIONINFO #include "clientversion.h" // holds the needed client version information -#define VER_PRODUCTVERSION CLIENT_VERSION_MAJOR,CLIENT_VERSION_MINOR,CLIENT_VERSION_REVISION,CLIENT_VERSION_BUILD -#define VER_PRODUCTVERSION_STR STRINGIZE(CLIENT_VERSION_MAJOR) "." STRINGIZE(CLIENT_VERSION_MINOR) "." STRINGIZE(CLIENT_VERSION_REVISION) "." STRINGIZE(CLIENT_VERSION_BUILD) +#define VER_PRODUCTVERSION CLIENT_VERSION_MAJOR,CLIENT_VERSION_MINOR,CLIENT_VERSION_BUILD +#define VER_PRODUCTVERSION_STR STRINGIZE(CLIENT_VERSION_MAJOR) "." STRINGIZE(CLIENT_VERSION_MINOR) "." STRINGIZE(CLIENT_VERSION_BUILD) #define VER_FILEVERSION VER_PRODUCTVERSION #define VER_FILEVERSION_STR VER_PRODUCTVERSION_STR diff --git a/src/bitcoind-res.rc b/src/bitcoind-res.rc index 3a64acd5d1..a98b50c899 100644 --- a/src/bitcoind-res.rc +++ b/src/bitcoind-res.rc @@ -1,8 +1,8 @@ #include <windows.h> // needed for VERSIONINFO #include "clientversion.h" // holds the needed client version information -#define VER_PRODUCTVERSION CLIENT_VERSION_MAJOR,CLIENT_VERSION_MINOR,CLIENT_VERSION_REVISION,CLIENT_VERSION_BUILD -#define VER_PRODUCTVERSION_STR STRINGIZE(CLIENT_VERSION_MAJOR) "." STRINGIZE(CLIENT_VERSION_MINOR) "." STRINGIZE(CLIENT_VERSION_REVISION) "." STRINGIZE(CLIENT_VERSION_BUILD) +#define VER_PRODUCTVERSION CLIENT_VERSION_MAJOR,CLIENT_VERSION_MINOR,CLIENT_VERSION_BUILD +#define VER_PRODUCTVERSION_STR STRINGIZE(CLIENT_VERSION_MAJOR) "." STRINGIZE(CLIENT_VERSION_MINOR) "." STRINGIZE(CLIENT_VERSION_BUILD) #define VER_FILEVERSION VER_PRODUCTVERSION #define VER_FILEVERSION_STR VER_PRODUCTVERSION_STR diff --git a/src/bloom.h b/src/bloom.h index 9307257852..24dc607cd9 100644 --- a/src/bloom.h +++ b/src/bloom.h @@ -94,7 +94,18 @@ public: * insert()'ed ... but may also return true for items that were not inserted. * * It needs around 1.8 bytes per element per factor 0.1 of false positive rate. - * (More accurately: 3/(log(256)*log(2)) * log(1/fpRate) * nElements bytes) + * For example, if we want 1000 elements, we'd need: + * - ~1800 bytes for a false positive rate of 0.1 + * - ~3600 bytes for a false positive rate of 0.01 + * - ~5400 bytes for a false positive rate of 0.001 + * + * If we make these simplifying assumptions: + * - logFpRate / log(0.5) doesn't get rounded or clamped in the nHashFuncs calculation + * - nElements is even, so that nEntriesPerGeneration == nElements / 2 + * + * Then we get a more accurate estimate for filter bytes: + * + * 3/(log(256)*log(2)) * log(1/fpRate) * nElements */ class CRollingBloomFilter { diff --git a/src/clientversion.cpp b/src/clientversion.cpp index 993967a180..aaf041602b 100644 --- a/src/clientversion.cpp +++ b/src/clientversion.cpp @@ -30,8 +30,7 @@ const std::string CLIENT_NAME("Satoshi"); #define BUILD_DESC BUILD_GIT_TAG #define BUILD_SUFFIX "" #else - #define BUILD_DESC "v" STRINGIZE(CLIENT_VERSION_MAJOR) "." STRINGIZE(CLIENT_VERSION_MINOR) \ - "." STRINGIZE(CLIENT_VERSION_REVISION) "." STRINGIZE(CLIENT_VERSION_BUILD) + #define BUILD_DESC "v" STRINGIZE(CLIENT_VERSION_MAJOR) "." STRINGIZE(CLIENT_VERSION_MINOR) "." STRINGIZE(CLIENT_VERSION_BUILD) #ifdef BUILD_GIT_COMMIT #define BUILD_SUFFIX "-" BUILD_GIT_COMMIT #elif defined(GIT_COMMIT_ID) @@ -45,10 +44,7 @@ const std::string CLIENT_BUILD(BUILD_DESC BUILD_SUFFIX); static std::string FormatVersion(int nVersion) { - if (nVersion % 100 == 0) - return strprintf("%d.%d.%d", nVersion / 1000000, (nVersion / 10000) % 100, (nVersion / 100) % 100); - else - return strprintf("%d.%d.%d.%d", nVersion / 1000000, (nVersion / 10000) % 100, (nVersion / 100) % 100, nVersion % 100); + return strprintf("%d.%d.%d", nVersion / 10000, (nVersion / 100) % 100, nVersion % 100); } std::string FormatFullVersion() diff --git a/src/clientversion.h b/src/clientversion.h index 363094b696..c925b8f084 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -10,7 +10,7 @@ #endif //HAVE_CONFIG_H // Check that required client information is defined -#if !defined(CLIENT_VERSION_MAJOR) || !defined(CLIENT_VERSION_MINOR) || !defined(CLIENT_VERSION_REVISION) || !defined(CLIENT_VERSION_BUILD) || !defined(CLIENT_VERSION_IS_RELEASE) || !defined(COPYRIGHT_YEAR) +#if !defined(CLIENT_VERSION_MAJOR) || !defined(CLIENT_VERSION_MINOR) || !defined(CLIENT_VERSION_BUILD) || !defined(CLIENT_VERSION_IS_RELEASE) || !defined(COPYRIGHT_YEAR) #error Client version information missing: version is not defined by bitcoin-config.h or in any other way #endif @@ -36,9 +36,8 @@ #include <vector> static const int CLIENT_VERSION = - 1000000 * CLIENT_VERSION_MAJOR - + 10000 * CLIENT_VERSION_MINOR - + 100 * CLIENT_VERSION_REVISION + 10000 * CLIENT_VERSION_MAJOR + + 100 * CLIENT_VERSION_MINOR + 1 * CLIENT_VERSION_BUILD; extern const std::string CLIENT_NAME; diff --git a/src/core_read.cpp b/src/core_read.cpp index 121e62457c..a2eebbd528 100644 --- a/src/core_read.cpp +++ b/src/core_read.cpp @@ -15,16 +15,15 @@ #include <version.h> #include <boost/algorithm/string/classification.hpp> -#include <boost/algorithm/string/replace.hpp> #include <boost/algorithm/string/split.hpp> #include <algorithm> #include <string> -CScript ParseScript(const std::string& s) -{ - CScript result; +namespace { +opcodetype ParseOpCode(const std::string& s) +{ static std::map<std::string, opcodetype> mapOpNames; if (mapOpNames.empty()) @@ -40,11 +39,23 @@ CScript ParseScript(const std::string& s) continue; mapOpNames[strName] = static_cast<opcodetype>(op); // Convenience: OP_ADD and just ADD are both recognized: - boost::algorithm::replace_first(strName, "OP_", ""); - mapOpNames[strName] = static_cast<opcodetype>(op); + if (strName.compare(0, 3, "OP_") == 0) { // strName starts with "OP_" + mapOpNames[strName.substr(3)] = static_cast<opcodetype>(op); + } } } + auto it = mapOpNames.find(s); + if (it == mapOpNames.end()) throw std::runtime_error("script parse error: unknown opcode"); + return it->second; +} + +} // namespace + +CScript ParseScript(const std::string& s) +{ + CScript result; + std::vector<std::string> words; boost::algorithm::split(words, s, boost::algorithm::is_any_of(" \t\n"), boost::algorithm::token_compress_on); @@ -82,14 +93,10 @@ CScript ParseScript(const std::string& s) std::vector<unsigned char> value(w->begin()+1, w->end()-1); result << value; } - else if (mapOpNames.count(*w)) - { - // opcode, e.g. OP_ADD or ADD: - result << mapOpNames[*w]; - } else { - throw std::runtime_error("script parse error"); + // opcode, e.g. OP_ADD or ADD: + result << ParseOpCode(*w); } } diff --git a/src/init.cpp b/src/init.cpp index 495d96f938..1e41616e94 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1039,7 +1039,7 @@ bool AppInitParameterInteraction(const ArgsManager& args) // Trim requested connection counts, to fit into system limitations // <int> in std::min<int>(...) to work around FreeBSD compilation issue described in #2695 - nFD = RaiseFileDescriptorLimit(nMaxConnections + MIN_CORE_FILEDESCRIPTORS + MAX_ADDNODE_CONNECTIONS); + nFD = RaiseFileDescriptorLimit(nMaxConnections + MIN_CORE_FILEDESCRIPTORS + MAX_ADDNODE_CONNECTIONS + nBind); #ifdef USE_POLL int fd_max = nFD; #else diff --git a/src/net.cpp b/src/net.cpp index 20c1763ea6..9c6d7b6375 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -629,34 +629,21 @@ void CNode::copyStats(CNodeStats &stats, const std::vector<bool> &m_asmap) } #undef X -/** - * Receive bytes from the buffer and deserialize them into messages. - * - * @param[in] pch A pointer to the raw data - * @param[in] nBytes Size of the data - * @param[out] complete Set True if at least one message has been - * deserialized and is ready to be processed - * @return True if the peer should stay connected, - * False if the peer should be disconnected from. - */ -bool CNode::ReceiveMsgBytes(const char *pch, unsigned int nBytes, bool& complete) +bool CNode::ReceiveMsgBytes(Span<const uint8_t> msg_bytes, bool& complete) { complete = false; const auto time = GetTime<std::chrono::microseconds>(); LOCK(cs_vRecv); nLastRecv = std::chrono::duration_cast<std::chrono::seconds>(time).count(); - nRecvBytes += nBytes; - while (nBytes > 0) { + nRecvBytes += msg_bytes.size(); + while (msg_bytes.size() > 0) { // absorb network data - int handled = m_deserializer->Read(pch, nBytes); + int handled = m_deserializer->Read(msg_bytes); if (handled < 0) { // Serious header problem, disconnect from the peer. return false; } - pch += handled; - nBytes -= handled; - if (m_deserializer->Complete()) { // decompose a transport agnostic CNetMessage from the deserializer uint32_t out_err_raw_size{0}; @@ -686,13 +673,13 @@ bool CNode::ReceiveMsgBytes(const char *pch, unsigned int nBytes, bool& complete return true; } -int V1TransportDeserializer::readHeader(const char *pch, unsigned int nBytes) +int V1TransportDeserializer::readHeader(Span<const uint8_t> msg_bytes) { // copy data to temporary parsing buffer unsigned int nRemaining = CMessageHeader::HEADER_SIZE - nHdrPos; - unsigned int nCopy = std::min(nRemaining, nBytes); + unsigned int nCopy = std::min<unsigned int>(nRemaining, msg_bytes.size()); - memcpy(&hdrbuf[nHdrPos], pch, nCopy); + memcpy(&hdrbuf[nHdrPos], msg_bytes.data(), nCopy); nHdrPos += nCopy; // if header incomplete, exit @@ -726,18 +713,18 @@ int V1TransportDeserializer::readHeader(const char *pch, unsigned int nBytes) return nCopy; } -int V1TransportDeserializer::readData(const char *pch, unsigned int nBytes) +int V1TransportDeserializer::readData(Span<const uint8_t> msg_bytes) { unsigned int nRemaining = hdr.nMessageSize - nDataPos; - unsigned int nCopy = std::min(nRemaining, nBytes); + unsigned int nCopy = std::min<unsigned int>(nRemaining, msg_bytes.size()); if (vRecv.size() < nDataPos + nCopy) { // Allocate up to 256 KiB ahead, but never more than the total message size. vRecv.resize(std::min(hdr.nMessageSize, nDataPos + nCopy + 256 * 1024)); } - hasher.Write({(const unsigned char*)pch, nCopy}); - memcpy(&vRecv[nDataPos], pch, nCopy); + hasher.Write(msg_bytes.first(nCopy)); + memcpy(&vRecv[nDataPos], msg_bytes.data(), nCopy); nDataPos += nCopy; return nCopy; @@ -1476,18 +1463,18 @@ void CConnman::SocketHandler() if (recvSet || errorSet) { // typical socket buffer is 8K-64K - char pchBuf[0x10000]; + uint8_t pchBuf[0x10000]; int nBytes = 0; { LOCK(pnode->cs_hSocket); if (pnode->hSocket == INVALID_SOCKET) continue; - nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT); + nBytes = recv(pnode->hSocket, (char*)pchBuf, sizeof(pchBuf), MSG_DONTWAIT); } if (nBytes > 0) { bool notify = false; - if (!pnode->ReceiveMsgBytes(pchBuf, nBytes, notify)) + if (!pnode->ReceiveMsgBytes(Span<const uint8_t>(pchBuf, nBytes), notify)) pnode->CloseSocketDisconnect(); RecordBytesRecv(nBytes); if (notify) { @@ -757,8 +757,8 @@ public: virtual bool Complete() const = 0; // set the serialization context version virtual void SetVersion(int version) = 0; - // read and deserialize data - virtual int Read(const char *data, unsigned int bytes) = 0; + /** read and deserialize data, advances msg_bytes data pointer */ + virtual int Read(Span<const uint8_t>& msg_bytes) = 0; // decomposes a message from the context virtual Optional<CNetMessage> GetMessage(std::chrono::microseconds time, uint32_t& out_err) = 0; virtual ~TransportDeserializer() {} @@ -779,8 +779,8 @@ private: unsigned int nDataPos; const uint256& GetMessageHash() const; - int readHeader(const char *pch, unsigned int nBytes); - int readData(const char *pch, unsigned int nBytes); + int readHeader(Span<const uint8_t> msg_bytes); + int readData(Span<const uint8_t> msg_bytes); void Reset() { vRecv.clear(); @@ -814,9 +814,14 @@ public: hdrbuf.SetVersion(nVersionIn); vRecv.SetVersion(nVersionIn); } - int Read(const char *pch, unsigned int nBytes) override { - int ret = in_data ? readData(pch, nBytes) : readHeader(pch, nBytes); - if (ret < 0) Reset(); + int Read(Span<const uint8_t>& msg_bytes) override + { + int ret = in_data ? readData(msg_bytes) : readHeader(msg_bytes); + if (ret < 0) { + Reset(); + } else { + msg_bytes = msg_bytes.subspan(ret); + } return ret; } Optional<CNetMessage> GetMessage(std::chrono::microseconds time, uint32_t& out_err_raw_size) override; @@ -1118,7 +1123,16 @@ public: return nRefCount; } - bool ReceiveMsgBytes(const char *pch, unsigned int nBytes, bool& complete); + /** + * Receive bytes from the buffer and deserialize them into messages. + * + * @param[in] msg_bytes The raw data + * @param[out] complete Set True if at least one message has been + * deserialized and is ready to be processed + * @return True if the peer should stay connected, + * False if the peer should be disconnected from. + */ + bool ReceiveMsgBytes(Span<const uint8_t> msg_bytes, bool& complete); void SetCommonVersion(int greatest_common_version) { diff --git a/src/net_processing.cpp b/src/net_processing.cpp index c649cf7757..e9915a3091 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -290,8 +290,6 @@ namespace { struct CNodeState { //! The peer's address const CService address; - //! Whether we have a fully established connection. - bool fCurrentlyConnected; //! The best known block we know this peer has announced. const CBlockIndex *pindexBestKnownBlock; //! The hash of the last unknown block this peer has announced. @@ -390,7 +388,6 @@ struct CNodeState { CNodeState(CAddress addrIn, bool is_inbound, bool is_manual) : address(addrIn), m_is_inbound(is_inbound), m_is_manual_connection(is_manual) { - fCurrentlyConnected = false; pindexBestKnownBlock = nullptr; hashLastUnknownBlock.SetNull(); pindexLastCommonBlock = nullptr; @@ -857,8 +854,9 @@ void PeerManager::FinalizeNode(const CNode& node, bool& fUpdateConnectionTime) { if (state->fSyncStarted) nSyncStarted--; - if (misbehavior == 0 && state->fCurrentlyConnected && !node.IsBlockOnlyConn()) { - // Note: we avoid changing visible addrman state for block-relay-only peers + if (node.fSuccessfullyConnected && misbehavior == 0 && + !node.IsBlockOnlyConn() && !node.IsInboundConn()) { + // Only change visible addrman state for outbound, full-relay peers fUpdateConnectionTime = true; } @@ -2488,9 +2486,6 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat if (pfrom.fSuccessfullyConnected) return; if (!pfrom.IsInboundConn()) { - // Mark this node as currently connected, so we update its timestamp later. - LOCK(cs_main); - State(pfrom.GetId())->fCurrentlyConnected = true; LogPrintf("New outbound peer connected: version: %d, blocks=%d, peer=%d%s (%s)\n", pfrom.nVersion.load(), pfrom.nStartingHeight, pfrom.GetId(), (fLogIPs ? strprintf(", peeraddr=%s", pfrom.addr.ToString()) : ""), diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index 63b4107f7e..4e1b239bc7 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -263,7 +263,7 @@ void BitcoinApplication::createWindow(const NetworkStyle *networkStyle) void BitcoinApplication::createSplashScreen(const NetworkStyle *networkStyle) { assert(!m_splash); - m_splash = new SplashScreen(nullptr, networkStyle); + m_splash = new SplashScreen(networkStyle); // We don't hold a direct pointer to the splash screen after creation, but the splash // screen will take care of deleting itself when finish() happens. m_splash->show(); diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 23370e6ad3..20120285d8 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -1311,7 +1311,7 @@ void BitcoinGUI::updateProxyIcon() bool proxy_enabled = clientModel->getProxyInfo(ip_port); if (proxy_enabled) { - if (labelProxyIcon->pixmap() == nullptr) { + if (!GUIUtil::HasPixmap(labelProxyIcon)) { QString ip_port_q = QString::fromStdString(ip_port); labelProxyIcon->setPixmap(platformStyle->SingleColorIcon(":/icons/proxy").pixmap(STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE)); labelProxyIcon->setToolTip(tr("Proxy is <b>enabled</b>: %1").arg(ip_port_q)); diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index 912297a74e..17458c5777 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -49,6 +49,7 @@ struct BlockAndHeaderTipInfo; QT_BEGIN_NAMESPACE class QAction; class QComboBox; +class QDateTime; class QMenu; class QProgressBar; class QProgressDialog; diff --git a/src/qt/forms/optionsdialog.ui b/src/qt/forms/optionsdialog.ui index 0016fb9739..045c2d3539 100644 --- a/src/qt/forms/optionsdialog.ui +++ b/src/qt/forms/optionsdialog.ui @@ -55,7 +55,7 @@ <item> <widget class="QCheckBox" name="prune"> <property name="toolTip"> - <string>Disables some advanced features but all blocks will still be fully validated. Reverting this setting requires re-downloading the entire blockchain. Actual disk usage may be somewhat higher.</string> + <string>Enabling pruning significantly reduces the disk space required to store transactions. All blocks are still fully validated. Reverting this setting requires re-downloading the entire blockchain.</string> </property> <property name="text"> <string>Prune &block storage to</string> diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index bab17562a6..70e76f765b 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -920,4 +920,35 @@ void PopupMenu(QMenu* menu, const QPoint& point, QAction* at_action) menu->popup(point, at_action); } +QDateTime StartOfDay(const QDate& date) +{ +#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)) + return date.startOfDay(); +#else + return QDateTime(date); +#endif +} + +bool HasPixmap(const QLabel* label) +{ +#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)) + return !label->pixmap(Qt::ReturnByValue).isNull(); +#else + return label->pixmap() != nullptr; +#endif +} + +QImage GetImage(const QLabel* label) +{ + if (!HasPixmap(label)) { + return QImage(); + } + +#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)) + return label->pixmap(Qt::ReturnByValue).toImage(); +#else + return label->pixmap()->toImage(); +#endif +} + } // namespace GUIUtil diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h index 2bd94b5eb3..c976b4b4bb 100644 --- a/src/qt/guiutil.h +++ b/src/qt/guiutil.h @@ -289,7 +289,7 @@ namespace GUIUtil /** * Returns the distance in pixels appropriate for drawing a subsequent character after text. * - * In Qt 5.12 and before the QFontMetrics::width() is used and it is deprecated since Qt 13.0. + * In Qt 5.12 and before the QFontMetrics::width() is used and it is deprecated since Qt 5.13. * In Qt 5.11 the QFontMetrics::horizontalAdvance() was introduced. */ int TextWidth(const QFontMetrics& fm, const QString& text); @@ -303,6 +303,44 @@ namespace GUIUtil * Call QMenu::popup() only on supported QT_QPA_PLATFORM. */ void PopupMenu(QMenu* menu, const QPoint& point, QAction* at_action = nullptr); + + /** + * Returns the start-moment of the day in local time. + * + * QDateTime::QDateTime(const QDate& date) is deprecated since Qt 5.15. + * QDate::startOfDay() was introduced in Qt 5.14. + */ + QDateTime StartOfDay(const QDate& date); + + /** + * Returns true if pixmap has been set. + * + * QPixmap* QLabel::pixmap() is deprecated since Qt 5.15. + */ + bool HasPixmap(const QLabel* label); + QImage GetImage(const QLabel* label); + + /** + * Splits the string into substrings wherever separator occurs, and returns + * the list of those strings. Empty strings do not appear in the result. + * + * QString::split() signature differs in different Qt versions: + * - QString::SplitBehavior is deprecated since Qt 5.15 + * - Qt::SplitBehavior was introduced in Qt 5.14 + * If {QString|Qt}::SkipEmptyParts behavior is required, use this + * function instead of QString::split(). + */ + template <typename SeparatorType> + QStringList SplitSkipEmptyParts(const QString& string, const SeparatorType& separator) + { + #if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)) + return string.split(separator, Qt::SkipEmptyParts); + #else + return string.split(separator, QString::SkipEmptyParts); + #endif + } + + } // namespace GUIUtil #endif // BITCOIN_QT_GUIUTIL_H diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index 7e089b4f95..1603b12a73 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -219,7 +219,7 @@ static ProxySetting GetProxySetting(QSettings &settings, const QString &name) return default_val; } // contains IP at index 0 and port at index 1 - QStringList ip_port = settings.value(name).toString().split(":", QString::SkipEmptyParts); + QStringList ip_port = GUIUtil::SplitSkipEmptyParts(settings.value(name).toString(), ":"); if (ip_port.size() == 2) { return {true, ip_port.at(0), ip_port.at(1)}; } else { // Invalid: return default diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp index b536567c8b..1297eb8b75 100644 --- a/src/qt/overviewpage.cpp +++ b/src/qt/overviewpage.cpp @@ -17,6 +17,7 @@ #include <QAbstractItemDelegate> #include <QApplication> +#include <QDateTime> #include <QPainter> #include <QStatusTipEvent> diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp index 6c2db52f63..86d681aa6f 100644 --- a/src/qt/paymentserver.cpp +++ b/src/qt/paymentserver.cpp @@ -26,7 +26,6 @@ #include <QApplication> #include <QByteArray> #include <QDataStream> -#include <QDateTime> #include <QDebug> #include <QFile> #include <QFileOpenEvent> diff --git a/src/qt/qrimagewidget.cpp b/src/qt/qrimagewidget.cpp index 52f1e60957..141f4abb3b 100644 --- a/src/qt/qrimagewidget.cpp +++ b/src/qt/qrimagewidget.cpp @@ -98,15 +98,12 @@ bool QRImageWidget::setQR(const QString& data, const QString& text) QImage QRImageWidget::exportImage() { - if(!pixmap()) - return QImage(); - return pixmap()->toImage(); + return GUIUtil::GetImage(this); } void QRImageWidget::mousePressEvent(QMouseEvent *event) { - if(event->button() == Qt::LeftButton && pixmap()) - { + if (event->button() == Qt::LeftButton && GUIUtil::HasPixmap(this)) { event->accept(); QMimeData *mimeData = new QMimeData; mimeData->setImageData(exportImage()); @@ -121,7 +118,7 @@ void QRImageWidget::mousePressEvent(QMouseEvent *event) void QRImageWidget::saveImage() { - if(!pixmap()) + if (!GUIUtil::HasPixmap(this)) return; QString fn = GUIUtil::getSaveFileName(this, tr("Save QR Code"), QString(), tr("PNG Image (*.png)"), nullptr); if (!fn.isEmpty()) @@ -132,14 +129,14 @@ void QRImageWidget::saveImage() void QRImageWidget::copyImage() { - if(!pixmap()) + if (!GUIUtil::HasPixmap(this)) return; QApplication::clipboard()->setImage(exportImage()); } void QRImageWidget::contextMenuEvent(QContextMenuEvent *event) { - if(!pixmap()) + if (!GUIUtil::HasPixmap(this)) return; contextMenu->exec(event->globalPos()); } diff --git a/src/qt/res/bitcoin-qt-res.rc b/src/qt/res/bitcoin-qt-res.rc index 94ae256477..e590b407b0 100644 --- a/src/qt/res/bitcoin-qt-res.rc +++ b/src/qt/res/bitcoin-qt-res.rc @@ -4,8 +4,8 @@ IDI_ICON2 ICON DISCARDABLE "icons/bitcoin_testnet.ico" #include <windows.h> // needed for VERSIONINFO #include "../../clientversion.h" // holds the needed client version information -#define VER_PRODUCTVERSION CLIENT_VERSION_MAJOR,CLIENT_VERSION_MINOR,CLIENT_VERSION_REVISION,CLIENT_VERSION_BUILD -#define VER_PRODUCTVERSION_STR STRINGIZE(CLIENT_VERSION_MAJOR) "." STRINGIZE(CLIENT_VERSION_MINOR) "." STRINGIZE(CLIENT_VERSION_REVISION) "." STRINGIZE(CLIENT_VERSION_BUILD) +#define VER_PRODUCTVERSION CLIENT_VERSION_MAJOR,CLIENT_VERSION_MINOR,CLIENT_VERSION_BUILD +#define VER_PRODUCTVERSION_STR STRINGIZE(CLIENT_VERSION_MAJOR) "." STRINGIZE(CLIENT_VERSION_MINOR) "." STRINGIZE(CLIENT_VERSION_BUILD) #define VER_FILEVERSION VER_PRODUCTVERSION #define VER_FILEVERSION_STR VER_PRODUCTVERSION_STR diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 88dfbd69ff..236c6e13d5 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -32,6 +32,7 @@ #include <wallet/wallet.h> #endif +#include <QDateTime> #include <QFont> #include <QKeyEvent> #include <QMenu> @@ -489,9 +490,7 @@ RPCConsole::RPCConsole(interfaces::Node& node, const PlatformStyle *_platformSty m_node.rpcSetTimerInterfaceIfUnset(rpcTimerInterface); setTrafficGraphRange(INITIAL_TRAFFIC_GRAPH_MINS); - - ui->detailWidget->hide(); - ui->peerHeading->setText(tr("Select a peer to view detailed information.")); + updateDetailWidget(); consoleFontSize = settings.value(fontSizeSettingsKey, QFont().pointSize()).toInt(); clear(); @@ -622,7 +621,7 @@ void RPCConsole::setClientModel(ClientModel *model, int bestblock_height, int64_ connect(disconnectAction, &QAction::triggered, this, &RPCConsole::disconnectSelectedNode); // peer table signal handling - update peer details when selecting new node - connect(ui->peerWidget->selectionModel(), &QItemSelectionModel::selectionChanged, this, &RPCConsole::peerSelected); + connect(ui->peerWidget->selectionModel(), &QItemSelectionModel::selectionChanged, this, &RPCConsole::updateDetailWidget); // peer table signal handling - update peer details when new nodes are added to the model connect(model->getPeerTableModel(), &PeerTableModel::layoutChanged, this, &RPCConsole::peerLayoutChanged); // peer table signal handling - cache selected node ids @@ -1017,18 +1016,6 @@ void RPCConsole::updateTrafficStats(quint64 totalBytesIn, quint64 totalBytesOut) ui->lblBytesOut->setText(GUIUtil::formatBytes(totalBytesOut)); } -void RPCConsole::peerSelected(const QItemSelection &selected, const QItemSelection &deselected) -{ - Q_UNUSED(deselected); - - if (!clientModel || !clientModel->getPeerTableModel() || selected.indexes().isEmpty()) - return; - - const CNodeCombinedStats *stats = clientModel->getPeerTableModel()->getNodeStats(selected.indexes().first().row()); - if (stats) - updateNodeDetail(stats); -} - void RPCConsole::peerLayoutAboutToChange() { QModelIndexList selected = ui->peerWidget->selectionModel()->selectedIndexes(); @@ -1045,7 +1032,6 @@ void RPCConsole::peerLayoutChanged() if (!clientModel || !clientModel->getPeerTableModel()) return; - const CNodeCombinedStats *stats = nullptr; bool fUnselect = false; bool fReselect = false; @@ -1076,9 +1062,6 @@ void RPCConsole::peerLayoutChanged() fUnselect = true; fReselect = true; } - - // get fresh stats on the detail node. - stats = clientModel->getPeerTableModel()->getNodeStats(detailNodeRow); } if (fUnselect && selectedRow >= 0) { @@ -1093,12 +1076,20 @@ void RPCConsole::peerLayoutChanged() } } - if (stats) - updateNodeDetail(stats); + updateDetailWidget(); } -void RPCConsole::updateNodeDetail(const CNodeCombinedStats *stats) +void RPCConsole::updateDetailWidget() { + QModelIndexList selected_rows; + auto selection_model = ui->peerWidget->selectionModel(); + if (selection_model) selected_rows = selection_model->selectedRows(); + if (!clientModel || !clientModel->getPeerTableModel() || selected_rows.size() != 1) { + ui->detailWidget->hide(); + ui->peerHeading->setText(tr("Select a peer to view detailed information.")); + return; + } + const CNodeCombinedStats *stats = clientModel->getPeerTableModel()->getNodeStats(selected_rows.first().row()); // update the detail ui with latest node information QString peerAddrDetails(QString::fromStdString(stats->nodeStats.addrName) + " "); peerAddrDetails += tr("(node id: %1)").arg(QString::number(stats->nodeStats.nodeid)); @@ -1256,8 +1247,7 @@ void RPCConsole::clearSelectedNode() { ui->peerWidget->selectionModel()->clearSelection(); cachedNodeids.clear(); - ui->detailWidget->hide(); - ui->peerHeading->setText(tr("Select a peer to view detailed information.")); + updateDetailWidget(); } void RPCConsole::showOrHideBanTableIfRequired() diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h index 280c5bd71a..8fea08ab5c 100644 --- a/src/qt/rpcconsole.h +++ b/src/qt/rpcconsole.h @@ -28,6 +28,7 @@ namespace Ui { } QT_BEGIN_NAMESPACE +class QDateTime; class QMenu; class QItemSelection; QT_END_NAMESPACE @@ -94,6 +95,8 @@ private Q_SLOTS: void showOrHideBanTableIfRequired(); /** clear the selected node */ void clearSelectedNode(); + /** show detailed information on ui about selected node */ + void updateDetailWidget(); public Q_SLOTS: void clear(bool clearHistory = true); @@ -115,8 +118,6 @@ public Q_SLOTS: void browseHistory(int offset); /** Scroll console view to end */ void scrollToEnd(); - /** Handle selection of peer in peers list */ - void peerSelected(const QItemSelection &selected, const QItemSelection &deselected); /** Handle selection caching before update */ void peerLayoutAboutToChange(); /** Handle updated peer information */ @@ -137,8 +138,6 @@ Q_SIGNALS: private: void startExecutor(); void setTrafficGraphRange(int mins); - /** show detailed information on ui about selected node */ - void updateNodeDetail(const CNodeCombinedStats *stats); enum ColumnWidths { diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index 50a1ea6936..8a62c64d79 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -173,8 +173,15 @@ void SendCoinsDialog::setModel(WalletModel *_model) } connect(ui->confTargetSelector, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &SendCoinsDialog::updateSmartFeeLabel); connect(ui->confTargetSelector, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &SendCoinsDialog::coinControlUpdateLabels); + +#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)) + connect(ui->groupFee, &QButtonGroup::idClicked, this, &SendCoinsDialog::updateFeeSectionControls); + connect(ui->groupFee, &QButtonGroup::idClicked, this, &SendCoinsDialog::coinControlUpdateLabels); +#else connect(ui->groupFee, static_cast<void (QButtonGroup::*)(int)>(&QButtonGroup::buttonClicked), this, &SendCoinsDialog::updateFeeSectionControls); connect(ui->groupFee, static_cast<void (QButtonGroup::*)(int)>(&QButtonGroup::buttonClicked), this, &SendCoinsDialog::coinControlUpdateLabels); +#endif + connect(ui->customFee, &BitcoinAmountField::valueChanged, this, &SendCoinsDialog::coinControlUpdateLabels); connect(ui->optInRBF, &QCheckBox::stateChanged, this, &SendCoinsDialog::updateSmartFeeLabel); connect(ui->optInRBF, &QCheckBox::stateChanged, this, &SendCoinsDialog::coinControlUpdateLabels); diff --git a/src/qt/splashscreen.cpp b/src/qt/splashscreen.cpp index f00f086d1e..5796a6ef56 100644 --- a/src/qt/splashscreen.cpp +++ b/src/qt/splashscreen.cpp @@ -25,8 +25,8 @@ #include <QScreen> -SplashScreen::SplashScreen(Qt::WindowFlags f, const NetworkStyle *networkStyle) : - QWidget(nullptr, f), curAlignment(0) +SplashScreen::SplashScreen(const NetworkStyle* networkStyle) + : QWidget(), curAlignment(0) { // set reference point, paddings int paddingRight = 50; diff --git a/src/qt/splashscreen.h b/src/qt/splashscreen.h index a0cd677d3d..d49fd87055 100644 --- a/src/qt/splashscreen.h +++ b/src/qt/splashscreen.h @@ -28,7 +28,7 @@ class SplashScreen : public QWidget Q_OBJECT public: - explicit SplashScreen(Qt::WindowFlags f, const NetworkStyle *networkStyle); + explicit SplashScreen(const NetworkStyle *networkStyle); ~SplashScreen(); void setNode(interfaces::Node& node); diff --git a/src/qt/test/rpcnestedtests.cpp b/src/qt/test/rpcnestedtests.cpp index de1fbcb94c..ea7b5f0c9e 100644 --- a/src/qt/test/rpcnestedtests.cpp +++ b/src/qt/test/rpcnestedtests.cpp @@ -14,17 +14,26 @@ #include <QDir> #include <QtGlobal> -static UniValue rpcNestedTest_rpc(const JSONRPCRequest& request) +static RPCHelpMan rpcNestedTest_rpc() { - if (request.fHelp) { - return "help message"; - } - return request.params.write(0, 0); + return RPCHelpMan{ + "rpcNestedTest", + "echo the passed string(s)", + { + {"arg1", RPCArg::Type::STR, RPCArg::Optional::OMITTED, ""}, + {"arg2", RPCArg::Type::STR, RPCArg::Optional::OMITTED, ""}, + {"arg3", RPCArg::Type::STR, RPCArg::Optional::OMITTED, ""}, + }, + {}, + RPCExamples{""}, + [](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue { + return request.params.write(0, 0); + }, + }; } -static const CRPCCommand vRPCCommands[] = -{ - { "test", "rpcNestedTest", &rpcNestedTest_rpc, {} }, +static const CRPCCommand vRPCCommands[] = { + {"test", "rpcNestedTest", &rpcNestedTest_rpc, {"arg1", "arg2", "arg3"}}, }; void RPCNestedTests::rpcNestedTests() diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp index 54ecfc38ec..e14e22e9de 100644 --- a/src/qt/transactionview.cpp +++ b/src/qt/transactionview.cpp @@ -237,7 +237,7 @@ void TransactionView::setModel(WalletModel *_model) if (_model->getOptionsModel()) { // Add third party transaction URLs to context menu - QStringList listUrls = _model->getOptionsModel()->getThirdPartyTxUrls().split("|", QString::SkipEmptyParts); + QStringList listUrls = GUIUtil::SplitSkipEmptyParts(_model->getOptionsModel()->getThirdPartyTxUrls(), "|"); for (int i = 0; i < listUrls.size(); ++i) { QString url = listUrls[i].trimmed(); @@ -275,30 +275,30 @@ void TransactionView::chooseDate(int idx) break; case Today: transactionProxyModel->setDateRange( - QDateTime(current), + GUIUtil::StartOfDay(current), TransactionFilterProxy::MAX_DATE); break; case ThisWeek: { // Find last Monday QDate startOfWeek = current.addDays(-(current.dayOfWeek()-1)); transactionProxyModel->setDateRange( - QDateTime(startOfWeek), + GUIUtil::StartOfDay(startOfWeek), TransactionFilterProxy::MAX_DATE); } break; case ThisMonth: transactionProxyModel->setDateRange( - QDateTime(QDate(current.year(), current.month(), 1)), + GUIUtil::StartOfDay(QDate(current.year(), current.month(), 1)), TransactionFilterProxy::MAX_DATE); break; case LastMonth: transactionProxyModel->setDateRange( - QDateTime(QDate(current.year(), current.month(), 1).addMonths(-1)), - QDateTime(QDate(current.year(), current.month(), 1))); + GUIUtil::StartOfDay(QDate(current.year(), current.month(), 1).addMonths(-1)), + GUIUtil::StartOfDay(QDate(current.year(), current.month(), 1))); break; case ThisYear: transactionProxyModel->setDateRange( - QDateTime(QDate(current.year(), 1, 1)), + GUIUtil::StartOfDay(QDate(current.year(), 1, 1)), TransactionFilterProxy::MAX_DATE); break; case Range: @@ -583,8 +583,8 @@ void TransactionView::dateRangeChanged() if(!transactionProxyModel) return; transactionProxyModel->setDateRange( - QDateTime(dateFrom->date()), - QDateTime(dateTo->date()).addDays(1)); + GUIUtil::StartOfDay(dateFrom->date()), + GUIUtil::StartOfDay(dateTo->date()).addDays(1)); } void TransactionView::focusTransaction(const QModelIndex &idx) diff --git a/src/randomenv.cpp b/src/randomenv.cpp index 07122b7f6d..5e07c3db40 100644 --- a/src/randomenv.cpp +++ b/src/randomenv.cpp @@ -53,7 +53,7 @@ #include <sys/vmmeter.h> #endif #endif -#ifdef __linux__ +#if defined(HAVE_STRONG_GETAUXVAL) || defined(HAVE_WEAK_GETAUXVAL) #include <sys/auxv.h> #endif @@ -326,7 +326,7 @@ void RandAddStaticEnv(CSHA512& hasher) // Bitcoin client version hasher << CLIENT_VERSION; -#ifdef __linux__ +#if defined(HAVE_STRONG_GETAUXVAL) || defined(HAVE_WEAK_GETAUXVAL) // Information available through getauxval() # ifdef AT_HWCAP hasher << getauxval(AT_HWCAP); @@ -346,7 +346,7 @@ void RandAddStaticEnv(CSHA512& hasher) const char* exec_str = (const char*)getauxval(AT_EXECFN); if (exec_str) hasher.Write((const unsigned char*)exec_str, strlen(exec_str) + 1); # endif -#endif // __linux__ +#endif // HAVE_STRONG_GETAUXVAL || HAVE_WEAK_GETAUXVAL #ifdef HAVE_GETCPUID AddAllCPUID(hasher); diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 6522c0d73e..7d45ad9434 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -242,12 +242,7 @@ static RPCHelpMan generatetodescriptor() static RPCHelpMan generate() { return RPCHelpMan{"generate", "has been replaced by the -generate cli option. Refer to -help for more information.", {}, {}, RPCExamples{""}, [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue { - - if (request.fHelp) { - throw std::runtime_error(self.ToString()); - } else { throw JSONRPCError(RPC_METHOD_NOT_FOUND, self.ToString()); - } }}; } diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 0c982317f5..b3102a236d 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -624,8 +624,6 @@ static RPCHelpMan echo(const std::string& name) RPCExamples{""}, [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue { - if (request.fHelp) throw std::runtime_error(self.ToString()); - if (request.params[9].isStr()) { CHECK_NONFATAL(request.params[9].get_str() != "trigger_internal_bug"); } diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index f98ea63782..e72ef24d12 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -288,10 +288,10 @@ static RPCHelpMan addnode() std::string strCommand; if (!request.params[1].isNull()) strCommand = request.params[1].get_str(); - if (request.fHelp || request.params.size() != 2 || - (strCommand != "onetry" && strCommand != "add" && strCommand != "remove")) + if (strCommand != "onetry" && strCommand != "add" && strCommand != "remove") { throw std::runtime_error( self.ToString()); + } NodeContext& node = EnsureNodeContext(request.context); if(!node.connman) @@ -628,7 +628,7 @@ static RPCHelpMan setban() std::string strCommand; if (!request.params[1].isNull()) strCommand = request.params[1].get_str(); - if (request.fHelp || !help.IsValidNumArgs(request.params.size()) || (strCommand != "add" && strCommand != "remove")) { + if (strCommand != "add" && strCommand != "remove") { throw std::runtime_error(help.ToString()); } NodeContext& node = EnsureNodeContext(request.context); diff --git a/src/rpc/server.h b/src/rpc/server.h index b2358ac5b2..7d13edb8b0 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -85,7 +85,6 @@ void RPCUnsetTimerInterface(RPCTimerInterface *iface); */ void RPCRunLater(const std::string& name, std::function<void()> func, int64_t nSeconds); -typedef UniValue(*rpcfn_type)(const JSONRPCRequest& jsonRequest); typedef RPCHelpMan (*RpcMethodFnType)(); class CRPCCommand @@ -116,14 +115,6 @@ public: CHECK_NONFATAL(fn().GetArgNames() == args_in); } - //! Simplified constructor taking plain rpcfn_type function pointer. - CRPCCommand(const char* category, const char* name, rpcfn_type fn, std::initializer_list<const char*> args) - : CRPCCommand(category, name, - [fn](const JSONRPCRequest& request, UniValue& result, bool) { result = fn(request); return true; }, - {args.begin(), args.end()}, intptr_t(fn)) - { - } - std::string category; std::string name; Actor actor; diff --git a/src/test/base32_tests.cpp b/src/test/base32_tests.cpp index d519eca859..3f7c5e99ee 100644 --- a/src/test/base32_tests.cpp +++ b/src/test/base32_tests.cpp @@ -6,6 +6,9 @@ #include <util/strencodings.h> #include <boost/test/unit_test.hpp> +#include <string> + +using namespace std::literals; BOOST_FIXTURE_TEST_SUITE(base32_tests, BasicTestingSetup) @@ -26,14 +29,14 @@ BOOST_AUTO_TEST_CASE(base32_testvectors) // Decoding strings with embedded NUL characters should fail bool failure; - (void)DecodeBase32(std::string("invalid", 7), &failure); - BOOST_CHECK_EQUAL(failure, true); - (void)DecodeBase32(std::string("AWSX3VPP", 8), &failure); - BOOST_CHECK_EQUAL(failure, false); - (void)DecodeBase32(std::string("AWSX3VPP\0invalid", 16), &failure); - BOOST_CHECK_EQUAL(failure, true); - (void)DecodeBase32(std::string("AWSX3VPPinvalid", 15), &failure); - BOOST_CHECK_EQUAL(failure, true); + (void)DecodeBase32("invalid\0"s, &failure); // correct size, invalid due to \0 + BOOST_CHECK(failure); + (void)DecodeBase32("AWSX3VPP"s, &failure); // valid + BOOST_CHECK(!failure); + (void)DecodeBase32("AWSX3VPP\0invalid"s, &failure); // correct size, invalid due to \0 + BOOST_CHECK(failure); + (void)DecodeBase32("AWSX3VPPinvalid"s, &failure); // invalid size + BOOST_CHECK(failure); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/base58_tests.cpp b/src/test/base58_tests.cpp index 6a636f2574..e55d6b3b19 100644 --- a/src/test/base58_tests.cpp +++ b/src/test/base58_tests.cpp @@ -12,7 +12,9 @@ #include <univalue.h> #include <boost/test/unit_test.hpp> +#include <string> +using namespace std::literals; extern UniValue read_json(const std::string& jsondata); @@ -58,14 +60,14 @@ BOOST_AUTO_TEST_CASE(base58_DecodeBase58) BOOST_CHECK_MESSAGE(result.size() == expected.size() && std::equal(result.begin(), result.end(), expected.begin()), strTest); } - BOOST_CHECK(!DecodeBase58("invalid", result, 100)); - BOOST_CHECK(!DecodeBase58(std::string("invalid"), result, 100)); - BOOST_CHECK(!DecodeBase58(std::string("\0invalid", 8), result, 100)); + BOOST_CHECK(!DecodeBase58("invalid"s, result, 100)); + BOOST_CHECK(!DecodeBase58("invalid\0"s, result, 100)); + BOOST_CHECK(!DecodeBase58("\0invalid"s, result, 100)); - BOOST_CHECK(DecodeBase58(std::string("good", 4), result, 100)); - BOOST_CHECK(!DecodeBase58(std::string("bad0IOl", 7), result, 100)); - BOOST_CHECK(!DecodeBase58(std::string("goodbad0IOl", 11), result, 100)); - BOOST_CHECK(!DecodeBase58(std::string("good\0bad0IOl", 12), result, 100)); + BOOST_CHECK(DecodeBase58("good"s, result, 100)); + BOOST_CHECK(!DecodeBase58("bad0IOl"s, result, 100)); + BOOST_CHECK(!DecodeBase58("goodbad0IOl"s, result, 100)); + BOOST_CHECK(!DecodeBase58("good\0bad0IOl"s, result, 100)); // check that DecodeBase58 skips whitespace, but still fails with unexpected non-whitespace at the end. BOOST_CHECK(!DecodeBase58(" \t\n\v\f\r skip \r\f\v\n\t a", result, 3)); @@ -73,10 +75,10 @@ BOOST_AUTO_TEST_CASE(base58_DecodeBase58) std::vector<unsigned char> expected = ParseHex("971a55"); BOOST_CHECK_EQUAL_COLLECTIONS(result.begin(), result.end(), expected.begin(), expected.end()); - BOOST_CHECK(DecodeBase58Check(std::string("3vQB7B6MrGQZaxCuFg4oh", 21), result, 100)); - BOOST_CHECK(!DecodeBase58Check(std::string("3vQB7B6MrGQZaxCuFg4oi", 21), result, 100)); - BOOST_CHECK(!DecodeBase58Check(std::string("3vQB7B6MrGQZaxCuFg4oh0IOl", 25), result, 100)); - BOOST_CHECK(!DecodeBase58Check(std::string("3vQB7B6MrGQZaxCuFg4oh\00IOl", 26), result, 100)); + BOOST_CHECK(DecodeBase58Check("3vQB7B6MrGQZaxCuFg4oh"s, result, 100)); + BOOST_CHECK(!DecodeBase58Check("3vQB7B6MrGQZaxCuFg4oi"s, result, 100)); + BOOST_CHECK(!DecodeBase58Check("3vQB7B6MrGQZaxCuFg4oh0IOl"s, result, 100)); + BOOST_CHECK(!DecodeBase58Check("3vQB7B6MrGQZaxCuFg4oh\0" "0IOl"s, result, 100)); } BOOST_AUTO_TEST_CASE(base58_random_encode_decode) diff --git a/src/test/base64_tests.cpp b/src/test/base64_tests.cpp index 5927eab6cf..bb8d102bd0 100644 --- a/src/test/base64_tests.cpp +++ b/src/test/base64_tests.cpp @@ -6,6 +6,9 @@ #include <util/strencodings.h> #include <boost/test/unit_test.hpp> +#include <string> + +using namespace std::literals; BOOST_FIXTURE_TEST_SUITE(base64_tests, BasicTestingSetup) @@ -23,14 +26,14 @@ BOOST_AUTO_TEST_CASE(base64_testvectors) // Decoding strings with embedded NUL characters should fail bool failure; - (void)DecodeBase64(std::string("invalid", 7), &failure); - BOOST_CHECK_EQUAL(failure, true); - (void)DecodeBase64(std::string("nQB/pZw=", 8), &failure); - BOOST_CHECK_EQUAL(failure, false); - (void)DecodeBase64(std::string("nQB/pZw=\0invalid", 16), &failure); - BOOST_CHECK_EQUAL(failure, true); - (void)DecodeBase64(std::string("nQB/pZw=invalid", 15), &failure); - BOOST_CHECK_EQUAL(failure, true); + (void)DecodeBase64("invalid\0"s, &failure); + BOOST_CHECK(failure); + (void)DecodeBase64("nQB/pZw="s, &failure); + BOOST_CHECK(!failure); + (void)DecodeBase64("nQB/pZw=\0invalid"s, &failure); + BOOST_CHECK(failure); + (void)DecodeBase64("nQB/pZw=invalid\0"s, &failure); + BOOST_CHECK(failure); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/fuzz/net.cpp b/src/test/fuzz/net.cpp index c61d406291..a0c8b7aac5 100644 --- a/src/test/fuzz/net.cpp +++ b/src/test/fuzz/net.cpp @@ -128,7 +128,7 @@ void test_one_input(const std::vector<uint8_t>& buffer) case 11: { const std::vector<uint8_t> b = ConsumeRandomLengthByteVector(fuzzed_data_provider); bool complete; - node.ReceiveMsgBytes((const char*)b.data(), b.size(), complete); + node.ReceiveMsgBytes(b, complete); break; } } diff --git a/src/test/fuzz/p2p_transport_deserializer.cpp b/src/test/fuzz/p2p_transport_deserializer.cpp index 7e216e16fe..7a6236efac 100644 --- a/src/test/fuzz/p2p_transport_deserializer.cpp +++ b/src/test/fuzz/p2p_transport_deserializer.cpp @@ -21,15 +21,12 @@ void test_one_input(const std::vector<uint8_t>& buffer) { // Construct deserializer, with a dummy NodeId V1TransportDeserializer deserializer{Params(), (NodeId)0, SER_NETWORK, INIT_PROTO_VERSION}; - const char* pch = (const char*)buffer.data(); - size_t n_bytes = buffer.size(); - while (n_bytes > 0) { - const int handled = deserializer.Read(pch, n_bytes); + Span<const uint8_t> msg_bytes{buffer}; + while (msg_bytes.size() > 0) { + const int handled = deserializer.Read(msg_bytes); if (handled < 0) { break; } - pch += handled; - n_bytes -= handled; if (deserializer.Complete()) { const std::chrono::microseconds m_time{std::numeric_limits<int64_t>::max()}; uint32_t out_err_raw_size{0}; diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp index 37eca8b7ef..b23fec9b95 100644 --- a/src/test/net_tests.cpp +++ b/src/test/net_tests.cpp @@ -25,6 +25,8 @@ #include <memory> #include <string> +using namespace std::literals; + class CAddrManSerializationMock : public CAddrMan { public: @@ -106,8 +108,8 @@ BOOST_AUTO_TEST_CASE(caddrdb_read) BOOST_CHECK(Lookup("250.7.1.1", addr1, 8333, false)); BOOST_CHECK(Lookup("250.7.2.2", addr2, 9999, false)); BOOST_CHECK(Lookup("250.7.3.3", addr3, 9999, false)); - BOOST_CHECK(Lookup(std::string("250.7.3.3", 9), addr3, 9999, false)); - BOOST_CHECK(!Lookup(std::string("250.7.3.3\0example.com", 21), addr3, 9999, false)); + BOOST_CHECK(Lookup("250.7.3.3"s, addr3, 9999, false)); + BOOST_CHECK(!Lookup("250.7.3.3\0example.com"s, addr3, 9999, false)); // Add three addresses to new table. CService source; diff --git a/src/test/netbase_tests.cpp b/src/test/netbase_tests.cpp index f5d26fafef..ac4db3a5b6 100644 --- a/src/test/netbase_tests.cpp +++ b/src/test/netbase_tests.cpp @@ -16,6 +16,8 @@ #include <boost/test/unit_test.hpp> +using namespace std::literals; + BOOST_FIXTURE_TEST_SUITE(netbase_tests, BasicTestingSetup) static CNetAddr ResolveIP(const std::string& ip) @@ -431,20 +433,20 @@ BOOST_AUTO_TEST_CASE(netpermissions_test) BOOST_AUTO_TEST_CASE(netbase_dont_resolve_strings_with_embedded_nul_characters) { CNetAddr addr; - BOOST_CHECK(LookupHost(std::string("127.0.0.1", 9), addr, false)); - BOOST_CHECK(!LookupHost(std::string("127.0.0.1\0", 10), addr, false)); - BOOST_CHECK(!LookupHost(std::string("127.0.0.1\0example.com", 21), addr, false)); - BOOST_CHECK(!LookupHost(std::string("127.0.0.1\0example.com\0", 22), addr, false)); + BOOST_CHECK(LookupHost("127.0.0.1"s, addr, false)); + BOOST_CHECK(!LookupHost("127.0.0.1\0"s, addr, false)); + BOOST_CHECK(!LookupHost("127.0.0.1\0example.com"s, addr, false)); + BOOST_CHECK(!LookupHost("127.0.0.1\0example.com\0"s, addr, false)); CSubNet ret; - BOOST_CHECK(LookupSubNet(std::string("1.2.3.0/24", 10), ret)); - BOOST_CHECK(!LookupSubNet(std::string("1.2.3.0/24\0", 11), ret)); - BOOST_CHECK(!LookupSubNet(std::string("1.2.3.0/24\0example.com", 22), ret)); - BOOST_CHECK(!LookupSubNet(std::string("1.2.3.0/24\0example.com\0", 23), ret)); + BOOST_CHECK(LookupSubNet("1.2.3.0/24"s, ret)); + BOOST_CHECK(!LookupSubNet("1.2.3.0/24\0"s, ret)); + BOOST_CHECK(!LookupSubNet("1.2.3.0/24\0example.com"s, ret)); + BOOST_CHECK(!LookupSubNet("1.2.3.0/24\0example.com\0"s, ret)); // We only do subnetting for IPv4 and IPv6 - BOOST_CHECK(!LookupSubNet(std::string("5wyqrzbvrdsumnok.onion", 22), ret)); - BOOST_CHECK(!LookupSubNet(std::string("5wyqrzbvrdsumnok.onion\0", 23), ret)); - BOOST_CHECK(!LookupSubNet(std::string("5wyqrzbvrdsumnok.onion\0example.com", 34), ret)); - BOOST_CHECK(!LookupSubNet(std::string("5wyqrzbvrdsumnok.onion\0example.com\0", 35), ret)); + BOOST_CHECK(!LookupSubNet("5wyqrzbvrdsumnok.onion"s, ret)); + BOOST_CHECK(!LookupSubNet("5wyqrzbvrdsumnok.onion\0"s, ret)); + BOOST_CHECK(!LookupSubNet("5wyqrzbvrdsumnok.onion\0example.com"s, ret)); + BOOST_CHECK(!LookupSubNet("5wyqrzbvrdsumnok.onion\0example.com\0"s, ret)); } // Since CNetAddr (un)ser is tested separately in net_tests.cpp here we only diff --git a/src/test/util/net.cpp b/src/test/util/net.cpp index 09f2f1807f..847a490e03 100644 --- a/src/test/util/net.cpp +++ b/src/test/util/net.cpp @@ -7,9 +7,9 @@ #include <chainparams.h> #include <net.h> -void ConnmanTestMsg::NodeReceiveMsgBytes(CNode& node, const char* pch, unsigned int nBytes, bool& complete) const +void ConnmanTestMsg::NodeReceiveMsgBytes(CNode& node, Span<const uint8_t> msg_bytes, bool& complete) const { - assert(node.ReceiveMsgBytes(pch, nBytes, complete)); + assert(node.ReceiveMsgBytes(msg_bytes, complete)); if (complete) { size_t nSizeAdded = 0; auto it(node.vRecvMsg.begin()); @@ -29,11 +29,11 @@ void ConnmanTestMsg::NodeReceiveMsgBytes(CNode& node, const char* pch, unsigned bool ConnmanTestMsg::ReceiveMsgFrom(CNode& node, CSerializedNetMsg& ser_msg) const { - std::vector<unsigned char> ser_msg_header; + std::vector<uint8_t> ser_msg_header; node.m_serializer->prepareForTransport(ser_msg, ser_msg_header); bool complete; - NodeReceiveMsgBytes(node, (const char*)ser_msg_header.data(), ser_msg_header.size(), complete); - NodeReceiveMsgBytes(node, (const char*)ser_msg.data.data(), ser_msg.data.size(), complete); + NodeReceiveMsgBytes(node, ser_msg_header, complete); + NodeReceiveMsgBytes(node, ser_msg.data, complete); return complete; } diff --git a/src/test/util/net.h b/src/test/util/net.h index ca8cb7fad5..1208e92762 100644 --- a/src/test/util/net.h +++ b/src/test/util/net.h @@ -25,7 +25,7 @@ struct ConnmanTestMsg : public CConnman { void ProcessMessagesOnce(CNode& node) { m_msgproc->ProcessMessages(&node, flagInterruptMsgProc); } - void NodeReceiveMsgBytes(CNode& node, const char* pch, unsigned int nBytes, bool& complete) const; + void NodeReceiveMsgBytes(CNode& node, Span<const uint8_t> msg_bytes, bool& complete) const; bool ReceiveMsgFrom(CNode& node, CSerializedNetMsg& ser_msg) const; }; diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index 010b6adf1f..8f2fc71cce 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -23,6 +23,7 @@ #include <array> #include <stdint.h> +#include <string.h> #include <thread> #include <univalue.h> #include <utility> @@ -35,6 +36,8 @@ #include <boost/test/unit_test.hpp> +using namespace std::literals; + /* defined in logging.cpp */ namespace BCLog { std::string LogEscapeMessage(const std::string& str); @@ -1257,9 +1260,9 @@ BOOST_AUTO_TEST_CASE(util_ParseMoney) BOOST_CHECK(!ParseMoney("-1", ret)); // Parsing strings with embedded NUL characters should fail - BOOST_CHECK(!ParseMoney(std::string("\0-1", 3), ret)); - BOOST_CHECK(!ParseMoney(std::string("\01", 2), ret)); - BOOST_CHECK(!ParseMoney(std::string("1\0", 2), ret)); + BOOST_CHECK(!ParseMoney("\0-1"s, ret)); + BOOST_CHECK(!ParseMoney("\0" "1"s, ret)); + BOOST_CHECK(!ParseMoney("1\0"s, ret)); } BOOST_AUTO_TEST_CASE(util_IsHex) @@ -1593,9 +1596,9 @@ BOOST_AUTO_TEST_CASE(test_FormatSubVersion) std::vector<std::string> comments2; comments2.push_back(std::string("comment1")); comments2.push_back(SanitizeString(std::string("Comment2; .,_?@-; !\"#$%&'()*+/<=>[]\\^`{|}~"), SAFE_CHARS_UA_COMMENT)); // Semicolon is discouraged but not forbidden by BIP-0014 - BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, std::vector<std::string>()),std::string("/Test:0.9.99/")); - BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, comments),std::string("/Test:0.9.99(comment1)/")); - BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, comments2),std::string("/Test:0.9.99(comment1; Comment2; .,_?@-; )/")); + BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, std::vector<std::string>()),std::string("/Test:9.99.0/")); + BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, comments),std::string("/Test:9.99.0(comment1)/")); + BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, comments2),std::string("/Test:9.99.0(comment1; Comment2; .,_?@-; )/")); } BOOST_AUTO_TEST_CASE(test_ParseFixedPoint) diff --git a/src/univalue/include/univalue.h b/src/univalue/include/univalue.h index 6080516353..048e162f7d 100644 --- a/src/univalue/include/univalue.h +++ b/src/univalue/include/univalue.h @@ -100,6 +100,10 @@ public: UniValue tmpVal(val_); return push_back(tmpVal); } + bool push_back(bool val_) { + UniValue tmpVal(val_); + return push_back(tmpVal); + } bool push_back(int val_) { UniValue tmpVal(val_); return push_back(tmpVal); @@ -129,7 +133,7 @@ public: return pushKV(key, tmpVal); } bool pushKV(const std::string& key, bool val_) { - UniValue tmpVal((bool)val_); + UniValue tmpVal(val_); return pushKV(key, tmpVal); } bool pushKV(const std::string& key, int val_) { diff --git a/src/univalue/test/object.cpp b/src/univalue/test/object.cpp index 70ccc0d08a..ccc1344836 100644 --- a/src/univalue/test/object.cpp +++ b/src/univalue/test/object.cpp @@ -210,19 +210,31 @@ BOOST_AUTO_TEST_CASE(univalue_array) BOOST_CHECK(arr.push_back((int64_t) -400LL)); BOOST_CHECK(arr.push_back((int) -401)); BOOST_CHECK(arr.push_back(-40.1)); + BOOST_CHECK(arr.push_back(true)); BOOST_CHECK_EQUAL(arr.empty(), false); - BOOST_CHECK_EQUAL(arr.size(), 9); + BOOST_CHECK_EQUAL(arr.size(), 10); BOOST_CHECK_EQUAL(arr[0].getValStr(), "1023"); + BOOST_CHECK_EQUAL(arr[0].getType(), UniValue::VNUM); BOOST_CHECK_EQUAL(arr[1].getValStr(), "zippy"); + BOOST_CHECK_EQUAL(arr[1].getType(), UniValue::VSTR); BOOST_CHECK_EQUAL(arr[2].getValStr(), "pippy"); + BOOST_CHECK_EQUAL(arr[2].getType(), UniValue::VSTR); BOOST_CHECK_EQUAL(arr[3].getValStr(), "boing"); + BOOST_CHECK_EQUAL(arr[3].getType(), UniValue::VSTR); BOOST_CHECK_EQUAL(arr[4].getValStr(), "going"); + BOOST_CHECK_EQUAL(arr[4].getType(), UniValue::VSTR); BOOST_CHECK_EQUAL(arr[5].getValStr(), "400"); + BOOST_CHECK_EQUAL(arr[5].getType(), UniValue::VNUM); BOOST_CHECK_EQUAL(arr[6].getValStr(), "-400"); + BOOST_CHECK_EQUAL(arr[6].getType(), UniValue::VNUM); BOOST_CHECK_EQUAL(arr[7].getValStr(), "-401"); + BOOST_CHECK_EQUAL(arr[7].getType(), UniValue::VNUM); BOOST_CHECK_EQUAL(arr[8].getValStr(), "-40.1"); + BOOST_CHECK_EQUAL(arr[8].getType(), UniValue::VNUM); + BOOST_CHECK_EQUAL(arr[9].getValStr(), "1"); + BOOST_CHECK_EQUAL(arr[9].getType(), UniValue::VBOOL); BOOST_CHECK_EQUAL(arr[999].getValStr(), ""); diff --git a/src/util/memory.h b/src/util/memory.h index 15ecf8f80d..4d73b32869 100644 --- a/src/util/memory.h +++ b/src/util/memory.h @@ -10,10 +10,11 @@ #include <utility> //! Substitute for C++14 std::make_unique. +//! DEPRECATED use std::make_unique in new code. template <typename T, typename... Args> std::unique_ptr<T> MakeUnique(Args&&... args) { - return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); + return std::make_unique<T>(std::forward<Args>(args)...); } #endif diff --git a/src/validation.cpp b/src/validation.cpp index 8c87c53ac7..71402ef263 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -2398,9 +2398,7 @@ static void UpdateTip(CTxMemPool& mempool, const CBlockIndex* pindexNew, const C } bilingual_str warning_messages; - int num_unexpected_version = 0; - if (!::ChainstateActive().IsInitialBlockDownload()) - { + if (!::ChainstateActive().IsInitialBlockDownload()) { const CBlockIndex* pindex = pindexNew; for (int bit = 0; bit < VERSIONBITS_NUM_BITS; bit++) { WarningBitsConditionChecker checker(bit); @@ -2414,14 +2412,6 @@ static void UpdateTip(CTxMemPool& mempool, const CBlockIndex* pindexNew, const C } } } - // Check the version of the last 100 blocks to see if we need to upgrade: - for (int i = 0; i < 100 && pindex != nullptr; i++) - { - int32_t nExpectedVersion = ComputeBlockVersion(pindex->pprev, chainParams.GetConsensus()); - if (pindex->nVersion > VERSIONBITS_LAST_OLD_BLOCK_VERSION && (pindex->nVersion & ~nExpectedVersion) != 0) - ++num_unexpected_version; - pindex = pindex->pprev; - } } LogPrintf("%s: new best=%s height=%d version=0x%08x log2_work=%f tx=%lu date='%s' progress=%f cache=%.1fMiB(%utxo)%s\n", __func__, pindexNew->GetBlockHash().ToString(), pindexNew->nHeight, pindexNew->nVersion, @@ -2429,10 +2419,6 @@ static void UpdateTip(CTxMemPool& mempool, const CBlockIndex* pindexNew, const C FormatISO8601DateTime(pindexNew->GetBlockTime()), GuessVerificationProgress(chainParams.TxData(), pindexNew), ::ChainstateActive().CoinsTip().DynamicMemoryUsage() * (1.0 / (1<<20)), ::ChainstateActive().CoinsTip().GetCacheSize(), !warning_messages.empty() ? strprintf(" warning='%s'", warning_messages.original) : ""); - - if (num_unexpected_version > 0) { - LogPrint(BCLog::VALIDATION, "%d of last 100 blocks have unexpected version\n", num_unexpected_version); - } } /** Disconnect m_chain's tip. diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index ace2975e2a..9425efa2dd 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -29,7 +29,6 @@ #include <util/translation.h> #include <util/url.h> #include <util/vector.h> -#include <validation.h> #include <wallet/coincontrol.h> #include <wallet/context.h> #include <wallet/feebumper.h> @@ -219,14 +218,8 @@ static void SetFeeEstimateMode(const CWallet* pwallet, CCoinControl& cc, const U if (!estimate_mode.isNull() && !estimate_mode.get_str().empty()) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify both estimate_mode and fee_rate"); } - CFeeRate fee_rate_in_sat_vb{CFeeRate(AmountFromValue(fee_rate), COIN)}; - if (override_min_fee) { - if (fee_rate_in_sat_vb <= CFeeRate(0)) { - throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid fee_rate %s (must be greater than 0)", fee_rate_in_sat_vb.ToString(FeeEstimateMode::SAT_VB))); - } - cc.fOverrideFeeRate = true; - } - cc.m_feerate = fee_rate_in_sat_vb; + cc.m_feerate = CFeeRate(AmountFromValue(fee_rate), COIN); + if (override_min_fee) cc.fOverrideFeeRate = true; // Default RBF to true for explicit fee_rate, if unset. if (cc.m_signal_bip125_rbf == nullopt) cc.m_signal_bip125_rbf = true; return; @@ -3156,11 +3149,7 @@ void FundTransaction(CWallet* const pwallet, CMutableTransaction& tx, CAmount& f if (options.exists("estimate_mode")) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify both estimate_mode and feeRate"); } - CFeeRate fee_rate(AmountFromValue(options["feeRate"])); - if (fee_rate <= CFeeRate(0)) { - throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid feeRate %s (must be greater than 0)", fee_rate.ToString(FeeEstimateMode::BTC_KVB))); - } - coinControl.m_feerate = fee_rate; + coinControl.m_feerate = CFeeRate(AmountFromValue(options["feeRate"])); coinControl.fOverrideFeeRate = true; } @@ -3399,7 +3388,7 @@ RPCHelpMan signrawtransactionwithwallet() static RPCHelpMan bumpfee_helper(std::string method_name) { bool want_psbt = method_name == "psbtbumpfee"; - const std::string incremental_fee{CFeeRate(DEFAULT_MIN_RELAY_TX_FEE).ToString(FeeEstimateMode::SAT_VB)}; + const std::string incremental_fee{CFeeRate(DEFAULT_INCREMENTAL_RELAY_FEE).ToString(FeeEstimateMode::SAT_VB)}; return RPCHelpMan{method_name, "\nBumps the fee of an opt-in-RBF transaction T, replacing it with a new transaction B.\n" @@ -3422,7 +3411,7 @@ static RPCHelpMan bumpfee_helper(std::string method_name) {"conf_target", RPCArg::Type::NUM, /* default */ "wallet -txconfirmtarget", "Confirmation target in blocks\n"}, {"fee_rate", RPCArg::Type::AMOUNT, /* default */ "not set, fall back to wallet fee estimation", "\nSpecify a fee rate in " + CURRENCY_ATOM + "/vB instead of relying on the built-in fee estimator.\n" - "Must be at least " + incremental_fee + " " + CURRENCY_ATOM + "/vB higher than the current transaction fee rate.\n" + "Must be at least " + incremental_fee + " higher than the current transaction fee rate.\n" "WARNING: before version 0.21, fee_rate was in " + CURRENCY_UNIT + "/kvB. As of 0.21, fee_rate is in " + CURRENCY_ATOM + "/vB.\n"}, {"replaceable", RPCArg::Type::BOOL, /* default */ "true", "Whether the new transaction should still be\n" "marked bip-125 replaceable. If true, the sequence numbers in the transaction will\n" diff --git a/src/wallet/test/walletdb_tests.cpp b/src/wallet/test/walletdb_tests.cpp new file mode 100644 index 0000000000..a3859e2e4b --- /dev/null +++ b/src/wallet/test/walletdb_tests.cpp @@ -0,0 +1,29 @@ +// Copyright (c) 2012-2019 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include <test/util/setup_common.h> +#include <clientversion.h> +#include <streams.h> +#include <uint256.h> + +#include <boost/test/unit_test.hpp> + +BOOST_FIXTURE_TEST_SUITE(walletdb_tests, BasicTestingSetup) + +BOOST_AUTO_TEST_CASE(walletdb_readkeyvalue) +{ + /** + * When ReadKeyValue() reads from either a "key" or "wkey" it first reads the CDataStream steam into a + * CPrivKey or CWalletKey respectively and then reads a hash of the pubkey and privkey into a uint256. + * Wallets from 0.8 or before do not store the pubkey/privkey hash, trying to read the hash from old + * wallets throws an exception, for backwards compatibility this read is wrapped in a try block to + * silently fail. The test here makes sure the type of exception thrown from CDataStream::read() + * matches the type we expect, otherwise we need to update the "key"/"wkey" exception type caught. + */ + CDataStream ssValue(SER_DISK, CLIENT_VERSION); + uint256 dummy; + BOOST_CHECK_THROW(ssValue >> dummy, std::ios_base::failure); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 1543e8fb81..45807ae6fd 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -364,7 +364,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, { ssValue >> hash; } - catch (...) {} + catch (const std::ios_base::failure&) {} bool fSkipCheck = false; diff --git a/test/functional/feature_taproot.py b/test/functional/feature_taproot.py index 6e28cfb265..0f0fe8a34a 100755 --- a/test/functional/feature_taproot.py +++ b/test/functional/feature_taproot.py @@ -1442,17 +1442,23 @@ class TaprootTest(BitcoinTestFramework): self.nodes[1].generate(101) self.test_spenders(self.nodes[1], spenders_taproot_active(), input_counts=[1, 2, 2, 2, 2, 3]) - # Transfer funds to pre-taproot node. + # Transfer value of the largest 500 coins to pre-taproot node. addr = self.nodes[0].getnewaddress() + + unsp = self.nodes[1].listunspent() + unsp = sorted(unsp, key=lambda i: i['amount'], reverse=True) + unsp = unsp[:500] + rawtx = self.nodes[1].createrawtransaction( inputs=[{ 'txid': i['txid'], 'vout': i['vout'] - } for i in self.nodes[1].listunspent()], - outputs={addr: self.nodes[1].getbalance()}, + } for i in unsp], + outputs={addr: sum(i['amount'] for i in unsp)} ) rawtx = self.nodes[1].signrawtransactionwithwallet(rawtx)['hex'] - # Transaction is too large to fit into the mempool, so put it into a block + + # Mine a block with the transaction block = create_block(tmpl=self.nodes[1].getblocktemplate(NORMAL_GBT_REQUEST_PARAMS), txlist=[rawtx]) add_witness_commitment(block) block.rehash() diff --git a/test/functional/mempool_spend_coinbase.py b/test/functional/mempool_spend_coinbase.py index 854d506f0d..86d382ff69 100755 --- a/test/functional/mempool_spend_coinbase.py +++ b/test/functional/mempool_spend_coinbase.py @@ -13,44 +13,48 @@ but less mature coinbase spends are NOT. """ from test_framework.test_framework import BitcoinTestFramework -from test_framework.blocktools import create_raw_transaction from test_framework.util import assert_equal, assert_raises_rpc_error +from test_framework.wallet import MiniWallet class MempoolSpendCoinbaseTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 1 - - def skip_test_if_missing_module(self): - self.skip_if_no_wallet() + self.setup_clean_chain = True def run_test(self): + wallet = MiniWallet(self.nodes[0]) + + wallet.generate(200) chain_height = self.nodes[0].getblockcount() assert_equal(chain_height, 200) - node0_address = self.nodes[0].getnewaddress() # Coinbase at height chain_height-100+1 ok in mempool, should # get mined. Coinbase at height chain_height-100+2 is - # is too immature to spend. + # too immature to spend. b = [self.nodes[0].getblockhash(n) for n in range(101, 103)] coinbase_txids = [self.nodes[0].getblock(h)['tx'][0] for h in b] - spends_raw = [create_raw_transaction(self.nodes[0], txid, node0_address, amount=49.99) for txid in coinbase_txids] + utxo_101 = wallet.get_utxo(txid=coinbase_txids[0]) + utxo_102 = wallet.get_utxo(txid=coinbase_txids[1]) - spend_101_id = self.nodes[0].sendrawtransaction(spends_raw[0]) + spend_101_id = wallet.send_self_transfer(from_node=self.nodes[0], utxo_to_spend=utxo_101)["txid"] # coinbase at height 102 should be too immature to spend - assert_raises_rpc_error(-26,"bad-txns-premature-spend-of-coinbase", self.nodes[0].sendrawtransaction, spends_raw[1]) + assert_raises_rpc_error(-26, + "bad-txns-premature-spend-of-coinbase", + lambda: wallet.send_self_transfer(from_node=self.nodes[0], utxo_to_spend=utxo_102)) # mempool should have just spend_101: - assert_equal(self.nodes[0].getrawmempool(), [ spend_101_id ]) + assert_equal(self.nodes[0].getrawmempool(), [spend_101_id]) # mine a block, spend_101 should get confirmed self.nodes[0].generate(1) assert_equal(set(self.nodes[0].getrawmempool()), set()) # ... and now height 102 can be spent: - spend_102_id = self.nodes[0].sendrawtransaction(spends_raw[1]) - assert_equal(self.nodes[0].getrawmempool(), [ spend_102_id ]) + spend_102_id = wallet.send_self_transfer(from_node=self.nodes[0], utxo_to_spend=utxo_102)["txid"] + assert_equal(self.nodes[0].getrawmempool(), [spend_102_id]) + if __name__ == '__main__': MempoolSpendCoinbaseTest().main() diff --git a/test/functional/p2p_fingerprint.py b/test/functional/p2p_fingerprint.py index aaf862e6c8..f60eba2dbf 100755 --- a/test/functional/p2p_fingerprint.py +++ b/test/functional/p2p_fingerprint.py @@ -18,6 +18,7 @@ from test_framework.p2p import ( msg_block, msg_getdata, msg_getheaders, + p2p_lock, ) from test_framework.test_framework import BitcoinTestFramework from test_framework.util import ( @@ -57,18 +58,6 @@ class P2PFingerprintTest(BitcoinTestFramework): msg.hashstop = block_hash node.send_message(msg) - # Check whether last block received from node has a given hash - def last_block_equals(self, expected_hash, node): - block_msg = node.last_message.get("block") - return block_msg and block_msg.block.rehash() == expected_hash - - # Check whether last block header received from node has a given hash - def last_header_equals(self, expected_hash, node): - headers_msg = node.last_message.get("headers") - return (headers_msg and - headers_msg.headers and - headers_msg.headers[0].rehash() == expected_hash) - # Checks that stale blocks timestamped more than a month ago are not served # by the node while recent stale blocks and old active chain blocks are. # This does not currently test that stale blocks timestamped within the @@ -101,34 +90,31 @@ class P2PFingerprintTest(BitcoinTestFramework): # Check that getdata request for stale block succeeds self.send_block_request(stale_hash, node0) - test_function = lambda: self.last_block_equals(stale_hash, node0) - self.wait_until(test_function, timeout=3) + node0.wait_for_block(stale_hash, timeout=3) # Check that getheader request for stale block header succeeds self.send_header_request(stale_hash, node0) - test_function = lambda: self.last_header_equals(stale_hash, node0) - self.wait_until(test_function, timeout=3) + node0.wait_for_header(hex(stale_hash), timeout=3) # Longest chain is extended so stale is much older than chain tip self.nodes[0].setmocktime(0) - tip = self.nodes[0].generatetoaddress(1, self.nodes[0].get_deterministic_priv_key().address)[0] + self.nodes[0].generatetoaddress(1, self.nodes[0].get_deterministic_priv_key().address) assert_equal(self.nodes[0].getblockcount(), 14) - - # Send getdata & getheaders to refresh last received getheader message - block_hash = int(tip, 16) - self.send_block_request(block_hash, node0) - self.send_header_request(block_hash, node0) node0.sync_with_ping() # Request for very old stale block should now fail + with p2p_lock: + node0.last_message.pop("block", None) self.send_block_request(stale_hash, node0) - time.sleep(3) - assert not self.last_block_equals(stale_hash, node0) + node0.sync_with_ping() + assert "block" not in node0.last_message # Request for very old stale block header should now fail + with p2p_lock: + node0.last_message.pop("headers", None) self.send_header_request(stale_hash, node0) - time.sleep(3) - assert not self.last_header_equals(stale_hash, node0) + node0.sync_with_ping() + assert "headers" not in node0.last_message # Verify we can fetch very old blocks and headers on the active chain block_hash = int(block_hashes[2], 16) @@ -137,12 +123,10 @@ class P2PFingerprintTest(BitcoinTestFramework): node0.sync_with_ping() self.send_block_request(block_hash, node0) - test_function = lambda: self.last_block_equals(block_hash, node0) - self.wait_until(test_function, timeout=3) + node0.wait_for_block(block_hash, timeout=3) self.send_header_request(block_hash, node0) - test_function = lambda: self.last_header_equals(block_hash, node0) - self.wait_until(test_function, timeout=3) + node0.wait_for_header(hex(block_hash), timeout=3) if __name__ == '__main__': P2PFingerprintTest().main() diff --git a/test/functional/rpc_fundrawtransaction.py b/test/functional/rpc_fundrawtransaction.py index f987867e61..8ee0ecab0a 100755 --- a/test/functional/rpc_fundrawtransaction.py +++ b/test/functional/rpc_fundrawtransaction.py @@ -721,11 +721,17 @@ class RawTransactionsTest(BitcoinTestFramework): result2 = node.fundrawtransaction(rawtx, {"feeRate": 2 * self.min_relay_tx_fee}) result3 = node.fundrawtransaction(rawtx, {"fee_rate": 10 * btc_kvb_to_sat_vb * self.min_relay_tx_fee}) result4 = node.fundrawtransaction(rawtx, {"feeRate": 10 * self.min_relay_tx_fee}) + # Test that funding non-standard "zero-fee" transactions is valid. + result5 = self.nodes[3].fundrawtransaction(rawtx, {"fee_rate": 0}) + result6 = self.nodes[3].fundrawtransaction(rawtx, {"feeRate": 0}) + result_fee_rate = result['fee'] * 1000 / count_bytes(result['hex']) assert_fee_amount(result1['fee'], count_bytes(result2['hex']), 2 * result_fee_rate) assert_fee_amount(result2['fee'], count_bytes(result2['hex']), 2 * result_fee_rate) assert_fee_amount(result3['fee'], count_bytes(result3['hex']), 10 * result_fee_rate) assert_fee_amount(result4['fee'], count_bytes(result3['hex']), 10 * result_fee_rate) + assert_fee_amount(result5['fee'], count_bytes(result5['hex']), 0) + assert_fee_amount(result6['fee'], count_bytes(result6['hex']), 0) # With no arguments passed, expect fee of 141 satoshis. assert_approx(node.fundrawtransaction(rawtx)["fee"], vexp=0.00000141, vspan=0.00000001) @@ -752,19 +758,15 @@ class RawTransactionsTest(BitcoinTestFramework): node.fundrawtransaction, rawtx, {"estimate_mode": mode, "conf_target": n, "add_inputs": True}) self.log.info("Test invalid fee rate settings") - assert_raises_rpc_error(-8, "Invalid fee_rate 0.000 sat/vB (must be greater than 0)", - node.fundrawtransaction, rawtx, {"fee_rate": 0, "add_inputs": True}) - assert_raises_rpc_error(-8, "Invalid feeRate 0.00000000 BTC/kvB (must be greater than 0)", - node.fundrawtransaction, rawtx, {"feeRate": 0, "add_inputs": True}) for param, value in {("fee_rate", 100000), ("feeRate", 1.000)}: assert_raises_rpc_error(-4, "Fee exceeds maximum configured by user (e.g. -maxtxfee, maxfeerate)", node.fundrawtransaction, rawtx, {param: value, "add_inputs": True}) assert_raises_rpc_error(-3, "Amount out of range", - node.fundrawtransaction, rawtx, {"fee_rate": -1, "add_inputs": True}) + node.fundrawtransaction, rawtx, {param: -1, "add_inputs": True}) assert_raises_rpc_error(-3, "Amount is not a number or string", - node.fundrawtransaction, rawtx, {"fee_rate": {"foo": "bar"}, "add_inputs": True}) + node.fundrawtransaction, rawtx, {param: {"foo": "bar"}, "add_inputs": True}) assert_raises_rpc_error(-3, "Invalid amount", - node.fundrawtransaction, rawtx, {"fee_rate": "", "add_inputs": True}) + node.fundrawtransaction, rawtx, {param: "", "add_inputs": True}) self.log.info("Test min fee rate checks are bypassed with fundrawtxn, e.g. a fee_rate under 1 sat/vB is allowed") node.fundrawtransaction(rawtx, {"fee_rate": 0.99999999, "add_inputs": True}) diff --git a/test/functional/rpc_psbt.py b/test/functional/rpc_psbt.py index 498197b5e5..5840801b00 100755 --- a/test/functional/rpc_psbt.py +++ b/test/functional/rpc_psbt.py @@ -192,26 +192,27 @@ class PSBTTest(BitcoinTestFramework): assert_approx(res1["fee"], 0.055, 0.005) res2 = self.nodes[1].walletcreatefundedpsbt(inputs, outputs, 0, {"feeRate": 0.1, "add_inputs": True}) assert_approx(res2["fee"], 0.055, 0.005) + self.log.info("Test min fee rate checks with walletcreatefundedpsbt are bypassed, e.g. a fee_rate under 1 sat/vB is allowed") res3 = self.nodes[1].walletcreatefundedpsbt(inputs, outputs, 0, {"fee_rate": 0.99999999, "add_inputs": True}) assert_approx(res3["fee"], 0.00000381, 0.0000001) res4 = self.nodes[1].walletcreatefundedpsbt(inputs, outputs, 0, {"feeRate": 0.00000999, "add_inputs": True}) assert_approx(res4["fee"], 0.00000381, 0.0000001) + self.log.info("Test min fee rate checks with walletcreatefundedpsbt are bypassed and that funding non-standard 'zero-fee' transactions is valid") + for param in ["fee_rate", "feeRate"]: + assert_equal(self.nodes[1].walletcreatefundedpsbt(inputs, outputs, 0, {param: 0, "add_inputs": True})["fee"], 0) + self.log.info("Test invalid fee rate settings") - assert_raises_rpc_error(-8, "Invalid fee_rate 0.000 sat/vB (must be greater than 0)", - self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {"fee_rate": 0, "add_inputs": True}) - assert_raises_rpc_error(-8, "Invalid feeRate 0.00000000 BTC/kvB (must be greater than 0)", - self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {"feeRate": 0, "add_inputs": True}) for param, value in {("fee_rate", 100000), ("feeRate", 1)}: assert_raises_rpc_error(-4, "Fee exceeds maximum configured by user (e.g. -maxtxfee, maxfeerate)", self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {param: value, "add_inputs": True}) assert_raises_rpc_error(-3, "Amount out of range", - self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {"fee_rate": -1, "add_inputs": True}) + self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {param: -1, "add_inputs": True}) assert_raises_rpc_error(-3, "Amount is not a number or string", - self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {"fee_rate": {"foo": "bar"}, "add_inputs": True}) + self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {param: {"foo": "bar"}, "add_inputs": True}) assert_raises_rpc_error(-3, "Invalid amount", - self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {"fee_rate": "", "add_inputs": True}) + self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {param: "", "add_inputs": True}) self.log.info("- raises RPC error if both feeRate and fee_rate are passed") assert_raises_rpc_error(-8, "Cannot specify both fee_rate (sat/vB) and feeRate (BTC/kvB)", diff --git a/test/functional/test_framework/wallet.py b/test/functional/test_framework/wallet.py index 39b3bf2a5b..a71f2c69cb 100644 --- a/test/functional/test_framework/wallet.py +++ b/test/functional/test_framework/wallet.py @@ -40,9 +40,20 @@ class MiniWallet: self._utxos.append({'txid': cb_tx['txid'], 'vout': 0, 'value': cb_tx['vout'][0]['value']}) return blocks - def get_utxo(self): - """Return the last utxo. Can be used to get the change output immediately after a send_self_transfer""" - return self._utxos.pop() + def get_utxo(self, *, txid=''): + """ + Returns a utxo and marks it as spent (pops it from the internal list) + + Args: + txid (string), optional: get the first utxo we find from a specific transaction + + Note: Can be used to get the change output immediately after a send_self_transfer + """ + index = -1 # by default the last utxo + if txid: + utxo = next(filter(lambda utxo: txid == utxo['txid'], self._utxos)) + index = self._utxos.index(utxo) + return self._utxos.pop(index) def send_self_transfer(self, *, fee_rate=Decimal("0.003"), from_node, utxo_to_spend=None): """Create and send a tx with the specified fee_rate. Fee may be exact or at most one satoshi higher than needed.""" diff --git a/test/functional/wallet_bumpfee.py b/test/functional/wallet_bumpfee.py index c323aac3cc..99c9737258 100755 --- a/test/functional/wallet_bumpfee.py +++ b/test/functional/wallet_bumpfee.py @@ -107,12 +107,10 @@ class BumpFeeTest(BitcoinTestFramework): assert_raises_rpc_error(-3, "Unexpected key {}".format(key), rbf_node.bumpfee, rbfid, {key: NORMAL}) # Bumping to just above minrelay should fail to increase the total fee enough. - assert_raises_rpc_error(-8, "Insufficient total fee 0.00000141, must be at least 0.00001704 (oldFee 0.00000999 + incrementalFee 0.00000705)", - rbf_node.bumpfee, rbfid, {"fee_rate": INSUFFICIENT}) + assert_raises_rpc_error(-8, "Insufficient total fee 0.00000141", rbf_node.bumpfee, rbfid, {"fee_rate": INSUFFICIENT}) self.log.info("Test invalid fee rate settings") - assert_raises_rpc_error(-8, "Insufficient total fee 0.00, must be at least 0.00001704 (oldFee 0.00000999 + incrementalFee 0.00000705)", - rbf_node.bumpfee, rbfid, {"fee_rate": 0}) + assert_raises_rpc_error(-8, "Insufficient total fee 0.00", rbf_node.bumpfee, rbfid, {"fee_rate": 0}) assert_raises_rpc_error(-4, "Specified or calculated fee 0.141 is too high (cannot be higher than -maxtxfee 0.10", rbf_node.bumpfee, rbfid, {"fee_rate": TOO_HIGH}) assert_raises_rpc_error(-3, "Amount out of range", rbf_node.bumpfee, rbfid, {"fee_rate": -1}) @@ -421,7 +419,7 @@ def test_watchonly_psbt(self, peer_node, rbf_node, dest_address): self.sync_all() # Create single-input PSBT for transaction to be bumped - psbt = watcher.walletcreatefundedpsbt([], {dest_address: 0.0005}, 0, {"feeRate": 0.00001}, True)['psbt'] + psbt = watcher.walletcreatefundedpsbt([], {dest_address: 0.0005}, 0, {"fee_rate": 1}, True)['psbt'] psbt_signed = signer.walletprocesspsbt(psbt=psbt, sign=True, sighashtype="ALL", bip32derivs=True) psbt_final = watcher.finalizepsbt(psbt_signed["psbt"]) original_txid = watcher.sendrawtransaction(psbt_final["hex"]) diff --git a/test/functional/wallet_send.py b/test/functional/wallet_send.py index 5da71c85f9..685e805877 100755 --- a/test/functional/wallet_send.py +++ b/test/functional/wallet_send.py @@ -303,10 +303,16 @@ class WalletSendTest(BitcoinTestFramework): self.test_send(from_wallet=w0, to_wallet=w1, amount=1, conf_target=v, estimate_mode=mode, expect_error=(-3, "Expected type number for conf_target, got {}".format(k))) - # Test setting explicit fee rate just below the minimum. + # Test setting explicit fee rate just below the minimum and at zero. self.log.info("Explicit fee rate raises RPC error 'fee rate too low' if fee_rate of 0.99999999 is passed") self.test_send(from_wallet=w0, to_wallet=w1, amount=1, fee_rate=0.99999999, expect_error=(-4, "Fee rate (0.999 sat/vB) is lower than the minimum fee rate setting (1.000 sat/vB)")) + self.test_send(from_wallet=w0, to_wallet=w1, amount=1, arg_fee_rate=0.99999999, + expect_error=(-4, "Fee rate (0.999 sat/vB) is lower than the minimum fee rate setting (1.000 sat/vB)")) + self.test_send(from_wallet=w0, to_wallet=w1, amount=1, fee_rate=0, + expect_error=(-4, "Fee rate (0.000 sat/vB) is lower than the minimum fee rate setting (1.000 sat/vB)")) + self.test_send(from_wallet=w0, to_wallet=w1, amount=1, arg_fee_rate=0, + expect_error=(-4, "Fee rate (0.000 sat/vB) is lower than the minimum fee rate setting (1.000 sat/vB)")) # TODO: Return hex if fee rate is below -maxmempool # res = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, conf_target=0.1, estimate_mode="sat/b", add_to_wallet=False) diff --git a/test/lint/extended-lint-cppcheck.sh b/test/lint/extended-lint-cppcheck.sh index 20021d8605..dfa49977de 100755 --- a/test/lint/extended-lint-cppcheck.sh +++ b/test/lint/extended-lint-cppcheck.sh @@ -66,7 +66,7 @@ function join_array { ENABLED_CHECKS_REGEXP=$(join_array "|" "${ENABLED_CHECKS[@]}") IGNORED_WARNINGS_REGEXP=$(join_array "|" "${IGNORED_WARNINGS[@]}") WARNINGS=$(git ls-files -- "*.cpp" "*.h" ":(exclude)src/leveldb/" ":(exclude)src/crc32c/" ":(exclude)src/secp256k1/" ":(exclude)src/univalue/" | \ - xargs cppcheck --enable=all -j "$(getconf _NPROCESSORS_ONLN)" --language=c++ --std=c++11 --template=gcc -D__cplusplus -DCLIENT_VERSION_BUILD -DCLIENT_VERSION_IS_RELEASE -DCLIENT_VERSION_MAJOR -DCLIENT_VERSION_MINOR -DCLIENT_VERSION_REVISION -DCOPYRIGHT_YEAR -DDEBUG -I src/ -q 2>&1 | sort -u | \ + xargs cppcheck --enable=all -j "$(getconf _NPROCESSORS_ONLN)" --language=c++ --std=c++11 --template=gcc -D__cplusplus -DCLIENT_VERSION_BUILD -DCLIENT_VERSION_IS_RELEASE -DCLIENT_VERSION_MAJOR -DCLIENT_VERSION_MINOR -DCOPYRIGHT_YEAR -DDEBUG -I src/ -q 2>&1 | sort -u | \ grep -E "${ENABLED_CHECKS_REGEXP}" | \ grep -vE "${IGNORED_WARNINGS_REGEXP}") if [[ ${WARNINGS} != "" ]]; then diff --git a/test/lint/lint-rpc-help.sh b/test/lint/lint-rpc-help.sh deleted file mode 100755 index faac5d43e2..0000000000 --- a/test/lint/lint-rpc-help.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env bash -# -# Copyright (c) 2018 The Bitcoin Core developers -# Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. -# -# Check that all RPC help texts are generated by RPCHelpMan. - -export LC_ALL=C - -EXIT_CODE=0 - -# Assume that all multiline strings passed into a runtime_error are help texts. -# This is potentially fragile, but the linter is only temporary and can safely -# be removed early 2019. - -non_autogenerated_help=$(grep --perl-regexp --null-data --only-matching 'runtime_error\(\n\s*".*\\n"\n' $(git ls-files -- "*.cpp")) -if [[ ${non_autogenerated_help} != "" ]]; then - echo "Must use RPCHelpMan to generate the help for the following RPC methods:" - echo "${non_autogenerated_help}" - echo - EXIT_CODE=1 -fi -exit ${EXIT_CODE} diff --git a/test/lint/lint-shell.sh b/test/lint/lint-shell.sh index 9a26cd9c02..351b65dea6 100755 --- a/test/lint/lint-shell.sh +++ b/test/lint/lint-shell.sh @@ -36,7 +36,8 @@ fi SHELLCHECK_CMD=(shellcheck --external-sources --check-sourced) EXCLUDE="--exclude=$(IFS=','; echo "${disabled[*]}")" -if ! "${SHELLCHECK_CMD[@]}" "$EXCLUDE" $(git ls-files -- '*.sh' | grep -vE 'src/(leveldb|secp256k1|univalue)/'); then +SOURCED_FILES=$(git ls-files | xargs gawk '/^# shellcheck shell=/ {print FILENAME} {nextfile}') # Check shellcheck directive used for sourced files +if ! "${SHELLCHECK_CMD[@]}" "$EXCLUDE" $SOURCED_FILES $(git ls-files -- '*.sh' | grep -vE 'src/(leveldb|secp256k1|univalue)/'); then EXIT_CODE=1 fi diff --git a/test/sanitizer_suppressions/ubsan b/test/sanitizer_suppressions/ubsan index e2f3fec851..291aab0a4a 100644 --- a/test/sanitizer_suppressions/ubsan +++ b/test/sanitizer_suppressions/ubsan @@ -6,6 +6,7 @@ # contains files in which we expect unsigned integer overflows to occur. The # list is used to suppress -fsanitize=integer warnings when running our CI UBSan # job. +unsigned-integer-overflow:*/include/c++/*/bits/basic_string.tcc unsigned-integer-overflow:arith_uint256.h unsigned-integer-overflow:basic_string.h unsigned-integer-overflow:bench/bench.h diff --git a/test/util/data/bitcoin-util-test.json b/test/util/data/bitcoin-util-test.json index 99cd4ab695..0a9846b4be 100644 --- a/test/util/data/bitcoin-util-test.json +++ b/test/util/data/bitcoin-util-test.json @@ -221,7 +221,7 @@ { "exec": "./bitcoin-tx", "args": ["-create", "outscript=0:123badscript"], "return_code": 1, - "error_txt": "error: script parse error", + "error_txt": "error: script parse error: unknown opcode", "description": "Create a new transaction with an invalid output script" }, { "exec": "./bitcoin-tx", |