aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml2
-rw-r--r--build_msvc/bitcoin_config.h11
-rw-r--r--ci/test/00_setup_env_i686_centos.sh9
-rw-r--r--ci/test/00_setup_env_native_nowallet.sh6
-rw-r--r--ci/test/00_setup_env_native_qt5.sh4
-rwxr-xr-xci/test/04_install.sh4
-rw-r--r--configure.ac23
-rw-r--r--contrib/gitian-descriptors/gitian-linux.yml2
-rw-r--r--contrib/gitian-descriptors/gitian-osx.yml2
-rw-r--r--contrib/gitian-descriptors/gitian-win.yml2
-rwxr-xr-xcontrib/macdeploy/custom_dsstore.py3
-rw-r--r--contrib/seeds/README.md8
-rwxr-xr-xcontrib/seeds/makeseeds.py2
-rw-r--r--contrib/signet/README.md19
-rwxr-xr-xcontrib/signet/getcoins.py36
-rw-r--r--depends/config.site.in16
-rw-r--r--depends/packages/native_biplist.mk15
-rw-r--r--depends/packages/native_ds_store.mk5
-rw-r--r--depends/packages/packages.mk2
-rw-r--r--depends/packages/qt.mk51
-rw-r--r--depends/patches/qt/fix_mingw_cross_compile.patch25
-rw-r--r--depends/patches/qt/mac-qmake.conf4
-rw-r--r--doc/dependencies.md4
-rw-r--r--doc/descriptors.md2
-rw-r--r--doc/release-process.md7
-rw-r--r--share/qt/Info.plist.in6
-rw-r--r--share/setup.nsi.in2
-rw-r--r--src/Makefile.test.include1
-rw-r--r--src/addrman.h16
-rw-r--r--src/bitcoin-cli-res.rc4
-rw-r--r--src/bitcoin-tx-res.rc4
-rw-r--r--src/bitcoin-wallet-res.rc4
-rw-r--r--src/bitcoind-res.rc4
-rw-r--r--src/bloom.h13
-rw-r--r--src/clientversion.cpp8
-rw-r--r--src/clientversion.h7
-rw-r--r--src/core_read.cpp31
-rw-r--r--src/init.cpp2
-rw-r--r--src/net.cpp41
-rw-r--r--src/net.h30
-rw-r--r--src/net_processing.cpp11
-rw-r--r--src/qt/bitcoin.cpp2
-rw-r--r--src/qt/bitcoingui.cpp2
-rw-r--r--src/qt/bitcoingui.h1
-rw-r--r--src/qt/forms/optionsdialog.ui2
-rw-r--r--src/qt/guiutil.cpp31
-rw-r--r--src/qt/guiutil.h40
-rw-r--r--src/qt/optionsmodel.cpp2
-rw-r--r--src/qt/overviewpage.cpp1
-rw-r--r--src/qt/paymentserver.cpp1
-rw-r--r--src/qt/qrimagewidget.cpp13
-rw-r--r--src/qt/res/bitcoin-qt-res.rc4
-rw-r--r--src/qt/rpcconsole.cpp40
-rw-r--r--src/qt/rpcconsole.h7
-rw-r--r--src/qt/sendcoinsdialog.cpp7
-rw-r--r--src/qt/splashscreen.cpp4
-rw-r--r--src/qt/splashscreen.h2
-rw-r--r--src/qt/test/rpcnestedtests.cpp25
-rw-r--r--src/qt/transactionview.cpp18
-rw-r--r--src/randomenv.cpp6
-rw-r--r--src/rpc/mining.cpp5
-rw-r--r--src/rpc/misc.cpp2
-rw-r--r--src/rpc/net.cpp6
-rw-r--r--src/rpc/server.h9
-rw-r--r--src/test/base32_tests.cpp19
-rw-r--r--src/test/base58_tests.cpp24
-rw-r--r--src/test/base64_tests.cpp19
-rw-r--r--src/test/fuzz/net.cpp2
-rw-r--r--src/test/fuzz/p2p_transport_deserializer.cpp9
-rw-r--r--src/test/net_tests.cpp6
-rw-r--r--src/test/netbase_tests.cpp26
-rw-r--r--src/test/util/net.cpp10
-rw-r--r--src/test/util/net.h2
-rw-r--r--src/test/util_tests.cpp15
-rw-r--r--src/univalue/include/univalue.h6
-rw-r--r--src/univalue/test/object.cpp14
-rw-r--r--src/util/memory.h3
-rw-r--r--src/validation.cpp16
-rw-r--r--src/wallet/rpcwallet.cpp21
-rw-r--r--src/wallet/test/walletdb_tests.cpp29
-rw-r--r--src/wallet/walletdb.cpp2
-rwxr-xr-xtest/functional/feature_taproot.py14
-rwxr-xr-xtest/functional/mempool_spend_coinbase.py28
-rwxr-xr-xtest/functional/p2p_fingerprint.py44
-rwxr-xr-xtest/functional/rpc_fundrawtransaction.py16
-rwxr-xr-xtest/functional/rpc_psbt.py15
-rw-r--r--test/functional/test_framework/wallet.py17
-rwxr-xr-xtest/functional/wallet_bumpfee.py8
-rwxr-xr-xtest/functional/wallet_send.py8
-rwxr-xr-xtest/lint/extended-lint-cppcheck.sh2
-rwxr-xr-xtest/lint/lint-rpc-help.sh24
-rwxr-xr-xtest/lint/lint-shell.sh3
-rw-r--r--test/sanitizer_suppressions/ubsan1
-rw-r--r--test/util/data/bitcoin-util-test.json2
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) {
diff --git a/src/net.h b/src/net.h
index a6dcf7f610..fe7b72c920 100644
--- a/src/net.h
+++ b/src/net.h
@@ -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 &amp;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",