aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xci/lint/06_script.sh2
-rwxr-xr-xci/test/00_setup_env_native_nowallet_libbitcoinkernel.sh2
-rwxr-xr-xci/test/00_setup_env_native_tidy.sh2
-rwxr-xr-xci/test/04_install.sh7
-rwxr-xr-xci/test/06_script_b.sh2
-rw-r--r--configure.ac83
-rw-r--r--contrib/devtools/iwyu/bitcoin.core.imp6
-rw-r--r--src/Makefile.am169
-rw-r--r--src/Makefile.bench.include3
-rw-r--r--src/Makefile.crc32c.include65
-rw-r--r--src/Makefile.leveldb.include217
-rw-r--r--src/Makefile.qt.include2
-rw-r--r--src/Makefile.qttest.include2
-rw-r--r--src/Makefile.test.include3
-rw-r--r--src/Makefile.test_fuzz.include5
-rw-r--r--src/Makefile.test_util.include5
-rw-r--r--src/base58.cpp4
-rw-r--r--src/bitcoin-chainstate.cpp4
-rw-r--r--src/bitcoin-tx.cpp2
-rw-r--r--src/compat/byteswap.h2
-rw-r--r--src/compat/cpuid.h2
-rw-r--r--src/compat/endian.h2
-rw-r--r--src/compat/glibcxx_sanity.cpp1
-rw-r--r--src/compat/stdin.cpp18
-rw-r--r--src/dummywallet.cpp1
-rw-r--r--src/httprpc.cpp7
-rw-r--r--src/i2p.cpp7
-rw-r--r--src/init.cpp33
-rw-r--r--src/init/bitcoin-gui.cpp1
-rw-r--r--src/init/bitcoin-node.cpp1
-rw-r--r--src/init/bitcoin-qt.cpp1
-rw-r--r--src/init/bitcoin-wallet.cpp2
-rw-r--r--src/init/bitcoind.cpp1
-rw-r--r--src/init/common.cpp5
-rw-r--r--src/kernel/bitcoinkernel.cpp10
-rw-r--r--src/net_processing.cpp7
-rw-r--r--src/netaddress.cpp22
-rw-r--r--src/netbase.cpp14
-rw-r--r--src/node/blockstorage.cpp14
-rw-r--r--src/node/blockstorage.h8
-rw-r--r--src/node/chainstate.cpp2
-rw-r--r--src/psbt.cpp11
-rw-r--r--src/psbt.h2
-rw-r--r--src/qt/rpcconsole.cpp21
-rw-r--r--src/qt/rpcconsole.h15
-rw-r--r--src/qt/walletframe.cpp12
-rw-r--r--src/rpc/blockchain.cpp21
-rw-r--r--src/test/base32_tests.cpp18
-rw-r--r--src/test/base64_tests.cpp18
-rw-r--r--src/test/fuzz/base_encode_decode.cpp17
-rw-r--r--src/test/fuzz/http_request.cpp2
-rw-r--r--src/test/fuzz/psbt.cpp6
-rw-r--r--src/test/fuzz/string.cpp4
-rw-r--r--src/test/util/setup_common.cpp1
-rw-r--r--src/test/util_tests.cpp20
-rw-r--r--src/test/validation_chainstate_tests.cpp2
-rw-r--r--src/test/validation_chainstatemanager_tests.cpp4
-rw-r--r--src/util/check.h1
-rw-r--r--src/util/message.cpp7
-rw-r--r--src/util/moneystr.cpp2
-rw-r--r--src/util/strencodings.cpp188
-rw-r--r--src/util/strencodings.h66
-rw-r--r--src/util/string.h29
-rw-r--r--src/util/system.cpp4
-rw-r--r--src/validation.cpp44
-rw-r--r--src/validation.h16
-rw-r--r--src/wallet/init.cpp1
-rw-r--r--src/wallet/wallet.cpp23
-rw-r--r--src/wallet/wallet.h2
-rw-r--r--test/README.md2
-rwxr-xr-xtest/functional/feature_taproot.py110
-rwxr-xr-xtest/functional/p2p_addr_relay.py66
-rwxr-xr-xtest/functional/test_runner.py2
-rwxr-xr-xtest/functional/wallet_createwallet.py2
-rwxr-xr-xtest/functional/wallet_crosschain.py60
-rw-r--r--test/lint/README.md2
-rwxr-xr-xtest/lint/lint-all.py23
-rwxr-xr-xtest/lint/lint-all.sh30
-rwxr-xr-xtest/lint/lint-assertions.py12
79 files changed, 859 insertions, 753 deletions
diff --git a/ci/lint/06_script.sh b/ci/lint/06_script.sh
index fa9bf4c646..f174b4d074 100755
--- a/ci/lint/06_script.sh
+++ b/ci/lint/06_script.sh
@@ -22,7 +22,7 @@ test/lint/git-subtree-check.sh src/univalue
test/lint/git-subtree-check.sh src/leveldb
test/lint/git-subtree-check.sh src/crc32c
test/lint/check-doc.py
-test/lint/lint-all.sh
+test/lint/lint-all.py
if [ "$CIRRUS_REPO_FULL_NAME" = "bitcoin/bitcoin" ] && [ "$CIRRUS_PR" = "" ] ; then
# Sanity check only the last few commits to get notified of missing sigs,
diff --git a/ci/test/00_setup_env_native_nowallet_libbitcoinkernel.sh b/ci/test/00_setup_env_native_nowallet_libbitcoinkernel.sh
index 763a5e8b6f..63560a5f5c 100755
--- a/ci/test/00_setup_env_native_nowallet_libbitcoinkernel.sh
+++ b/ci/test/00_setup_env_native_nowallet_libbitcoinkernel.sh
@@ -11,4 +11,4 @@ export DOCKER_NAME_TAG=ubuntu:18.04 # Use bionic to have one config run the tes
export PACKAGES="python3-zmq clang-8 llvm-8 libc++abi-8-dev libc++-8-dev" # Use clang-8 to test C++17 compatibility, see doc/dependencies.md
export DEP_OPTS="NO_WALLET=1 CC=clang-8 CXX='clang++-8 -stdlib=libc++'"
export GOAL="install"
-export BITCOIN_CONFIG="--enable-reduce-exports CC=clang-8 CXX='clang++-8 -stdlib=libc++' --enable-experimental-util-chainstate"
+export BITCOIN_CONFIG="--enable-reduce-exports CC=clang-8 CXX='clang++-8 -stdlib=libc++' --enable-experimental-util-chainstate --with-experimental-kernel-lib --enable-shared"
diff --git a/ci/test/00_setup_env_native_tidy.sh b/ci/test/00_setup_env_native_tidy.sh
index 87dd315e2e..e4d3468473 100755
--- a/ci/test/00_setup_env_native_tidy.sh
+++ b/ci/test/00_setup_env_native_tidy.sh
@@ -8,7 +8,7 @@ export LC_ALL=C.UTF-8
export DOCKER_NAME_TAG="ubuntu:22.04"
export CONTAINER_NAME=ci_native_tidy
-export PACKAGES="clang llvm clang-tidy bear libevent-dev libboost-dev libminiupnpc-dev libnatpmp-dev libzmq3-dev systemtap-sdt-dev libqt5gui5 libqt5core5a libqt5dbus5 qttools5-dev qttools5-dev-tools libqrencode-dev libsqlite3-dev libdb++-dev"
+export PACKAGES="clang libclang-dev llvm-dev clang-tidy bear cmake libevent-dev libboost-dev libminiupnpc-dev libnatpmp-dev libzmq3-dev systemtap-sdt-dev libqt5gui5 libqt5core5a libqt5dbus5 qttools5-dev qttools5-dev-tools libqrencode-dev libsqlite3-dev libdb++-dev"
export NO_DEPENDS=1
export RUN_UNIT_TESTS=false
export RUN_FUNCTIONAL_TESTS=false
diff --git a/ci/test/04_install.sh b/ci/test/04_install.sh
index c1324a0b14..227bdf3319 100755
--- a/ci/test/04_install.sh
+++ b/ci/test/04_install.sh
@@ -111,6 +111,13 @@ if [[ ${USE_MEMORY_SANITIZER} == "true" ]]; then
CI_EXEC "cd ${BASE_SCRATCH_DIR}/msan/build/ && make $MAKEJOBS cxx"
fi
+if [[ "${RUN_TIDY}" == "true" ]]; then
+ CI_EXEC "mkdir -p ${BASE_SCRATCH_DIR}/iwyu/build/"
+ CI_EXEC "git clone --depth=1 https://github.com/include-what-you-use/include-what-you-use -b clang_14 ${BASE_SCRATCH_DIR}/iwyu/include-what-you-use"
+ CI_EXEC "cd ${BASE_SCRATCH_DIR}/iwyu/build && cmake -G 'Unix Makefiles' -DCMAKE_PREFIX_PATH=/usr/lib/llvm-14 ../include-what-you-use"
+ CI_EXEC "cd ${BASE_SCRATCH_DIR}/iwyu/build && make install $MAKEJOBS"
+fi
+
if [ -z "$DANGER_RUN_CI_ON_HOST" ]; then
echo "Create $BASE_ROOT_DIR"
CI_EXEC rsync -a /ro_base/ "$BASE_ROOT_DIR"
diff --git a/ci/test/06_script_b.sh b/ci/test/06_script_b.sh
index 30788f1543..afab4c5e78 100755
--- a/ci/test/06_script_b.sh
+++ b/ci/test/06_script_b.sh
@@ -37,6 +37,8 @@ fi
if [ "${RUN_TIDY}" = "true" ]; then
export P_CI_DIR="${BASE_BUILD_DIR}/bitcoin-$HOST/src/"
CI_EXEC run-clang-tidy "${MAKEJOBS}"
+ export P_CI_DIR="${BASE_BUILD_DIR}/bitcoin-$HOST/"
+ CI_EXEC "python3 ${BASE_SCRATCH_DIR}/iwyu/include-what-you-use/iwyu_tool.py src/compat src/init -p . ${MAKEJOBS} -- -Xiwyu --cxx17ns -Xiwyu --mapping_file=${BASE_BUILD_DIR}/bitcoin-$HOST/contrib/devtools/iwyu/bitcoin.core.imp"
fi
if [ "$RUN_SECURITY_TESTS" = "true" ]; then
diff --git a/configure.ac b/configure.ac
index 554083a44c..ea97b1b1d9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -663,6 +663,12 @@ AC_ARG_WITH([libs],
[build_bitcoin_libs=$withval],
[build_bitcoin_libs=yes])
+AC_ARG_WITH([experimental-kernel-lib],
+ [AS_HELP_STRING([--with-experimental-kernel-lib],
+ [build experimental bitcoinkernel library (default is to build if we're building libraries and the experimental build-chainstate executable)])],
+ [build_experimental_kernel_lib=$withval],
+ [build_experimental_kernel_lib=auto])
+
AC_ARG_WITH([daemon],
[AS_HELP_STRING([--with-daemon],
[build bitcoind daemon (default=yes)])],
@@ -750,20 +756,20 @@ case $host in
if test "$use_upnp" != "no" && $BREW list --versions miniupnpc >/dev/null; then
miniupnpc_prefix=$($BREW --prefix miniupnpc 2>/dev/null)
if test "$suppress_external_warnings" != "no"; then
- CORE_CPPFLAGS="$CORE_CPPFLAGS -isystem $miniupnpc_prefix/include"
+ MINIUPNPC_CPPFLAGS="-isystem $miniupnpc_prefix/include"
else
- CORE_CPPFLAGS="$CORE_CPPFLAGS -I$miniupnpc_prefix/include"
+ MINIUPNPC_CPPFLAGS="-I$miniupnpc_prefix/include"
fi
- CORE_LDFLAGS="$CORE_LDFLAGS -L$miniupnpc_prefix/lib"
+ MINIUPNPC_LIBS="-L$miniupnpc_prefix/lib"
fi
if test "$use_natpmp" != "no" && $BREW list --versions libnatpmp >/dev/null; then
libnatpmp_prefix=$($BREW --prefix libnatpmp 2>/dev/null)
if test "$suppress_external_warnings" != "no"; then
- CORE_CPPFLAGS="$CORE_CPPFLAGS -isystem $libnatpmp_prefix/include"
+ NATPMP_CPPFLAGS="-isystem $libnatpmp_prefix/include"
else
- CORE_CPPFLAGS="$CORE_CPPFLAGS -I$libnatpmp_prefix/include"
+ NATPMP_CPPFLAGS="-I$libnatpmp_prefix/include"
fi
- CORE_LDFLAGS="$CORE_LDFLAGS -L$libnatpmp_prefix/lib"
+ NATPMP_LIBS="-L$libnatpmp_prefix/lib"
fi
;;
esac
@@ -1392,38 +1398,44 @@ fi
dnl Check for libminiupnpc (optional)
if test "$use_upnp" != "no"; then
+ TEMP_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $MINIUPNPC_CPPFLAGS"
AC_CHECK_HEADERS(
[miniupnpc/miniupnpc.h miniupnpc/upnpcommands.h miniupnpc/upnperrors.h],
- [AC_CHECK_LIB([miniupnpc], [upnpDiscover], [MINIUPNPC_LIBS=-lminiupnpc], [have_miniupnpc=no])],
+ [AC_CHECK_LIB([miniupnpc], [upnpDiscover], [MINIUPNPC_LIBS="$MINIUPNPC_LIBS -lminiupnpc"], [have_miniupnpc=no], [$MINIUPNPC_LIBS])],
[have_miniupnpc=no]
)
-dnl The minimum supported miniUPnPc API version is set to 10. This keeps compatibility
-dnl with Ubuntu 16.04 LTS and Debian 8 libminiupnpc-dev packages.
-if test "$have_miniupnpc" != "no"; then
- AC_MSG_CHECKING([whether miniUPnPc API version is supported])
- AC_PREPROC_IFELSE([AC_LANG_PROGRAM([[
- @%:@include <miniupnpc/miniupnpc.h>
- ]], [[
- #if MINIUPNPC_API_VERSION >= 10
- // Everything is okay
- #else
- # error miniUPnPc API version is too old
- #endif
- ]])],[
- AC_MSG_RESULT([yes])
- ],[
- AC_MSG_RESULT([no])
- AC_MSG_WARN([miniUPnPc API version < 10 is unsupported, disabling UPnP support.])
- have_miniupnpc=no
- ])
-fi
+ dnl The minimum supported miniUPnPc API version is set to 10. This keeps compatibility
+ dnl with Ubuntu 16.04 LTS and Debian 8 libminiupnpc-dev packages.
+ if test "$have_miniupnpc" != "no"; then
+ AC_MSG_CHECKING([whether miniUPnPc API version is supported])
+ AC_PREPROC_IFELSE([AC_LANG_PROGRAM([[
+ @%:@include <miniupnpc/miniupnpc.h>
+ ]], [[
+ #if MINIUPNPC_API_VERSION >= 10
+ // Everything is okay
+ #else
+ # error miniUPnPc API version is too old
+ #endif
+ ]])],[
+ AC_MSG_RESULT([yes])
+ ],[
+ AC_MSG_RESULT([no])
+ AC_MSG_WARN([miniUPnPc API version < 10 is unsupported, disabling UPnP support.])
+ have_miniupnpc=no
+ ])
+ fi
+ CPPFLAGS="$TEMP_CPPFLAGS"
fi
dnl Check for libnatpmp (optional).
if test "$use_natpmp" != "no"; then
+ TEMP_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $NATPMP_CPPFLAGS"
AC_CHECK_HEADERS([natpmp.h],
- [AC_CHECK_LIB([natpmp], [initnatpmp], [NATPMP_LIBS=-lnatpmp], [have_natpmp=no])],
+ [AC_CHECK_LIB([natpmp], [initnatpmp], [NATPMP_LIBS="$NATPMP_LIBS -lnatpmp"], [have_natpmp=no], [$NATPMP_LIBS])],
[have_natpmp=no])
+ CPPFLAGS="$TEMP_CPPFLAGS"
fi
if test "$build_bitcoin_wallet$build_bitcoin_cli$build_bitcoin_tx$build_bitcoind$bitcoin_enable_qt$use_tests$use_bench" = "nonononononono"; then
@@ -1656,15 +1668,23 @@ AM_CONDITIONAL([BUILD_BITCOIN_UTIL], [test $build_bitcoin_util = "yes"])
AC_MSG_RESULT($build_bitcoin_util)
AC_MSG_CHECKING([whether to build experimental bitcoin-chainstate])
-AM_CONDITIONAL([BUILD_BITCOIN_CHAINSTATE], [test $build_bitcoin_chainstate = "yes"])
+if test "$build_experimental_kernel_lib" = "no"; then
+AC_MSG_ERROR([experimental bitcoin-chainstate cannot be built without the experimental bitcoinkernel library. Use --with-experimental-kernel-lib]);
+else
+ AM_CONDITIONAL([BUILD_BITCOIN_CHAINSTATE], [test $build_bitcoin_chainstate = "yes"])
+fi
AC_MSG_RESULT($build_bitcoin_chainstate)
AC_MSG_CHECKING([whether to build libraries])
AM_CONDITIONAL([BUILD_BITCOIN_LIBS], [test $build_bitcoin_libs = "yes"])
+
if test "$build_bitcoin_libs" = "yes"; then
AC_DEFINE([HAVE_CONSENSUS_LIB], [1], [Define this symbol if the consensus lib has been built])
AC_CONFIG_FILES([libbitcoinconsensus.pc:libbitcoinconsensus.pc.in])
fi
+
+AM_CONDITIONAL([BUILD_BITCOIN_KERNEL_LIB], [test "$build_experimental_kernel_lib" != "no" && ( test "$build_experimental_kernel_lib" = "yes" || test "$build_bitcoin_chainstate" = "yes" )])
+
AC_MSG_RESULT($build_bitcoin_libs)
AC_LANG_POP
@@ -1721,7 +1741,7 @@ else
AC_MSG_RESULT([$use_upnp_default])
AC_DEFINE_UNQUOTED([USE_UPNP],[$upnp_setting],[UPnP support not compiled if undefined, otherwise value (0 or 1) determines default state])
if test "$TARGET_OS" = "windows"; then
- MINIUPNPC_CPPFLAGS="-DSTATICLIB -DMINIUPNP_STATICLIB"
+ MINIUPNPC_CPPFLAGS="$MINIUPNPC_CPPFLAGS -DSTATICLIB -DMINIUPNP_STATICLIB"
fi
else
AC_MSG_RESULT([no])
@@ -1749,7 +1769,7 @@ else
AC_MSG_RESULT($use_natpmp_default)
AC_DEFINE_UNQUOTED([USE_NATPMP], [$natpmp_setting], [NAT-PMP support not compiled if undefined, otherwise value (0 or 1) determines default state])
if test "$TARGET_OS" = "windows"; then
- NATPMP_CPPFLAGS="-DSTATICLIB -DNATPMP_STATICLIB"
+ NATPMP_CPPFLAGS="$NATPMP_CPPFLAGS -DSTATICLIB -DNATPMP_STATICLIB"
fi
else
AC_MSG_RESULT([no])
@@ -1933,6 +1953,7 @@ AC_CONFIG_LINKS([contrib/devtools/security-check.py:contrib/devtools/security-ch
AC_CONFIG_LINKS([contrib/devtools/symbol-check.py:contrib/devtools/symbol-check.py])
AC_CONFIG_LINKS([contrib/devtools/test-security-check.py:contrib/devtools/test-security-check.py])
AC_CONFIG_LINKS([contrib/devtools/test-symbol-check.py:contrib/devtools/test-symbol-check.py])
+AC_CONFIG_LINKS([contrib/devtools/iwyu/bitcoin.core.imp:contrib/devtools/iwyu/bitcoin.core.imp])
AC_CONFIG_LINKS([contrib/filter-lcov.py:contrib/filter-lcov.py])
AC_CONFIG_LINKS([contrib/macdeploy/background.tiff:contrib/macdeploy/background.tiff])
AC_CONFIG_LINKS([src/.bear-tidy-config:src/.bear-tidy-config])
diff --git a/contrib/devtools/iwyu/bitcoin.core.imp b/contrib/devtools/iwyu/bitcoin.core.imp
new file mode 100644
index 0000000000..ce7786f58c
--- /dev/null
+++ b/contrib/devtools/iwyu/bitcoin.core.imp
@@ -0,0 +1,6 @@
+# Fixups / upstreamed changes
+[
+ { include: [ "<bits/termios-c_lflag.h>", private, "<termios.h>", public ] },
+ { include: [ "<bits/termios-struct.h>", private, "<termios.h>", public ] },
+ { include: [ "<bits/termios-tcflow.h>", private, "<termios.h>", public ] },
+]
diff --git a/src/Makefile.am b/src/Makefile.am
index 476ff0a6c5..f77c2f919c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -15,14 +15,23 @@ AM_LIBTOOLFLAGS = --preserve-dup-deps
PTHREAD_FLAGS = $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
EXTRA_LIBRARIES =
+lib_LTLIBRARIES =
+noinst_LTLIBRARIES =
+
+bin_PROGRAMS =
+noinst_PROGRAMS =
+TESTS =
+BENCHMARKS =
+
BITCOIN_INCLUDES=-I$(builddir) -I$(srcdir)/$(MINISKETCH_INCLUDE_DIR_INT) -I$(srcdir)/secp256k1/include -I$(srcdir)/$(UNIVALUE_INCLUDE_DIR_INT) $(BDB_CPPFLAGS) $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS)
LIBBITCOIN_NODE=libbitcoin_node.a
LIBBITCOIN_COMMON=libbitcoin_common.a
LIBBITCOIN_CONSENSUS=libbitcoin_consensus.a
LIBBITCOIN_CLI=libbitcoin_cli.a
+LIBBITCOIN_KERNEL=libbitcoin_kernel.a
LIBBITCOIN_UTIL=libbitcoin_util.a
-LIBBITCOIN_CRYPTO_BASE=crypto/libbitcoin_crypto_base.a
+LIBBITCOIN_CRYPTO_BASE=crypto/libbitcoin_crypto_base.la
LIBBITCOINQT=qt/libbitcoinqt.a
LIBSECP256K1=secp256k1/libsecp256k1.la
@@ -32,28 +41,32 @@ endif
if BUILD_BITCOIN_LIBS
LIBBITCOINCONSENSUS=libbitcoinconsensus.la
endif
+if BUILD_BITCOIN_KERNEL_LIB
+LIBBITCOINKERNEL=libbitcoinkernel.la
+endif
if ENABLE_WALLET
LIBBITCOIN_WALLET=libbitcoin_wallet.a
LIBBITCOIN_WALLET_TOOL=libbitcoin_wallet_tool.a
endif
-LIBBITCOIN_CRYPTO= $(LIBBITCOIN_CRYPTO_BASE)
+LIBBITCOIN_CRYPTO = $(LIBBITCOIN_CRYPTO_BASE)
if ENABLE_SSE41
-LIBBITCOIN_CRYPTO_SSE41 = crypto/libbitcoin_crypto_sse41.a
+LIBBITCOIN_CRYPTO_SSE41 = crypto/libbitcoin_crypto_sse41.la
LIBBITCOIN_CRYPTO += $(LIBBITCOIN_CRYPTO_SSE41)
endif
if ENABLE_AVX2
-LIBBITCOIN_CRYPTO_AVX2 = crypto/libbitcoin_crypto_avx2.a
+LIBBITCOIN_CRYPTO_AVX2 = crypto/libbitcoin_crypto_avx2.la
LIBBITCOIN_CRYPTO += $(LIBBITCOIN_CRYPTO_AVX2)
endif
if ENABLE_X86_SHANI
-LIBBITCOIN_CRYPTO_X86_SHANI = crypto/libbitcoin_crypto_x86_shani.a
+LIBBITCOIN_CRYPTO_X86_SHANI = crypto/libbitcoin_crypto_x86_shani.la
LIBBITCOIN_CRYPTO += $(LIBBITCOIN_CRYPTO_X86_SHANI)
endif
if ENABLE_ARM_SHANI
-LIBBITCOIN_CRYPTO_ARM_SHANI = crypto/libbitcoin_crypto_arm_shani.a
+LIBBITCOIN_CRYPTO_ARM_SHANI = crypto/libbitcoin_crypto_arm_shani.la
LIBBITCOIN_CRYPTO += $(LIBBITCOIN_CRYPTO_ARM_SHANI)
endif
+noinst_LTLIBRARIES += $(LIBBITCOIN_CRYPTO)
$(LIBSECP256K1): $(wildcard secp256k1/src/*.h) $(wildcard secp256k1/src/*.c) $(wildcard secp256k1/include/*)
$(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F)
@@ -61,7 +74,6 @@ $(LIBSECP256K1): $(wildcard secp256k1/src/*.h) $(wildcard secp256k1/src/*.c) $(w
# Make is not made aware of per-object dependencies to avoid limiting building parallelization
# But to build the less dependent modules first, we manually select their order here:
EXTRA_LIBRARIES += \
- $(LIBBITCOIN_CRYPTO) \
$(LIBBITCOIN_UTIL) \
$(LIBBITCOIN_COMMON) \
$(LIBBITCOIN_CONSENSUS) \
@@ -72,14 +84,6 @@ EXTRA_LIBRARIES += \
$(LIBBITCOIN_WALLET_TOOL) \
$(LIBBITCOIN_ZMQ)
-lib_LTLIBRARIES = $(LIBBITCOINCONSENSUS)
-noinst_LTLIBRARIES =
-
-bin_PROGRAMS =
-noinst_PROGRAMS =
-TESTS =
-BENCHMARKS =
-
if BUILD_BITCOIND
bin_PROGRAMS += bitcoind
endif
@@ -464,9 +468,16 @@ libbitcoin_wallet_tool_a_SOURCES = \
$(BITCOIN_CORE_H)
# crypto primitives library
-crypto_libbitcoin_crypto_base_a_CPPFLAGS = $(AM_CPPFLAGS)
-crypto_libbitcoin_crypto_base_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-crypto_libbitcoin_crypto_base_a_SOURCES = \
+crypto_libbitcoin_crypto_base_la_CPPFLAGS = $(AM_CPPFLAGS)
+
+# Specify -static in both CXXFLAGS and LDFLAGS so libtool will only build a
+# static version of this library. We don't need a dynamic version, and a dynamic
+# version can't be used on windows anyway because the library doesn't currently
+# export DLL symbols.
+crypto_libbitcoin_crypto_base_la_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) -static
+crypto_libbitcoin_crypto_base_la_LDFLAGS = $(AM_LDFLAGS) -static
+
+crypto_libbitcoin_crypto_base_la_SOURCES = \
crypto/aes.cpp \
crypto/aes.h \
crypto/chacha_poly_aead.h \
@@ -498,32 +509,44 @@ crypto_libbitcoin_crypto_base_a_SOURCES = \
crypto/siphash.h
if USE_ASM
-crypto_libbitcoin_crypto_base_a_SOURCES += crypto/sha256_sse4.cpp
+crypto_libbitcoin_crypto_base_la_SOURCES += crypto/sha256_sse4.cpp
endif
-crypto_libbitcoin_crypto_sse41_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-crypto_libbitcoin_crypto_sse41_a_CPPFLAGS = $(AM_CPPFLAGS)
-crypto_libbitcoin_crypto_sse41_a_CXXFLAGS += $(SSE41_CXXFLAGS)
-crypto_libbitcoin_crypto_sse41_a_CPPFLAGS += -DENABLE_SSE41
-crypto_libbitcoin_crypto_sse41_a_SOURCES = crypto/sha256_sse41.cpp
-
-crypto_libbitcoin_crypto_avx2_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-crypto_libbitcoin_crypto_avx2_a_CPPFLAGS = $(AM_CPPFLAGS)
-crypto_libbitcoin_crypto_avx2_a_CXXFLAGS += $(AVX2_CXXFLAGS)
-crypto_libbitcoin_crypto_avx2_a_CPPFLAGS += -DENABLE_AVX2
-crypto_libbitcoin_crypto_avx2_a_SOURCES = crypto/sha256_avx2.cpp
-
-crypto_libbitcoin_crypto_x86_shani_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-crypto_libbitcoin_crypto_x86_shani_a_CPPFLAGS = $(AM_CPPFLAGS)
-crypto_libbitcoin_crypto_x86_shani_a_CXXFLAGS += $(X86_SHANI_CXXFLAGS)
-crypto_libbitcoin_crypto_x86_shani_a_CPPFLAGS += -DENABLE_X86_SHANI
-crypto_libbitcoin_crypto_x86_shani_a_SOURCES = crypto/sha256_x86_shani.cpp
-
-crypto_libbitcoin_crypto_arm_shani_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-crypto_libbitcoin_crypto_arm_shani_a_CPPFLAGS = $(AM_CPPFLAGS)
-crypto_libbitcoin_crypto_arm_shani_a_CXXFLAGS += $(ARM_SHANI_CXXFLAGS)
-crypto_libbitcoin_crypto_arm_shani_a_CPPFLAGS += -DENABLE_ARM_SHANI
-crypto_libbitcoin_crypto_arm_shani_a_SOURCES = crypto/sha256_arm_shani.cpp
+# See explanation for -static in crypto_libbitcoin_crypto_base_la's LDFLAGS and
+# CXXFLAGS above
+crypto_libbitcoin_crypto_sse41_la_LDFLAGS = $(AM_LDFLAGS) -static
+crypto_libbitcoin_crypto_sse41_la_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) -static
+crypto_libbitcoin_crypto_sse41_la_CPPFLAGS = $(AM_CPPFLAGS)
+crypto_libbitcoin_crypto_sse41_la_CXXFLAGS += $(SSE41_CXXFLAGS)
+crypto_libbitcoin_crypto_sse41_la_CPPFLAGS += -DENABLE_SSE41
+crypto_libbitcoin_crypto_sse41_la_SOURCES = crypto/sha256_sse41.cpp
+
+# See explanation for -static in crypto_libbitcoin_crypto_base_la's LDFLAGS and
+# CXXFLAGS above
+crypto_libbitcoin_crypto_avx2_la_LDFLAGS = $(AM_LDFLAGS) -static
+crypto_libbitcoin_crypto_avx2_la_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) -static
+crypto_libbitcoin_crypto_avx2_la_CPPFLAGS = $(AM_CPPFLAGS)
+crypto_libbitcoin_crypto_avx2_la_CXXFLAGS += $(AVX2_CXXFLAGS)
+crypto_libbitcoin_crypto_avx2_la_CPPFLAGS += -DENABLE_AVX2
+crypto_libbitcoin_crypto_avx2_la_SOURCES = crypto/sha256_avx2.cpp
+
+# See explanation for -static in crypto_libbitcoin_crypto_base_la's LDFLAGS and
+# CXXFLAGS above
+crypto_libbitcoin_crypto_x86_shani_la_LDFLAGS = $(AM_LDFLAGS) -static
+crypto_libbitcoin_crypto_x86_shani_la_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) -static
+crypto_libbitcoin_crypto_x86_shani_la_CPPFLAGS = $(AM_CPPFLAGS)
+crypto_libbitcoin_crypto_x86_shani_la_CXXFLAGS += $(X86_SHANI_CXXFLAGS)
+crypto_libbitcoin_crypto_x86_shani_la_CPPFLAGS += -DENABLE_X86_SHANI
+crypto_libbitcoin_crypto_x86_shani_la_SOURCES = crypto/sha256_x86_shani.cpp
+
+# See explanation for -static in crypto_libbitcoin_crypto_base_la's LDFLAGS and
+# CXXFLAGS above
+crypto_libbitcoin_crypto_arm_shani_la_LDFLAGS = $(AM_LDFLAGS) -static
+crypto_libbitcoin_crypto_arm_shani_la_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) -static
+crypto_libbitcoin_crypto_arm_shani_la_CPPFLAGS = $(AM_CPPFLAGS)
+crypto_libbitcoin_crypto_arm_shani_la_CXXFLAGS += $(ARM_SHANI_CXXFLAGS)
+crypto_libbitcoin_crypto_arm_shani_la_CPPFLAGS += -DENABLE_ARM_SHANI
+crypto_libbitcoin_crypto_arm_shani_la_SOURCES = crypto/sha256_arm_shani.cpp
# consensus: shared between all executables that validate any consensus rules.
libbitcoin_consensus_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
@@ -683,7 +706,6 @@ bitcoin_bin_ldadd = \
$(LIBBITCOIN_CONSENSUS) \
$(LIBBITCOIN_CRYPTO) \
$(LIBLEVELDB) \
- $(LIBLEVELDB_SSE42) \
$(LIBMEMENV) \
$(LIBSECP256K1)
@@ -782,8 +804,48 @@ bitcoin_util_LDADD = \
#
# bitcoin-chainstate binary #
-bitcoin_chainstate_SOURCES = \
- bitcoin-chainstate.cpp \
+bitcoin_chainstate_SOURCES = bitcoin-chainstate.cpp
+bitcoin_chainstate_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
+bitcoin_chainstate_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+
+# $(LIBTOOL_APP_LDFLAGS) deliberately omitted here so that we can test linking
+# bitcoin-chainstate against libbitcoinkernel as a shared or static library by
+# setting --{en,dis}able-shared.
+bitcoin_chainstate_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(PTHREAD_FLAGS)
+bitcoin_chainstate_LDADD = $(LIBBITCOINKERNEL)
+#
+
+# bitcoinkernel library #
+if BUILD_BITCOIN_KERNEL_LIB
+lib_LTLIBRARIES += $(LIBBITCOINKERNEL)
+
+libbitcoinkernel_la_LDFLAGS = $(AM_LDFLAGS) -no-undefined $(RELDFLAGS) $(PTHREAD_FLAGS)
+libbitcoinkernel_la_LIBADD = $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) $(LIBLEVELDB) $(LIBMEMENV) $(LIBSECP256K1)
+libbitcoinkernel_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(builddir)/obj -I$(srcdir)/secp256k1/include -DBUILD_BITCOIN_INTERNAL $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS) -I$(srcdir)/$(UNIVALUE_INCLUDE_DIR_INT)
+
+# libbitcoinkernel requires default symbol visibility, explicitly specify that
+# here so that things still work even when user configures with
+# --enable-reduce-exports
+#
+# Note this is a quick hack that will be removed as we incrementally define what
+# to export from the library.
+libbitcoinkernel_la_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) -fvisibility=default
+
+# TODO: For now, Specify -static in both CXXFLAGS and LDFLAGS when building for
+# windows targets so libtool will only build a static version of this
+# library. There are unresolved problems when building dll's for mingw-w64
+# and attempting to statically embed libstdc++, libpthread, etc.
+if TARGET_WINDOWS
+libbitcoinkernel_la_LDFLAGS += -static
+libbitcoinkernel_la_CXXFLAGS += -static
+endif
+
+# TODO: libbitcoinkernel is a work in progress consensus engine library, as more
+# and more modules are decoupled from the consensus engine, this list will
+# shrink to only those which are absolutely necessary. For example, things
+# like index/*.cpp will be removed.
+libbitcoinkernel_la_SOURCES = \
+ kernel/bitcoinkernel.cpp \
arith_uint256.cpp \
blockfilter.cpp \
chain.cpp \
@@ -862,26 +924,19 @@ bitcoin_chainstate_SOURCES = \
validationinterface.cpp \
versionbits.cpp \
warnings.cpp
-bitcoin_chainstate_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-bitcoin_chainstate_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-bitcoin_chainstate_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) $(PTHREAD_FLAGS)
-bitcoin_chainstate_LDADD = \
- $(LIBBITCOIN_CRYPTO) \
- $(LIBUNIVALUE) \
- $(LIBSECP256K1) \
- $(LIBLEVELDB) \
- $(LIBLEVELDB_SSE42) \
- $(LIBMEMENV)
# Required for obj/build.h to be generated first.
# More details: https://www.gnu.org/software/automake/manual/html_node/Built-Sources-Example.html
-bitcoin_chainstate-clientversion.$(OBJEXT): obj/build.h
+libbitcoinkernel_la-clientversion.l$(OBJEXT): obj/build.h
+endif # BUILD_BITCOIN_KERNEL_LIB
#
# bitcoinconsensus library #
if BUILD_BITCOIN_LIBS
+lib_LTLIBRARIES += $(LIBBITCOINCONSENSUS)
+
include_HEADERS = script/bitcoinconsensus.h
-libbitcoinconsensus_la_SOURCES = support/cleanse.cpp $(crypto_libbitcoin_crypto_base_a_SOURCES) $(libbitcoin_consensus_a_SOURCES)
+libbitcoinconsensus_la_SOURCES = support/cleanse.cpp $(crypto_libbitcoin_crypto_base_la_SOURCES) $(libbitcoin_consensus_a_SOURCES)
libbitcoinconsensus_la_LDFLAGS = $(AM_LDFLAGS) -no-undefined $(RELDFLAGS)
libbitcoinconsensus_la_LIBADD = $(LIBSECP256K1)
diff --git a/src/Makefile.bench.include b/src/Makefile.bench.include
index 58a09cd4a4..e90c8530d8 100644
--- a/src/Makefile.bench.include
+++ b/src/Makefile.bench.include
@@ -52,15 +52,14 @@ nodist_bench_bench_bitcoin_SOURCES = $(GENERATED_BENCH_FILES)
bench_bench_bitcoin_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(EVENT_CFLAGS) $(EVENT_PTHREADS_CFLAGS) -I$(builddir)/bench/
bench_bench_bitcoin_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
bench_bench_bitcoin_LDADD = \
+ $(LIBTEST_UTIL) \
$(LIBBITCOIN_NODE) \
$(LIBBITCOIN_WALLET) \
$(LIBBITCOIN_COMMON) \
$(LIBBITCOIN_UTIL) \
$(LIBBITCOIN_CONSENSUS) \
$(LIBBITCOIN_CRYPTO) \
- $(LIBTEST_UTIL) \
$(LIBLEVELDB) \
- $(LIBLEVELDB_SSE42) \
$(LIBMEMENV) \
$(LIBSECP256K1) \
$(LIBUNIVALUE) \
diff --git a/src/Makefile.crc32c.include b/src/Makefile.crc32c.include
index 3cbe71792c..c4dd84991d 100644
--- a/src/Makefile.crc32c.include
+++ b/src/Makefile.crc32c.include
@@ -2,10 +2,9 @@
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
-LIBCRC32C_INT = crc32c/libcrc32c.a
-LIBLEVELDB_SSE42_INT = leveldb/libleveldb_sse42.a
+LIBCRC32C_INT = crc32c/libcrc32c.la
-EXTRA_LIBRARIES += $(LIBCRC32C_INT)
+noinst_LTLIBRARIES += $(LIBCRC32C_INT)
LIBCRC32C = $(LIBCRC32C_INT)
@@ -34,41 +33,49 @@ else
CRC32C_CPPFLAGS_INT += -DBYTE_ORDER_BIG_ENDIAN=0
endif
-crc32c_libcrc32c_a_CPPFLAGS = $(AM_CPPFLAGS) $(CRC32C_CPPFLAGS_INT) $(CRC32C_CPPFLAGS)
-crc32c_libcrc32c_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-
-crc32c_libcrc32c_a_SOURCES =
-crc32c_libcrc32c_a_SOURCES += crc32c/include/crc32c/crc32c.h
-crc32c_libcrc32c_a_SOURCES += crc32c/src/crc32c_arm64.h
-crc32c_libcrc32c_a_SOURCES += crc32c/src/crc32c_arm64_check.h
-crc32c_libcrc32c_a_SOURCES += crc32c/src/crc32c_internal.h
-crc32c_libcrc32c_a_SOURCES += crc32c/src/crc32c_prefetch.h
-crc32c_libcrc32c_a_SOURCES += crc32c/src/crc32c_read_le.h
-crc32c_libcrc32c_a_SOURCES += crc32c/src/crc32c_round_up.h
-crc32c_libcrc32c_a_SOURCES += crc32c/src/crc32c_sse42_check.h
-crc32c_libcrc32c_a_SOURCES += crc32c/src/crc32c_sse42.h
-
-crc32c_libcrc32c_a_SOURCES += crc32c/src/crc32c.cc
-crc32c_libcrc32c_a_SOURCES += crc32c/src/crc32c_portable.cc
+crc32c_libcrc32c_la_CPPFLAGS = $(AM_CPPFLAGS) $(CRC32C_CPPFLAGS_INT) $(CRC32C_CPPFLAGS)
+
+# Specify -static in both CXXFLAGS and LDFLAGS so libtool will only build a
+# static version of this library. We don't need a dynamic version, and a dynamic
+# version can't be used on windows anyway because the library doesn't currently
+# export DLL symbols.
+crc32c_libcrc32c_la_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) -static
+crc32c_libcrc32c_la_LDFLAGS = $(AM_LDFLAGS) -static
+
+crc32c_libcrc32c_la_SOURCES =
+crc32c_libcrc32c_la_SOURCES += crc32c/include/crc32c/crc32c.h
+crc32c_libcrc32c_la_SOURCES += crc32c/src/crc32c_arm64.h
+crc32c_libcrc32c_la_SOURCES += crc32c/src/crc32c_arm64_check.h
+crc32c_libcrc32c_la_SOURCES += crc32c/src/crc32c_internal.h
+crc32c_libcrc32c_la_SOURCES += crc32c/src/crc32c_prefetch.h
+crc32c_libcrc32c_la_SOURCES += crc32c/src/crc32c_read_le.h
+crc32c_libcrc32c_la_SOURCES += crc32c/src/crc32c_round_up.h
+crc32c_libcrc32c_la_SOURCES += crc32c/src/crc32c_sse42_check.h
+crc32c_libcrc32c_la_SOURCES += crc32c/src/crc32c_sse42.h
+
+crc32c_libcrc32c_la_SOURCES += crc32c/src/crc32c.cc
+crc32c_libcrc32c_la_SOURCES += crc32c/src/crc32c_portable.cc
if ENABLE_SSE42
-LIBCRC32C_SSE42_INT = crc32c/libcrc32c_sse42.a
-EXTRA_LIBRARIES += $(LIBCRC32C_SSE42_INT)
+LIBCRC32C_SSE42_INT = crc32c/libcrc32c_sse42.la
+noinst_LTLIBRARIES += $(LIBCRC32C_SSE42_INT)
LIBCRC32C += $(LIBCRC32C_SSE42_INT)
-crc32c_libcrc32c_sse42_a_CPPFLAGS = $(crc32c_libcrc32c_a_CPPFLAGS)
-crc32c_libcrc32c_sse42_a_CXXFLAGS = $(crc32c_libcrc32c_a_CXXFLAGS) $(SSE42_CXXFLAGS)
+crc32c_libcrc32c_sse42_la_CPPFLAGS = $(crc32c_libcrc32c_la_CPPFLAGS)
+crc32c_libcrc32c_sse42_la_CXXFLAGS = $(crc32c_libcrc32c_la_CXXFLAGS) $(SSE42_CXXFLAGS)
+crc32c_libcrc32c_sse42_la_LDFLAGS = $(crc32c_libcrc32c_la_LDFLAGS)
-crc32c_libcrc32c_sse42_a_SOURCES = crc32c/src/crc32c_sse42.cc
+crc32c_libcrc32c_sse42_la_SOURCES = crc32c/src/crc32c_sse42.cc
endif
if ENABLE_ARM_CRC
-LIBCRC32C_ARM_CRC_INT = crc32c/libcrc32c_arm_crc.a
-EXTRA_LIBRARIES += $(LIBCRC32C_ARM_CRC_INT)
+LIBCRC32C_ARM_CRC_INT = crc32c/libcrc32c_arm_crc.la
+noinst_LTLIBRARIES += $(LIBCRC32C_ARM_CRC_INT)
LIBCRC32C += $(LIBCRC32C_ARM_CRC_INT)
-crc32c_libcrc32c_arm_crc_a_CPPFLAGS = $(crc32c_libcrc32c_a_CPPFLAGS)
-crc32c_libcrc32c_arm_crc_a_CXXFLAGS = $(crc32c_libcrc32c_a_CXXFLAGS) $(ARM_CRC_CXXFLAGS)
+crc32c_libcrc32c_arm_crc_la_CPPFLAGS = $(crc32c_libcrc32c_la_CPPFLAGS)
+crc32c_libcrc32c_arm_crc_la_CXXFLAGS = $(crc32c_libcrc32c_la_CXXFLAGS) $(ARM_CRC_CXXFLAGS)
+crc32c_libcrc32c_arm_crc_la_LDFLAGS = $(crc32c_libcrc32c_la_LDFLAGS)
-crc32c_libcrc32c_arm_crc_a_SOURCES = crc32c/src/crc32c_arm64.cc
+crc32c_libcrc32c_arm_crc_la_SOURCES = crc32c/src/crc32c_arm64.cc
endif
diff --git a/src/Makefile.leveldb.include b/src/Makefile.leveldb.include
index 3bec92482a..066f8940c5 100644
--- a/src/Makefile.leveldb.include
+++ b/src/Makefile.leveldb.include
@@ -2,11 +2,11 @@
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
-LIBLEVELDB_INT = leveldb/libleveldb.a
-LIBMEMENV_INT = leveldb/libmemenv.a
+LIBLEVELDB_INT = leveldb/libleveldb.la
+LIBMEMENV_INT = leveldb/libmemenv.la
-EXTRA_LIBRARIES += $(LIBLEVELDB_INT)
-EXTRA_LIBRARIES += $(LIBMEMENV_INT)
+noinst_LTLIBRARIES += $(LIBLEVELDB_INT)
+noinst_LTLIBRARIES += $(LIBMEMENV_INT)
LIBLEVELDB = $(LIBLEVELDB_INT) $(LIBCRC32C)
LIBMEMENV = $(LIBMEMENV_INT)
@@ -37,111 +37,118 @@ else
LEVELDB_CPPFLAGS_INT += -DLEVELDB_PLATFORM_POSIX
endif
-leveldb_libleveldb_a_CPPFLAGS = $(AM_CPPFLAGS) $(LEVELDB_CPPFLAGS_INT) $(LEVELDB_CPPFLAGS)
-leveldb_libleveldb_a_CXXFLAGS = $(filter-out -Wconditional-uninitialized -Werror=conditional-uninitialized -Wsuggest-override -Werror=suggest-override, $(AM_CXXFLAGS)) $(PIE_FLAGS)
+leveldb_libleveldb_la_CPPFLAGS = $(AM_CPPFLAGS) $(LEVELDB_CPPFLAGS_INT) $(LEVELDB_CPPFLAGS)
-leveldb_libleveldb_a_SOURCES=
-leveldb_libleveldb_a_SOURCES += leveldb/port/port_stdcxx.h
-leveldb_libleveldb_a_SOURCES += leveldb/port/port.h
-leveldb_libleveldb_a_SOURCES += leveldb/port/thread_annotations.h
-leveldb_libleveldb_a_SOURCES += leveldb/include/leveldb/db.h
-leveldb_libleveldb_a_SOURCES += leveldb/include/leveldb/options.h
-leveldb_libleveldb_a_SOURCES += leveldb/include/leveldb/comparator.h
-leveldb_libleveldb_a_SOURCES += leveldb/include/leveldb/filter_policy.h
-leveldb_libleveldb_a_SOURCES += leveldb/include/leveldb/slice.h
-leveldb_libleveldb_a_SOURCES += leveldb/include/leveldb/table_builder.h
-leveldb_libleveldb_a_SOURCES += leveldb/include/leveldb/env.h
-leveldb_libleveldb_a_SOURCES += leveldb/include/leveldb/export.h
-leveldb_libleveldb_a_SOURCES += leveldb/include/leveldb/c.h
-leveldb_libleveldb_a_SOURCES += leveldb/include/leveldb/iterator.h
-leveldb_libleveldb_a_SOURCES += leveldb/include/leveldb/cache.h
-leveldb_libleveldb_a_SOURCES += leveldb/include/leveldb/dumpfile.h
-leveldb_libleveldb_a_SOURCES += leveldb/include/leveldb/table.h
-leveldb_libleveldb_a_SOURCES += leveldb/include/leveldb/write_batch.h
-leveldb_libleveldb_a_SOURCES += leveldb/include/leveldb/status.h
-leveldb_libleveldb_a_SOURCES += leveldb/db/log_format.h
-leveldb_libleveldb_a_SOURCES += leveldb/db/memtable.h
-leveldb_libleveldb_a_SOURCES += leveldb/db/version_set.h
-leveldb_libleveldb_a_SOURCES += leveldb/db/write_batch_internal.h
-leveldb_libleveldb_a_SOURCES += leveldb/db/filename.h
-leveldb_libleveldb_a_SOURCES += leveldb/db/version_edit.h
-leveldb_libleveldb_a_SOURCES += leveldb/db/dbformat.h
-leveldb_libleveldb_a_SOURCES += leveldb/db/builder.h
-leveldb_libleveldb_a_SOURCES += leveldb/db/log_writer.h
-leveldb_libleveldb_a_SOURCES += leveldb/db/db_iter.h
-leveldb_libleveldb_a_SOURCES += leveldb/db/skiplist.h
-leveldb_libleveldb_a_SOURCES += leveldb/db/db_impl.h
-leveldb_libleveldb_a_SOURCES += leveldb/db/table_cache.h
-leveldb_libleveldb_a_SOURCES += leveldb/db/snapshot.h
-leveldb_libleveldb_a_SOURCES += leveldb/db/log_reader.h
-leveldb_libleveldb_a_SOURCES += leveldb/table/filter_block.h
-leveldb_libleveldb_a_SOURCES += leveldb/table/block_builder.h
-leveldb_libleveldb_a_SOURCES += leveldb/table/block.h
-leveldb_libleveldb_a_SOURCES += leveldb/table/two_level_iterator.h
-leveldb_libleveldb_a_SOURCES += leveldb/table/merger.h
-leveldb_libleveldb_a_SOURCES += leveldb/table/format.h
-leveldb_libleveldb_a_SOURCES += leveldb/table/iterator_wrapper.h
-leveldb_libleveldb_a_SOURCES += leveldb/util/crc32c.h
-leveldb_libleveldb_a_SOURCES += leveldb/util/env_posix_test_helper.h
-leveldb_libleveldb_a_SOURCES += leveldb/util/env_windows_test_helper.h
-leveldb_libleveldb_a_SOURCES += leveldb/util/arena.h
-leveldb_libleveldb_a_SOURCES += leveldb/util/random.h
-leveldb_libleveldb_a_SOURCES += leveldb/util/posix_logger.h
-leveldb_libleveldb_a_SOURCES += leveldb/util/hash.h
-leveldb_libleveldb_a_SOURCES += leveldb/util/histogram.h
-leveldb_libleveldb_a_SOURCES += leveldb/util/coding.h
-leveldb_libleveldb_a_SOURCES += leveldb/util/testutil.h
-leveldb_libleveldb_a_SOURCES += leveldb/util/mutexlock.h
-leveldb_libleveldb_a_SOURCES += leveldb/util/logging.h
-leveldb_libleveldb_a_SOURCES += leveldb/util/no_destructor.h
-leveldb_libleveldb_a_SOURCES += leveldb/util/testharness.h
-leveldb_libleveldb_a_SOURCES += leveldb/util/windows_logger.h
+# Specify -static in both CXXFLAGS and LDFLAGS so libtool will only build a
+# static version of this library. We don't need a dynamic version, and a dynamic
+# version can't be used on windows anyway because the library doesn't currently
+# export DLL symbols.
+leveldb_libleveldb_la_CXXFLAGS = $(filter-out -Wconditional-uninitialized -Werror=conditional-uninitialized -Wsuggest-override -Werror=suggest-override, $(AM_CXXFLAGS)) $(PIE_FLAGS) -static
+leveldb_libleveldb_la_LDFLAGS = $(AM_LDFLAGS) -static
-leveldb_libleveldb_a_SOURCES += leveldb/db/builder.cc
-leveldb_libleveldb_a_SOURCES += leveldb/db/c.cc
-leveldb_libleveldb_a_SOURCES += leveldb/db/dbformat.cc
-leveldb_libleveldb_a_SOURCES += leveldb/db/db_impl.cc
-leveldb_libleveldb_a_SOURCES += leveldb/db/db_iter.cc
-leveldb_libleveldb_a_SOURCES += leveldb/db/dumpfile.cc
-leveldb_libleveldb_a_SOURCES += leveldb/db/filename.cc
-leveldb_libleveldb_a_SOURCES += leveldb/db/log_reader.cc
-leveldb_libleveldb_a_SOURCES += leveldb/db/log_writer.cc
-leveldb_libleveldb_a_SOURCES += leveldb/db/memtable.cc
-leveldb_libleveldb_a_SOURCES += leveldb/db/repair.cc
-leveldb_libleveldb_a_SOURCES += leveldb/db/table_cache.cc
-leveldb_libleveldb_a_SOURCES += leveldb/db/version_edit.cc
-leveldb_libleveldb_a_SOURCES += leveldb/db/version_set.cc
-leveldb_libleveldb_a_SOURCES += leveldb/db/write_batch.cc
-leveldb_libleveldb_a_SOURCES += leveldb/table/block_builder.cc
-leveldb_libleveldb_a_SOURCES += leveldb/table/block.cc
-leveldb_libleveldb_a_SOURCES += leveldb/table/filter_block.cc
-leveldb_libleveldb_a_SOURCES += leveldb/table/format.cc
-leveldb_libleveldb_a_SOURCES += leveldb/table/iterator.cc
-leveldb_libleveldb_a_SOURCES += leveldb/table/merger.cc
-leveldb_libleveldb_a_SOURCES += leveldb/table/table_builder.cc
-leveldb_libleveldb_a_SOURCES += leveldb/table/table.cc
-leveldb_libleveldb_a_SOURCES += leveldb/table/two_level_iterator.cc
-leveldb_libleveldb_a_SOURCES += leveldb/util/arena.cc
-leveldb_libleveldb_a_SOURCES += leveldb/util/bloom.cc
-leveldb_libleveldb_a_SOURCES += leveldb/util/cache.cc
-leveldb_libleveldb_a_SOURCES += leveldb/util/coding.cc
-leveldb_libleveldb_a_SOURCES += leveldb/util/comparator.cc
-leveldb_libleveldb_a_SOURCES += leveldb/util/crc32c.cc
-leveldb_libleveldb_a_SOURCES += leveldb/util/env.cc
-leveldb_libleveldb_a_SOURCES += leveldb/util/filter_policy.cc
-leveldb_libleveldb_a_SOURCES += leveldb/util/hash.cc
-leveldb_libleveldb_a_SOURCES += leveldb/util/histogram.cc
-leveldb_libleveldb_a_SOURCES += leveldb/util/logging.cc
-leveldb_libleveldb_a_SOURCES += leveldb/util/options.cc
-leveldb_libleveldb_a_SOURCES += leveldb/util/status.cc
+leveldb_libleveldb_la_SOURCES=
+leveldb_libleveldb_la_SOURCES += leveldb/port/port_stdcxx.h
+leveldb_libleveldb_la_SOURCES += leveldb/port/port.h
+leveldb_libleveldb_la_SOURCES += leveldb/port/thread_annotations.h
+leveldb_libleveldb_la_SOURCES += leveldb/include/leveldb/db.h
+leveldb_libleveldb_la_SOURCES += leveldb/include/leveldb/options.h
+leveldb_libleveldb_la_SOURCES += leveldb/include/leveldb/comparator.h
+leveldb_libleveldb_la_SOURCES += leveldb/include/leveldb/filter_policy.h
+leveldb_libleveldb_la_SOURCES += leveldb/include/leveldb/slice.h
+leveldb_libleveldb_la_SOURCES += leveldb/include/leveldb/table_builder.h
+leveldb_libleveldb_la_SOURCES += leveldb/include/leveldb/env.h
+leveldb_libleveldb_la_SOURCES += leveldb/include/leveldb/export.h
+leveldb_libleveldb_la_SOURCES += leveldb/include/leveldb/c.h
+leveldb_libleveldb_la_SOURCES += leveldb/include/leveldb/iterator.h
+leveldb_libleveldb_la_SOURCES += leveldb/include/leveldb/cache.h
+leveldb_libleveldb_la_SOURCES += leveldb/include/leveldb/dumpfile.h
+leveldb_libleveldb_la_SOURCES += leveldb/include/leveldb/table.h
+leveldb_libleveldb_la_SOURCES += leveldb/include/leveldb/write_batch.h
+leveldb_libleveldb_la_SOURCES += leveldb/include/leveldb/status.h
+leveldb_libleveldb_la_SOURCES += leveldb/db/log_format.h
+leveldb_libleveldb_la_SOURCES += leveldb/db/memtable.h
+leveldb_libleveldb_la_SOURCES += leveldb/db/version_set.h
+leveldb_libleveldb_la_SOURCES += leveldb/db/write_batch_internal.h
+leveldb_libleveldb_la_SOURCES += leveldb/db/filename.h
+leveldb_libleveldb_la_SOURCES += leveldb/db/version_edit.h
+leveldb_libleveldb_la_SOURCES += leveldb/db/dbformat.h
+leveldb_libleveldb_la_SOURCES += leveldb/db/builder.h
+leveldb_libleveldb_la_SOURCES += leveldb/db/log_writer.h
+leveldb_libleveldb_la_SOURCES += leveldb/db/db_iter.h
+leveldb_libleveldb_la_SOURCES += leveldb/db/skiplist.h
+leveldb_libleveldb_la_SOURCES += leveldb/db/db_impl.h
+leveldb_libleveldb_la_SOURCES += leveldb/db/table_cache.h
+leveldb_libleveldb_la_SOURCES += leveldb/db/snapshot.h
+leveldb_libleveldb_la_SOURCES += leveldb/db/log_reader.h
+leveldb_libleveldb_la_SOURCES += leveldb/table/filter_block.h
+leveldb_libleveldb_la_SOURCES += leveldb/table/block_builder.h
+leveldb_libleveldb_la_SOURCES += leveldb/table/block.h
+leveldb_libleveldb_la_SOURCES += leveldb/table/two_level_iterator.h
+leveldb_libleveldb_la_SOURCES += leveldb/table/merger.h
+leveldb_libleveldb_la_SOURCES += leveldb/table/format.h
+leveldb_libleveldb_la_SOURCES += leveldb/table/iterator_wrapper.h
+leveldb_libleveldb_la_SOURCES += leveldb/util/crc32c.h
+leveldb_libleveldb_la_SOURCES += leveldb/util/env_posix_test_helper.h
+leveldb_libleveldb_la_SOURCES += leveldb/util/env_windows_test_helper.h
+leveldb_libleveldb_la_SOURCES += leveldb/util/arena.h
+leveldb_libleveldb_la_SOURCES += leveldb/util/random.h
+leveldb_libleveldb_la_SOURCES += leveldb/util/posix_logger.h
+leveldb_libleveldb_la_SOURCES += leveldb/util/hash.h
+leveldb_libleveldb_la_SOURCES += leveldb/util/histogram.h
+leveldb_libleveldb_la_SOURCES += leveldb/util/coding.h
+leveldb_libleveldb_la_SOURCES += leveldb/util/testutil.h
+leveldb_libleveldb_la_SOURCES += leveldb/util/mutexlock.h
+leveldb_libleveldb_la_SOURCES += leveldb/util/logging.h
+leveldb_libleveldb_la_SOURCES += leveldb/util/no_destructor.h
+leveldb_libleveldb_la_SOURCES += leveldb/util/testharness.h
+leveldb_libleveldb_la_SOURCES += leveldb/util/windows_logger.h
+
+leveldb_libleveldb_la_SOURCES += leveldb/db/builder.cc
+leveldb_libleveldb_la_SOURCES += leveldb/db/c.cc
+leveldb_libleveldb_la_SOURCES += leveldb/db/dbformat.cc
+leveldb_libleveldb_la_SOURCES += leveldb/db/db_impl.cc
+leveldb_libleveldb_la_SOURCES += leveldb/db/db_iter.cc
+leveldb_libleveldb_la_SOURCES += leveldb/db/dumpfile.cc
+leveldb_libleveldb_la_SOURCES += leveldb/db/filename.cc
+leveldb_libleveldb_la_SOURCES += leveldb/db/log_reader.cc
+leveldb_libleveldb_la_SOURCES += leveldb/db/log_writer.cc
+leveldb_libleveldb_la_SOURCES += leveldb/db/memtable.cc
+leveldb_libleveldb_la_SOURCES += leveldb/db/repair.cc
+leveldb_libleveldb_la_SOURCES += leveldb/db/table_cache.cc
+leveldb_libleveldb_la_SOURCES += leveldb/db/version_edit.cc
+leveldb_libleveldb_la_SOURCES += leveldb/db/version_set.cc
+leveldb_libleveldb_la_SOURCES += leveldb/db/write_batch.cc
+leveldb_libleveldb_la_SOURCES += leveldb/table/block_builder.cc
+leveldb_libleveldb_la_SOURCES += leveldb/table/block.cc
+leveldb_libleveldb_la_SOURCES += leveldb/table/filter_block.cc
+leveldb_libleveldb_la_SOURCES += leveldb/table/format.cc
+leveldb_libleveldb_la_SOURCES += leveldb/table/iterator.cc
+leveldb_libleveldb_la_SOURCES += leveldb/table/merger.cc
+leveldb_libleveldb_la_SOURCES += leveldb/table/table_builder.cc
+leveldb_libleveldb_la_SOURCES += leveldb/table/table.cc
+leveldb_libleveldb_la_SOURCES += leveldb/table/two_level_iterator.cc
+leveldb_libleveldb_la_SOURCES += leveldb/util/arena.cc
+leveldb_libleveldb_la_SOURCES += leveldb/util/bloom.cc
+leveldb_libleveldb_la_SOURCES += leveldb/util/cache.cc
+leveldb_libleveldb_la_SOURCES += leveldb/util/coding.cc
+leveldb_libleveldb_la_SOURCES += leveldb/util/comparator.cc
+leveldb_libleveldb_la_SOURCES += leveldb/util/crc32c.cc
+leveldb_libleveldb_la_SOURCES += leveldb/util/env.cc
+leveldb_libleveldb_la_SOURCES += leveldb/util/filter_policy.cc
+leveldb_libleveldb_la_SOURCES += leveldb/util/hash.cc
+leveldb_libleveldb_la_SOURCES += leveldb/util/histogram.cc
+leveldb_libleveldb_la_SOURCES += leveldb/util/logging.cc
+leveldb_libleveldb_la_SOURCES += leveldb/util/options.cc
+leveldb_libleveldb_la_SOURCES += leveldb/util/status.cc
if TARGET_WINDOWS
-leveldb_libleveldb_a_SOURCES += leveldb/util/env_windows.cc
+leveldb_libleveldb_la_SOURCES += leveldb/util/env_windows.cc
else
-leveldb_libleveldb_a_SOURCES += leveldb/util/env_posix.cc
+leveldb_libleveldb_la_SOURCES += leveldb/util/env_posix.cc
endif
-leveldb_libmemenv_a_CPPFLAGS = $(leveldb_libleveldb_a_CPPFLAGS)
-leveldb_libmemenv_a_CXXFLAGS = $(leveldb_libleveldb_a_CXXFLAGS)
-leveldb_libmemenv_a_SOURCES = leveldb/helpers/memenv/memenv.cc
-leveldb_libmemenv_a_SOURCES += leveldb/helpers/memenv/memenv.h
+leveldb_libmemenv_la_CPPFLAGS = $(leveldb_libleveldb_la_CPPFLAGS)
+leveldb_libmemenv_la_CXXFLAGS = $(leveldb_libleveldb_la_CXXFLAGS)
+leveldb_libmemenv_la_LDFLAGS = $(leveldb_libleveldb_la_LDFLAGS)
+leveldb_libmemenv_la_SOURCES = leveldb/helpers/memenv/memenv.cc
+leveldb_libmemenv_la_SOURCES += leveldb/helpers/memenv/memenv.h
diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include
index 3491f07ee0..72037b3db2 100644
--- a/src/Makefile.qt.include
+++ b/src/Makefile.qt.include
@@ -330,7 +330,7 @@ endif
if ENABLE_ZMQ
bitcoin_qt_ldadd += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS)
endif
-bitcoin_qt_ldadd += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) $(LIBLEVELDB) $(LIBLEVELDB_SSE42) $(LIBMEMENV) \
+bitcoin_qt_ldadd += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) $(LIBLEVELDB) $(LIBMEMENV) \
$(QT_LIBS) $(QT_DBUS_LIBS) $(QR_LIBS) $(BDB_LIBS) $(MINIUPNPC_LIBS) $(NATPMP_LIBS) $(LIBSECP256K1) \
$(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(SQLITE_LIBS)
bitcoin_qt_ldflags = $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) $(PTHREAD_FLAGS)
diff --git a/src/Makefile.qttest.include b/src/Makefile.qttest.include
index 29c322fbc2..fa822f2954 100644
--- a/src/Makefile.qttest.include
+++ b/src/Makefile.qttest.include
@@ -55,7 +55,7 @@ if ENABLE_ZMQ
qt_test_test_bitcoin_qt_LDADD += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS)
endif
qt_test_test_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) $(LIBLEVELDB) \
- $(LIBLEVELDB_SSE42) $(LIBMEMENV) $(QT_LIBS) $(QT_DBUS_LIBS) $(QT_TEST_LIBS) \
+ $(LIBMEMENV) $(QT_LIBS) $(QT_DBUS_LIBS) $(QT_TEST_LIBS) \
$(QR_LIBS) $(BDB_LIBS) $(MINIUPNPC_LIBS) $(NATPMP_LIBS) $(LIBSECP256K1) \
$(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(SQLITE_LIBS)
qt_test_test_bitcoin_qt_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) $(PTHREAD_FLAGS)
diff --git a/src/Makefile.test.include b/src/Makefile.test.include
index 4a35f40112..02a3f9ae7d 100644
--- a/src/Makefile.test.include
+++ b/src/Makefile.test.include
@@ -47,7 +47,6 @@ FUZZ_SUITE_LD_COMMON = \
$(LIBBITCOIN_CLI) \
$(LIBUNIVALUE) \
$(LIBLEVELDB) \
- $(LIBLEVELDB_SSE42) \
$(LIBMEMENV) \
$(LIBSECP256K1) \
$(MINISKETCH_LIBS) \
@@ -205,7 +204,7 @@ test_test_bitcoin_LDADD += $(LIBBITCOIN_WALLET)
endif
test_test_bitcoin_LDADD += $(LIBBITCOIN_NODE) $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) \
- $(LIBLEVELDB) $(LIBLEVELDB_SSE42) $(LIBMEMENV) $(LIBSECP256K1) $(EVENT_LIBS) $(EVENT_PTHREADS_LIBS) $(MINISKETCH_LIBS)
+ $(LIBLEVELDB) $(LIBMEMENV) $(LIBSECP256K1) $(EVENT_LIBS) $(EVENT_PTHREADS_LIBS) $(MINISKETCH_LIBS)
test_test_bitcoin_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_test_bitcoin_LDADD += $(BDB_LIBS) $(MINIUPNPC_LIBS) $(NATPMP_LIBS) $(SQLITE_LIBS)
diff --git a/src/Makefile.test_fuzz.include b/src/Makefile.test_fuzz.include
index 9574454fd2..8922dda3ad 100644
--- a/src/Makefile.test_fuzz.include
+++ b/src/Makefile.test_fuzz.include
@@ -18,8 +18,3 @@ libtest_fuzz_a_SOURCES = \
test/fuzz/fuzz.cpp \
test/fuzz/util.cpp \
$(TEST_FUZZ_H)
-
-LIBTEST_FUZZ += $(LIBBITCOIN_NODE)
-LIBTEST_FUZZ += $(LIBBITCOIN_COMMON)
-LIBTEST_FUZZ += $(LIBBITCOIN_UTIL)
-LIBTEST_FUZZ += $(LIBBITCOIN_CRYPTO_BASE)
diff --git a/src/Makefile.test_util.include b/src/Makefile.test_util.include
index 92cb8a5ce6..9306bb6fcc 100644
--- a/src/Makefile.test_util.include
+++ b/src/Makefile.test_util.include
@@ -34,8 +34,3 @@ libtest_util_a_SOURCES = \
test/util/validation.cpp \
test/util/wallet.cpp \
$(TEST_UTIL_H)
-
-LIBTEST_UTIL += $(LIBBITCOIN_NODE)
-LIBTEST_UTIL += $(LIBBITCOIN_COMMON)
-LIBTEST_UTIL += $(LIBBITCOIN_UTIL)
-LIBTEST_UTIL += $(LIBBITCOIN_CRYPTO_BASE)
diff --git a/src/base58.cpp b/src/base58.cpp
index dfa2e8db55..11c1ce7397 100644
--- a/src/base58.cpp
+++ b/src/base58.cpp
@@ -126,7 +126,7 @@ std::string EncodeBase58(Span<const unsigned char> input)
bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vchRet, int max_ret_len)
{
- if (!ValidAsCString(str)) {
+ if (!ContainsNoNUL(str)) {
return false;
}
return DecodeBase58(str.c_str(), vchRet, max_ret_len);
@@ -160,7 +160,7 @@ std::string EncodeBase58Check(Span<const unsigned char> input)
bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRet, int max_ret)
{
- if (!ValidAsCString(str)) {
+ if (!ContainsNoNUL(str)) {
return false;
}
return DecodeBase58Check(str.c_str(), vchRet, max_ret);
diff --git a/src/bitcoin-chainstate.cpp b/src/bitcoin-chainstate.cpp
index fcbb6aacce..e5b6875a36 100644
--- a/src/bitcoin-chainstate.cpp
+++ b/src/bitcoin-chainstate.cpp
@@ -28,8 +28,6 @@
#include <functional>
#include <iosfwd>
-const std::function<std::string(const char*)> G_TRANSLATION_FUN = nullptr;
-
int main(int argc, char* argv[])
{
// SETUP: Argument parsing and handling
@@ -256,7 +254,5 @@ epilogue:
}
GetMainSignals().UnregisterBackgroundSignalScheduler();
- WITH_LOCK(::cs_main, UnloadBlockIndex(nullptr, chainman));
-
init::UnsetGlobals();
}
diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp
index 05f910e9cb..cdc5960c12 100644
--- a/src/bitcoin-tx.cpp
+++ b/src/bitcoin-tx.cpp
@@ -240,7 +240,7 @@ static void MutateTxRBFOptIn(CMutableTransaction& tx, const std::string& strInId
template <typename T>
static T TrimAndParse(const std::string& int_str, const std::string& err)
{
- const auto parsed{ToIntegral<T>(TrimString(int_str))};
+ const auto parsed{ToIntegral<T>(TrimStringView(int_str))};
if (!parsed.has_value()) {
throw std::runtime_error(err + " '" + int_str + "'");
}
diff --git a/src/compat/byteswap.h b/src/compat/byteswap.h
index 27ef1a18df..2f4232fa5c 100644
--- a/src/compat/byteswap.h
+++ b/src/compat/byteswap.h
@@ -9,7 +9,7 @@
#include <config/bitcoin-config.h>
#endif
-#include <stdint.h>
+#include <cstdint>
#if defined(HAVE_BYTESWAP_H)
#include <byteswap.h>
diff --git a/src/compat/cpuid.h b/src/compat/cpuid.h
index 0877ad47d3..e78c1ce6d1 100644
--- a/src/compat/cpuid.h
+++ b/src/compat/cpuid.h
@@ -10,6 +10,8 @@
#include <cpuid.h>
+#include <cstdint>
+
// We can't use cpuid.h's __get_cpuid as it does not support subleafs.
void static inline GetCPUID(uint32_t leaf, uint32_t subleaf, uint32_t& a, uint32_t& b, uint32_t& c, uint32_t& d)
{
diff --git a/src/compat/endian.h b/src/compat/endian.h
index c5cf7a46cc..bdd8b84c1b 100644
--- a/src/compat/endian.h
+++ b/src/compat/endian.h
@@ -11,7 +11,7 @@
#include <compat/byteswap.h>
-#include <stdint.h>
+#include <cstdint>
#if defined(HAVE_ENDIAN_H)
#include <endian.h>
diff --git a/src/compat/glibcxx_sanity.cpp b/src/compat/glibcxx_sanity.cpp
index e6e6208e40..f2ceeeeb9c 100644
--- a/src/compat/glibcxx_sanity.cpp
+++ b/src/compat/glibcxx_sanity.cpp
@@ -5,6 +5,7 @@
#include <list>
#include <locale>
#include <stdexcept>
+#include <string>
namespace
{
diff --git a/src/compat/stdin.cpp b/src/compat/stdin.cpp
index 0fc4e0fcf2..61d66e39f2 100644
--- a/src/compat/stdin.cpp
+++ b/src/compat/stdin.cpp
@@ -2,23 +2,19 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#if defined(HAVE_CONFIG_H)
-#include <config/bitcoin-config.h>
-#endif
+#include <compat/stdin.h>
-#include <cstdio> // for fileno(), stdin
+#include <cstdio>
#ifdef WIN32
-#include <windows.h> // for SetStdinEcho()
-#include <io.h> // for isatty()
+#include <windows.h>
+#include <io.h>
#else
-#include <termios.h> // for SetStdinEcho()
-#include <unistd.h> // for SetStdinEcho(), isatty()
-#include <poll.h> // for StdinReady()
+#include <termios.h>
+#include <unistd.h>
+#include <poll.h>
#endif
-#include <compat/stdin.h>
-
// https://stackoverflow.com/questions/1413445/reading-a-password-from-stdcin
void SetStdinEcho(bool enable)
{
diff --git a/src/dummywallet.cpp b/src/dummywallet.cpp
index 2b94ed611b..028c6ebae1 100644
--- a/src/dummywallet.cpp
+++ b/src/dummywallet.cpp
@@ -50,6 +50,7 @@ void DummyWalletInit::AddWalletOptions(ArgsManager& argsman) const
"-flushwallet",
"-privdb",
"-walletrejectlongchains",
+ "-walletcrosschain",
"-unsafesqlitesync",
});
}
diff --git a/src/httprpc.cpp b/src/httprpc.cpp
index 5d0b59f7cb..93d9acf5da 100644
--- a/src/httprpc.cpp
+++ b/src/httprpc.cpp
@@ -131,8 +131,11 @@ static bool RPCAuthorized(const std::string& strAuth, std::string& strAuthUserna
return false;
if (strAuth.substr(0, 6) != "Basic ")
return false;
- std::string strUserPass64 = TrimString(strAuth.substr(6));
- std::string strUserPass = DecodeBase64(strUserPass64);
+ std::string_view strUserPass64 = TrimStringView(std::string_view{strAuth}.substr(6));
+ auto userpass_data = DecodeBase64(strUserPass64);
+ std::string strUserPass;
+ if (!userpass_data) return false;
+ strUserPass.assign(userpass_data->begin(), userpass_data->end());
if (strUserPass.find(':') != std::string::npos)
strAuthUsernameOut = strUserPass.substr(0, strUserPass.find(':'));
diff --git a/src/i2p.cpp b/src/i2p.cpp
index ccba14d63d..e08b5461fe 100644
--- a/src/i2p.cpp
+++ b/src/i2p.cpp
@@ -69,12 +69,11 @@ static std::string SwapBase64(const std::string& from)
static Binary DecodeI2PBase64(const std::string& i2p_b64)
{
const std::string& std_b64 = SwapBase64(i2p_b64);
- bool invalid;
- Binary decoded = DecodeBase64(std_b64.c_str(), &invalid);
- if (invalid) {
+ auto decoded = DecodeBase64(std_b64);
+ if (!decoded) {
throw std::runtime_error(strprintf("Cannot decode Base64: \"%s\"", i2p_b64));
}
- return decoded;
+ return std::move(*decoded);
}
/**
diff --git a/src/init.cpp b/src/init.cpp
index cccb088eec..fdcb2b8ac7 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -73,6 +73,7 @@
#include <validationinterface.h>
#include <walletinitinterface.h>
+#include <algorithm>
#include <condition_variable>
#include <cstdint>
#include <cstdio>
@@ -1288,19 +1289,6 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
// as they would never get updated.
if (!ignores_incoming_txs) node.fee_estimator = std::make_unique<CBlockPolicyEstimator>();
- assert(!node.mempool);
- int check_ratio = std::min<int>(std::max<int>(args.GetIntArg("-checkmempool", chainparams.DefaultConsistencyChecks() ? 1 : 0), 0), 1000000);
- node.mempool = std::make_unique<CTxMemPool>(node.fee_estimator.get(), check_ratio);
-
- assert(!node.chainman);
- node.chainman = std::make_unique<ChainstateManager>();
- ChainstateManager& chainman = *node.chainman;
-
- assert(!node.peerman);
- node.peerman = PeerManager::make(chainparams, *node.connman, *node.addrman, node.banman.get(),
- chainman, *node.mempool, ignores_incoming_txs);
- RegisterValidationInterface(node.peerman.get());
-
// sanitize comments per BIP-0014, format user agent and check total size
std::vector<std::string> uacomments;
for (const std::string& cmt : args.GetArgs("-uacomment")) {
@@ -1429,8 +1417,16 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
LogPrintf("* Using %.1f MiB for chain state database\n", cache_sizes.coins_db * (1.0 / 1024 / 1024));
LogPrintf("* Using %.1f MiB for in-memory UTXO set (plus up to %.1f MiB of unused mempool space)\n", cache_sizes.coins * (1.0 / 1024 / 1024), nMempoolSizeMax * (1.0 / 1024 / 1024));
- bool fLoaded = false;
- while (!fLoaded && !ShutdownRequested()) {
+ assert(!node.mempool);
+ assert(!node.chainman);
+ const int mempool_check_ratio = std::clamp<int>(args.GetIntArg("-checkmempool", chainparams.DefaultConsistencyChecks() ? 1 : 0), 0, 1000000);
+
+ for (bool fLoaded = false; !fLoaded && !ShutdownRequested();) {
+ node.mempool = std::make_unique<CTxMemPool>(node.fee_estimator.get(), mempool_check_ratio);
+
+ node.chainman = std::make_unique<ChainstateManager>();
+ ChainstateManager& chainman = *node.chainman;
+
const bool fReset = fReindex;
bilingual_str strLoadError;
@@ -1562,6 +1558,13 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
return false;
}
+ ChainstateManager& chainman = *Assert(node.chainman);
+
+ assert(!node.peerman);
+ node.peerman = PeerManager::make(chainparams, *node.connman, *node.addrman, node.banman.get(),
+ chainman, *node.mempool, ignores_incoming_txs);
+ RegisterValidationInterface(node.peerman.get());
+
// ********************************************************* Step 8: start indexers
if (args.GetBoolArg("-txindex", DEFAULT_TXINDEX)) {
if (const auto error{WITH_LOCK(cs_main, return CheckLegacyTxindex(*Assert(chainman.m_blockman.m_block_tree_db)))}) {
diff --git a/src/init/bitcoin-gui.cpp b/src/init/bitcoin-gui.cpp
index e297b48718..2fa4add4e5 100644
--- a/src/init/bitcoin-gui.cpp
+++ b/src/init/bitcoin-gui.cpp
@@ -9,6 +9,7 @@
#include <interfaces/node.h>
#include <interfaces/wallet.h>
#include <node/context.h>
+#include <util/check.h>
#include <util/system.h>
#include <memory>
diff --git a/src/init/bitcoin-node.cpp b/src/init/bitcoin-node.cpp
index 511a872bc0..78bc3e5980 100644
--- a/src/init/bitcoin-node.cpp
+++ b/src/init/bitcoin-node.cpp
@@ -9,6 +9,7 @@
#include <interfaces/node.h>
#include <interfaces/wallet.h>
#include <node/context.h>
+#include <util/check.h>
#include <util/system.h>
#include <memory>
diff --git a/src/init/bitcoin-qt.cpp b/src/init/bitcoin-qt.cpp
index 37d4e426c5..bb3bb945d0 100644
--- a/src/init/bitcoin-qt.cpp
+++ b/src/init/bitcoin-qt.cpp
@@ -8,6 +8,7 @@
#include <interfaces/node.h>
#include <interfaces/wallet.h>
#include <node/context.h>
+#include <util/check.h>
#include <util/system.h>
#include <memory>
diff --git a/src/init/bitcoin-wallet.cpp b/src/init/bitcoin-wallet.cpp
index e9dcde72fe..c8d499da10 100644
--- a/src/init/bitcoin-wallet.cpp
+++ b/src/init/bitcoin-wallet.cpp
@@ -4,6 +4,8 @@
#include <interfaces/init.h>
+#include <memory>
+
namespace interfaces {
std::unique_ptr<Init> MakeWalletInit(int argc, char* argv[], int& exit_status)
{
diff --git a/src/init/bitcoind.cpp b/src/init/bitcoind.cpp
index 2addff07c1..b473ebb805 100644
--- a/src/init/bitcoind.cpp
+++ b/src/init/bitcoind.cpp
@@ -8,6 +8,7 @@
#include <interfaces/node.h>
#include <interfaces/wallet.h>
#include <node/context.h>
+#include <util/check.h>
#include <util/system.h>
#include <memory>
diff --git a/src/init/common.cpp b/src/init/common.cpp
index 688471b35d..eac6732968 100644
--- a/src/init/common.cpp
+++ b/src/init/common.cpp
@@ -9,16 +9,21 @@
#include <clientversion.h>
#include <compat/sanity.h>
#include <crypto/sha256.h>
+#include <fs.h>
#include <key.h>
#include <logging.h>
#include <node/ui_interface.h>
#include <pubkey.h>
#include <random.h>
+#include <tinyformat.h>
#include <util/system.h>
#include <util/time.h>
#include <util/translation.h>
+#include <algorithm>
#include <memory>
+#include <string>
+#include <vector>
static std::unique_ptr<ECCVerifyHandle> globalVerifyHandle;
diff --git a/src/kernel/bitcoinkernel.cpp b/src/kernel/bitcoinkernel.cpp
new file mode 100644
index 0000000000..bb101ba186
--- /dev/null
+++ b/src/kernel/bitcoinkernel.cpp
@@ -0,0 +1,10 @@
+// Copyright (c) 2022 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 <functional>
+#include <string>
+
+// Define G_TRANSLATION_FUN symbol in libbitcoinkernel library so users of the
+// library aren't required to export this symbol
+extern const std::function<std::string(const char*)> G_TRANSLATION_FUN = nullptr;
diff --git a/src/net_processing.cpp b/src/net_processing.cpp
index 46b4d2e3df..e9e6544069 100644
--- a/src/net_processing.cpp
+++ b/src/net_processing.cpp
@@ -135,6 +135,8 @@ static const unsigned int NODE_NETWORK_LIMITED_MIN_BLOCKS = 288;
static constexpr auto AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL{24h};
/** Average delay between peer address broadcasts */
static constexpr auto AVG_ADDRESS_BROADCAST_INTERVAL{30s};
+/** Delay between rotating the peers we relay a particular address to */
+static constexpr auto ROTATE_ADDR_RELAY_DEST_INTERVAL{24h};
/** Average delay between trickled inventory transmissions for inbound peers.
* Blocks and peers with NetPermissionFlags::NoBan permission bypass this. */
static constexpr auto INBOUND_INVENTORY_BROADCAST_INTERVAL{5s};
@@ -1818,9 +1820,12 @@ void PeerManagerImpl::RelayAddress(NodeId originator,
// Use deterministic randomness to send to the same nodes for 24 hours
// at a time so the m_addr_knowns of the chosen nodes prevent repeats
const uint64_t hash_addr{CServiceHash(0, 0)(addr)};
+ const auto current_time{GetTime<std::chrono::seconds>()};
+ // Adding address hash makes exact rotation time different per address, while preserving periodicity.
+ const uint64_t time_addr{(static_cast<uint64_t>(count_seconds(current_time)) + hash_addr) / count_seconds(ROTATE_ADDR_RELAY_DEST_INTERVAL)};
const CSipHasher hasher{m_connman.GetDeterministicRandomizer(RANDOMIZER_ID_ADDRESS_RELAY)
.Write(hash_addr)
- .Write((GetTime() + hash_addr) / (24 * 60 * 60))};
+ .Write(time_addr)};
FastRandomContext insecure_rand;
// Relay reachable addresses to 2 peers. Unreachable addresses are relayed randomly to 1 or 2 peers.
diff --git a/src/netaddress.cpp b/src/netaddress.cpp
index bc1915aad9..7bf11a3e48 100644
--- a/src/netaddress.cpp
+++ b/src/netaddress.cpp
@@ -210,7 +210,7 @@ static void Checksum(Span<const uint8_t> addr_pubkey, uint8_t (&checksum)[CHECKS
bool CNetAddr::SetSpecial(const std::string& addr)
{
- if (!ValidAsCString(addr)) {
+ if (!ContainsNoNUL(addr)) {
return false;
}
@@ -234,17 +234,16 @@ bool CNetAddr::SetTor(const std::string& addr)
return false;
}
- bool invalid;
- const auto& input = DecodeBase32(addr.substr(0, addr.size() - suffix_len).c_str(), &invalid);
+ auto input = DecodeBase32(std::string_view{addr}.substr(0, addr.size() - suffix_len));
- if (invalid) {
+ if (!input) {
return false;
}
- if (input.size() == torv3::TOTAL_LEN) {
- Span<const uint8_t> input_pubkey{input.data(), ADDR_TORV3_SIZE};
- Span<const uint8_t> input_checksum{input.data() + ADDR_TORV3_SIZE, torv3::CHECKSUM_LEN};
- Span<const uint8_t> input_version{input.data() + ADDR_TORV3_SIZE + torv3::CHECKSUM_LEN, sizeof(torv3::VERSION)};
+ if (input->size() == torv3::TOTAL_LEN) {
+ Span<const uint8_t> input_pubkey{input->data(), ADDR_TORV3_SIZE};
+ Span<const uint8_t> input_checksum{input->data() + ADDR_TORV3_SIZE, torv3::CHECKSUM_LEN};
+ Span<const uint8_t> input_version{input->data() + ADDR_TORV3_SIZE + torv3::CHECKSUM_LEN, sizeof(torv3::VERSION)};
if (input_version != torv3::VERSION) {
return false;
@@ -280,15 +279,14 @@ bool CNetAddr::SetI2P(const std::string& addr)
// can decode it.
const std::string b32_padded = addr.substr(0, b32_len) + "====";
- bool invalid;
- const auto& address_bytes = DecodeBase32(b32_padded.c_str(), &invalid);
+ auto address_bytes = DecodeBase32(b32_padded);
- if (invalid || address_bytes.size() != ADDR_I2P_SIZE) {
+ if (!address_bytes || address_bytes->size() != ADDR_I2P_SIZE) {
return false;
}
m_net = NET_I2P;
- m_addr.assign(address_bytes.begin(), address_bytes.end());
+ m_addr.assign(address_bytes->begin(), address_bytes->end());
return true;
}
diff --git a/src/netbase.cpp b/src/netbase.cpp
index ce23f7e4ad..8ff3b7a68c 100644
--- a/src/netbase.cpp
+++ b/src/netbase.cpp
@@ -136,7 +136,7 @@ static bool LookupIntern(const std::string& name, std::vector<CNetAddr>& vIP, un
{
vIP.clear();
- if (!ValidAsCString(name)) {
+ if (!ContainsNoNUL(name)) {
return false;
}
@@ -169,7 +169,7 @@ static bool LookupIntern(const std::string& name, std::vector<CNetAddr>& vIP, un
bool LookupHost(const std::string& name, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions, bool fAllowLookup, DNSLookupFn dns_lookup_function)
{
- if (!ValidAsCString(name)) {
+ if (!ContainsNoNUL(name)) {
return false;
}
std::string strHost = name;
@@ -184,7 +184,7 @@ bool LookupHost(const std::string& name, std::vector<CNetAddr>& vIP, unsigned in
bool LookupHost(const std::string& name, CNetAddr& addr, bool fAllowLookup, DNSLookupFn dns_lookup_function)
{
- if (!ValidAsCString(name)) {
+ if (!ContainsNoNUL(name)) {
return false;
}
std::vector<CNetAddr> vIP;
@@ -197,7 +197,7 @@ bool LookupHost(const std::string& name, CNetAddr& addr, bool fAllowLookup, DNSL
bool Lookup(const std::string& name, std::vector<CService>& vAddr, uint16_t portDefault, bool fAllowLookup, unsigned int nMaxSolutions, DNSLookupFn dns_lookup_function)
{
- if (name.empty() || !ValidAsCString(name)) {
+ if (name.empty() || !ContainsNoNUL(name)) {
return false;
}
uint16_t port{portDefault};
@@ -216,7 +216,7 @@ bool Lookup(const std::string& name, std::vector<CService>& vAddr, uint16_t port
bool Lookup(const std::string& name, CService& addr, uint16_t portDefault, bool fAllowLookup, DNSLookupFn dns_lookup_function)
{
- if (!ValidAsCString(name)) {
+ if (!ContainsNoNUL(name)) {
return false;
}
std::vector<CService> vService;
@@ -229,7 +229,7 @@ bool Lookup(const std::string& name, CService& addr, uint16_t portDefault, bool
CService LookupNumeric(const std::string& name, uint16_t portDefault, DNSLookupFn dns_lookup_function)
{
- if (!ValidAsCString(name)) {
+ if (!ContainsNoNUL(name)) {
return {};
}
CService addr;
@@ -684,7 +684,7 @@ bool ConnectThroughProxy(const Proxy& proxy, const std::string& strDest, uint16_
bool LookupSubNet(const std::string& subnet_str, CSubNet& subnet_out)
{
- if (!ValidAsCString(subnet_str)) {
+ if (!ContainsNoNUL(subnet_str)) {
return false;
}
diff --git a/src/node/blockstorage.cpp b/src/node/blockstorage.cpp
index 8ed22bbbce..25771aacee 100644
--- a/src/node/blockstorage.cpp
+++ b/src/node/blockstorage.cpp
@@ -297,20 +297,6 @@ bool BlockManager::LoadBlockIndex(const Consensus::Params& consensus_params)
return true;
}
-void BlockManager::Unload()
-{
- m_blocks_unlinked.clear();
-
- m_block_index.clear();
-
- m_blockfile_info.clear();
- m_last_blockfile = 0;
- m_dirty_blockindex.clear();
- m_dirty_fileinfo.clear();
-
- m_have_pruned = false;
-}
-
bool BlockManager::WriteBlockIndexDB()
{
AssertLockHeld(::cs_main);
diff --git a/src/node/blockstorage.h b/src/node/blockstorage.h
index e4b9657372..622eac7fef 100644
--- a/src/node/blockstorage.h
+++ b/src/node/blockstorage.h
@@ -154,9 +154,6 @@ public:
bool WriteBlockIndexDB() EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
bool LoadBlockIndexDB() EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
- /** Clear all data members. */
- void Unload() EXCLUSIVE_LOCKS_REQUIRED(cs_main);
-
CBlockIndex* AddToBlockIndex(const CBlockHeader& block, CBlockIndex*& best_header) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
/** Create a new block index entry for a given block hash */
CBlockIndex* InsertBlockIndex(const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
@@ -189,11 +186,6 @@ public:
//! Create or update a prune lock identified by its name
void UpdatePruneLock(const std::string& name, const PruneLockInfo& lock_info) EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
-
- ~BlockManager()
- {
- Unload();
- }
};
//! Find the first block that is not pruned
diff --git a/src/node/chainstate.cpp b/src/node/chainstate.cpp
index e43211402c..99615dea69 100644
--- a/src/node/chainstate.cpp
+++ b/src/node/chainstate.cpp
@@ -32,8 +32,6 @@ std::optional<ChainstateLoadingError> LoadChainstate(bool fReset,
chainman.m_total_coinstip_cache = nCoinCacheUsage;
chainman.m_total_coinsdb_cache = nCoinDBCache;
- UnloadBlockIndex(mempool, chainman);
-
auto& pblocktree{chainman.m_blockman.m_block_tree_db};
// new CBlockTreeDB tries to delete the existing file, which
// fails if it's still open from the previous loop. Close it first:
diff --git a/src/psbt.cpp b/src/psbt.cpp
index c8c73e130b..6465e353be 100644
--- a/src/psbt.cpp
+++ b/src/psbt.cpp
@@ -388,18 +388,17 @@ std::string PSBTRoleName(PSBTRole role) {
bool DecodeBase64PSBT(PartiallySignedTransaction& psbt, const std::string& base64_tx, std::string& error)
{
- bool invalid;
- std::string tx_data = DecodeBase64(base64_tx, &invalid);
- if (invalid) {
+ auto tx_data = DecodeBase64(base64_tx);
+ if (!tx_data) {
error = "invalid base64";
return false;
}
- return DecodeRawPSBT(psbt, tx_data, error);
+ return DecodeRawPSBT(psbt, MakeByteSpan(*tx_data), error);
}
-bool DecodeRawPSBT(PartiallySignedTransaction& psbt, const std::string& tx_data, std::string& error)
+bool DecodeRawPSBT(PartiallySignedTransaction& psbt, Span<const std::byte> tx_data, std::string& error)
{
- CDataStream ss_data(MakeByteSpan(tx_data), SER_NETWORK, PROTOCOL_VERSION);
+ CDataStream ss_data(tx_data, SER_NETWORK, PROTOCOL_VERSION);
try {
ss_data >> psbt;
if (!ss_data.empty()) {
diff --git a/src/psbt.h b/src/psbt.h
index f0ceb02481..8a9cbd33d2 100644
--- a/src/psbt.h
+++ b/src/psbt.h
@@ -988,6 +988,6 @@ bool FinalizeAndExtractPSBT(PartiallySignedTransaction& psbtx, CMutableTransacti
//! Decode a base64ed PSBT into a PartiallySignedTransaction
[[nodiscard]] bool DecodeBase64PSBT(PartiallySignedTransaction& decoded_psbt, const std::string& base64_psbt, std::string& error);
//! Decode a raw (binary blob) PSBT into a PartiallySignedTransaction
-[[nodiscard]] bool DecodeRawPSBT(PartiallySignedTransaction& decoded_psbt, const std::string& raw_psbt, std::string& error);
+[[nodiscard]] bool DecodeRawPSBT(PartiallySignedTransaction& decoded_psbt, Span<const std::byte> raw_psbt, std::string& error);
#endif // BITCOIN_PSBT_H
diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp
index eb69fabe89..4a51990f88 100644
--- a/src/qt/rpcconsole.cpp
+++ b/src/qt/rpcconsole.cpp
@@ -1032,8 +1032,9 @@ void RPCConsole::on_lineEdit_returnPressed()
ui->lineEdit->clear();
+ WalletModel* wallet_model{nullptr};
#ifdef ENABLE_WALLET
- WalletModel* wallet_model = ui->WalletSelector->currentData().value<WalletModel*>();
+ wallet_model = ui->WalletSelector->currentData().value<WalletModel*>();
if (m_last_wallet_model != wallet_model) {
if (wallet_model) {
@@ -1049,7 +1050,10 @@ void RPCConsole::on_lineEdit_returnPressed()
//: A console message indicating an entered command is currently being executed.
message(CMD_REPLY, tr("Executing…"));
m_is_executing = true;
- Q_EMIT cmdRequest(cmd, m_last_wallet_model);
+
+ QMetaObject::invokeMethod(m_executor, [this, cmd, wallet_model] {
+ m_executor->request(cmd, wallet_model);
+ });
cmd = QString::fromStdString(strFilteredCmd);
@@ -1091,11 +1095,11 @@ void RPCConsole::browseHistory(int offset)
void RPCConsole::startExecutor()
{
- RPCExecutor *executor = new RPCExecutor(m_node);
- executor->moveToThread(&thread);
+ m_executor = new RPCExecutor(m_node);
+ m_executor->moveToThread(&thread);
// Replies from executor object must go to this object
- connect(executor, &RPCExecutor::reply, this, [this](int category, const QString& command) {
+ connect(m_executor, &RPCExecutor::reply, this, [this](int category, const QString& command) {
// Remove "Executing…" message.
ui->messagesWidget->undo();
message(category, command);
@@ -1103,16 +1107,13 @@ void RPCConsole::startExecutor()
m_is_executing = false;
});
- // Requests from this object must go to executor
- connect(this, &RPCConsole::cmdRequest, executor, &RPCExecutor::request);
-
// Make sure executor object is deleted in its own thread
- connect(&thread, &QThread::finished, executor, &RPCExecutor::deleteLater);
+ connect(&thread, &QThread::finished, m_executor, &RPCExecutor::deleteLater);
// Default implementation of QThread::run() simply spins up an event loop in the thread,
// which is what we want.
thread.start();
- QTimer::singleShot(0, executor, []() {
+ QTimer::singleShot(0, m_executor, []() {
util::ThreadRename("qt-rpcconsole");
});
}
diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h
index 528e2bef7d..1a54fe0cad 100644
--- a/src/qt/rpcconsole.h
+++ b/src/qt/rpcconsole.h
@@ -5,6 +5,10 @@
#ifndef BITCOIN_QT_RPCCONSOLE_H
#define BITCOIN_QT_RPCCONSOLE_H
+#if defined(HAVE_CONFIG_H)
+#include <config/bitcoin-config.h>
+#endif
+
#include <qt/guiutil.h>
#include <qt/peertablemodel.h>
@@ -17,6 +21,7 @@
class ClientModel;
class PlatformStyle;
+class RPCExecutor;
class RPCTimerInterface;
class WalletModel;
@@ -49,8 +54,11 @@ public:
}
void setClientModel(ClientModel *model = nullptr, int bestblock_height = 0, int64_t bestblock_date = 0, double verification_progress = 0.0);
- void addWallet(WalletModel * const walletModel);
+
+#ifdef ENABLE_WALLET
+ void addWallet(WalletModel* const walletModel);
void removeWallet(WalletModel* const walletModel);
+#endif // ENABLE_WALLET
enum MessageClass {
MC_ERROR,
@@ -129,10 +137,6 @@ public Q_SLOTS:
/** set which tab has the focus (is visible) */
void setTabFocus(enum TabTypes tabType);
-Q_SIGNALS:
- // For RPC command executor
- void cmdRequest(const QString &command, const WalletModel* wallet_model);
-
private:
struct TranslatedStrings {
const QString yes{tr("Yes")}, no{tr("No")}, to{tr("To")}, from{tr("From")},
@@ -166,6 +170,7 @@ private:
int consoleFontSize = 0;
QCompleter *autoCompleter = nullptr;
QThread thread;
+ RPCExecutor* m_executor{nullptr};
WalletModel* m_last_wallet_model{nullptr};
bool m_is_executing{false};
QByteArray m_peer_widget_header_state;
diff --git a/src/qt/walletframe.cpp b/src/qt/walletframe.cpp
index 91ce420a33..dc4e25a02b 100644
--- a/src/qt/walletframe.cpp
+++ b/src/qt/walletframe.cpp
@@ -194,16 +194,16 @@ void WalletFrame::gotoVerifyMessageTab(QString addr)
void WalletFrame::gotoLoadPSBT(bool from_clipboard)
{
- std::string data;
+ std::vector<unsigned char> data;
if (from_clipboard) {
std::string raw = QApplication::clipboard()->text().toStdString();
- bool invalid;
- data = DecodeBase64(raw, &invalid);
- if (invalid) {
+ auto result = DecodeBase64(raw);
+ if (!result) {
Q_EMIT message(tr("Error"), tr("Unable to decode PSBT from clipboard (invalid base64)"), CClientUIInterface::MSG_ERROR);
return;
}
+ data = std::move(*result);
} else {
QString filename = GUIUtil::getOpenFileName(this,
tr("Load Transaction Data"), QString(),
@@ -214,12 +214,12 @@ void WalletFrame::gotoLoadPSBT(bool from_clipboard)
return;
}
std::ifstream in{filename.toLocal8Bit().data(), std::ios::binary};
- data = std::string(std::istreambuf_iterator<char>{in}, {});
+ data.assign(std::istream_iterator<unsigned char>{in}, {});
}
std::string error;
PartiallySignedTransaction psbtx;
- if (!DecodeRawPSBT(psbtx, data, error)) {
+ if (!DecodeRawPSBT(psbtx, MakeByteSpan(data), error)) {
Q_EMIT message(tr("Error"), tr("Unable to decode PSBT") + "\n" + QString::fromStdString(error), CClientUIInterface::MSG_ERROR);
return;
}
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index 398b948388..96e9efb288 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -1199,24 +1199,23 @@ RPCHelpMan getblockchaininfo()
LOCK(cs_main);
CChainState& active_chainstate = chainman.ActiveChainstate();
- const CBlockIndex* tip = CHECK_NONFATAL(active_chainstate.m_chain.Tip());
- const int height = tip->nHeight;
+ const CBlockIndex& tip{*CHECK_NONFATAL(active_chainstate.m_chain.Tip())};
+ const int height{tip.nHeight};
UniValue obj(UniValue::VOBJ);
obj.pushKV("chain", Params().NetworkIDString());
obj.pushKV("blocks", height);
obj.pushKV("headers", chainman.m_best_header ? chainman.m_best_header->nHeight : -1);
- obj.pushKV("bestblockhash", tip->GetBlockHash().GetHex());
- obj.pushKV("difficulty", (double)GetDifficulty(tip));
- obj.pushKV("time", (int64_t)tip->nTime);
- obj.pushKV("mediantime", (int64_t)tip->GetMedianTimePast());
- obj.pushKV("verificationprogress", GuessVerificationProgress(Params().TxData(), tip));
+ obj.pushKV("bestblockhash", tip.GetBlockHash().GetHex());
+ obj.pushKV("difficulty", GetDifficulty(&tip));
+ obj.pushKV("time", int64_t{tip.nTime});
+ obj.pushKV("mediantime", tip.GetMedianTimePast());
+ obj.pushKV("verificationprogress", GuessVerificationProgress(Params().TxData(), &tip));
obj.pushKV("initialblockdownload", active_chainstate.IsInitialBlockDownload());
- obj.pushKV("chainwork", tip->nChainWork.GetHex());
+ obj.pushKV("chainwork", tip.nChainWork.GetHex());
obj.pushKV("size_on_disk", chainman.m_blockman.CalculateCurrentUsage());
obj.pushKV("pruned", node::fPruneMode);
if (node::fPruneMode) {
- const CBlockIndex* block = CHECK_NONFATAL(tip);
- obj.pushKV("pruneheight", node::GetFirstStoredBlock(block)->nHeight);
+ obj.pushKV("pruneheight", node::GetFirstStoredBlock(&tip)->nHeight);
// if 0, execution bypasses the whole if block.
bool automatic_pruning{args.GetIntArg("-prune", 0) != 1};
@@ -1228,7 +1227,7 @@ RPCHelpMan getblockchaininfo()
if (IsDeprecatedRPCEnabled("softforks")) {
const Consensus::Params& consensusParams = Params().GetConsensus();
- obj.pushKV("softforks", DeploymentInfo(tip, consensusParams));
+ obj.pushKV("softforks", DeploymentInfo(&tip, consensusParams));
}
obj.pushKV("warnings", GetWarnings(false).original);
diff --git a/src/test/base32_tests.cpp b/src/test/base32_tests.cpp
index 5fab7f0d1e..c6109dfeb0 100644
--- a/src/test/base32_tests.cpp
+++ b/src/test/base32_tests.cpp
@@ -22,20 +22,16 @@ BOOST_AUTO_TEST_CASE(base32_testvectors)
BOOST_CHECK_EQUAL(strEnc, vstrOut[i]);
strEnc = EncodeBase32(vstrIn[i], false);
BOOST_CHECK_EQUAL(strEnc, vstrOutNoPadding[i]);
- std::string strDec = DecodeBase32(vstrOut[i]);
- BOOST_CHECK_EQUAL(strDec, vstrIn[i]);
+ auto dec = DecodeBase32(vstrOut[i]);
+ BOOST_REQUIRE(dec);
+ BOOST_CHECK_MESSAGE(MakeByteSpan(*dec) == MakeByteSpan(vstrIn[i]), vstrOut[i]);
}
// Decoding strings with embedded NUL characters should fail
- bool failure;
- (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_CHECK(!DecodeBase32("invalid\0"s)); // correct size, invalid due to \0
+ BOOST_CHECK(DecodeBase32("AWSX3VPP"s)); // valid
+ BOOST_CHECK(!DecodeBase32("AWSX3VPP\0invalid"s)); // correct size, invalid due to \0
+ BOOST_CHECK(!DecodeBase32("AWSX3VPPinvalid"s)); // invalid size
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/base64_tests.cpp b/src/test/base64_tests.cpp
index 6ee1b83691..54a02c6bf8 100644
--- a/src/test/base64_tests.cpp
+++ b/src/test/base64_tests.cpp
@@ -19,8 +19,9 @@ BOOST_AUTO_TEST_CASE(base64_testvectors)
{
std::string strEnc = EncodeBase64(vstrIn[i]);
BOOST_CHECK_EQUAL(strEnc, vstrOut[i]);
- std::string strDec = DecodeBase64(strEnc);
- BOOST_CHECK_EQUAL(strDec, vstrIn[i]);
+ auto dec = DecodeBase64(strEnc);
+ BOOST_REQUIRE(dec);
+ BOOST_CHECK_MESSAGE(MakeByteSpan(*dec) == MakeByteSpan(vstrIn[i]), vstrOut[i]);
}
{
@@ -34,15 +35,10 @@ BOOST_AUTO_TEST_CASE(base64_testvectors)
}
// Decoding strings with embedded NUL characters should fail
- bool failure;
- (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_CHECK(!DecodeBase64("invalid\0"s));
+ BOOST_CHECK(DecodeBase64("nQB/pZw="s));
+ BOOST_CHECK(!DecodeBase64("nQB/pZw=\0invalid"s));
+ BOOST_CHECK(!DecodeBase64("nQB/pZw=invalid\0"s));
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/fuzz/base_encode_decode.cpp b/src/test/fuzz/base_encode_decode.cpp
index 196410e29c..48356065b0 100644
--- a/src/test/fuzz/base_encode_decode.cpp
+++ b/src/test/fuzz/base_encode_decode.cpp
@@ -26,7 +26,7 @@ FUZZ_TARGET_INIT(base_encode_decode, initialize_base_encode_decode)
std::vector<unsigned char> decoded;
if (DecodeBase58(random_encoded_string, decoded, 100)) {
const std::string encoded_string = EncodeBase58(decoded);
- assert(encoded_string == TrimString(encoded_string));
+ assert(encoded_string == TrimStringView(encoded_string));
assert(ToLower(encoded_string) == ToLower(TrimString(random_encoded_string)));
}
@@ -36,17 +36,16 @@ FUZZ_TARGET_INIT(base_encode_decode, initialize_base_encode_decode)
assert(ToLower(encoded_string) == ToLower(TrimString(random_encoded_string)));
}
- bool pf_invalid;
- std::string decoded_string = DecodeBase32(random_encoded_string, &pf_invalid);
- if (!pf_invalid) {
- const std::string encoded_string = EncodeBase32(decoded_string);
- assert(encoded_string == TrimString(encoded_string));
+ auto result = DecodeBase32(random_encoded_string);
+ if (result) {
+ const std::string encoded_string = EncodeBase32(*result);
+ assert(encoded_string == TrimStringView(encoded_string));
assert(ToLower(encoded_string) == ToLower(TrimString(random_encoded_string)));
}
- decoded_string = DecodeBase64(random_encoded_string, &pf_invalid);
- if (!pf_invalid) {
- const std::string encoded_string = EncodeBase64(decoded_string);
+ result = DecodeBase64(random_encoded_string);
+ if (result) {
+ const std::string encoded_string = EncodeBase64(*result);
assert(encoded_string == TrimString(encoded_string));
assert(ToLower(encoded_string) == ToLower(TrimString(random_encoded_string)));
}
diff --git a/src/test/fuzz/http_request.cpp b/src/test/fuzz/http_request.cpp
index 916e90e986..0fe18abaa9 100644
--- a/src/test/fuzz/http_request.cpp
+++ b/src/test/fuzz/http_request.cpp
@@ -39,7 +39,7 @@ FUZZ_TARGET(http_request)
// and is a consequence of our hacky but necessary use of the internal function evhttp_parse_firstline_ in
// this fuzzing harness. The workaround is not aesthetically pleasing, but it successfully avoids the troublesome
// code path. " http:// HTTP/1.1\n" was a crashing input prior to this workaround.
- const std::string http_buffer_str = ToLower({http_buffer.begin(), http_buffer.end()});
+ const std::string http_buffer_str = ToLower(std::string{http_buffer.begin(), http_buffer.end()});
if (http_buffer_str.find(" http://") != std::string::npos || http_buffer_str.find(" https://") != std::string::npos ||
evhttp_parse_firstline_(evreq, evbuf) != 1 || evhttp_parse_headers_(evreq, evbuf) != 1) {
evbuffer_free(evbuf);
diff --git a/src/test/fuzz/psbt.cpp b/src/test/fuzz/psbt.cpp
index 669688a80d..baa64bba0f 100644
--- a/src/test/fuzz/psbt.cpp
+++ b/src/test/fuzz/psbt.cpp
@@ -32,7 +32,8 @@ FUZZ_TARGET_INIT(psbt, initialize_psbt)
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
PartiallySignedTransaction psbt_mut;
std::string error;
- if (!DecodeRawPSBT(psbt_mut, fuzzed_data_provider.ConsumeRandomLengthString(), error)) {
+ auto str = fuzzed_data_provider.ConsumeRandomLengthString();
+ if (!DecodeRawPSBT(psbt_mut, MakeByteSpan(str), error)) {
return;
}
const PartiallySignedTransaction psbt = psbt_mut;
@@ -79,7 +80,8 @@ FUZZ_TARGET_INIT(psbt, initialize_psbt)
}
PartiallySignedTransaction psbt_merge;
- if (!DecodeRawPSBT(psbt_merge, fuzzed_data_provider.ConsumeRandomLengthString(), error)) {
+ str = fuzzed_data_provider.ConsumeRandomLengthString();
+ if (!DecodeRawPSBT(psbt_merge, MakeByteSpan(str), error)) {
psbt_merge = psbt;
}
psbt_mut = psbt;
diff --git a/src/test/fuzz/string.cpp b/src/test/fuzz/string.cpp
index b4876d427f..e6064d19b6 100644
--- a/src/test/fuzz/string.cpp
+++ b/src/test/fuzz/string.cpp
@@ -42,7 +42,7 @@ bool LegacyParsePrechecks(const std::string& str)
return false;
if (str.size() >= 1 && (IsSpace(str[0]) || IsSpace(str[str.size() - 1]))) // No padding allowed
return false;
- if (!ValidAsCString(str)) // No embedded NUL characters allowed
+ if (!ContainsNoNUL(str)) // No embedded NUL characters allowed
return false;
return true;
}
@@ -188,7 +188,7 @@ FUZZ_TARGET(string)
(void)TrimString(random_string_1);
(void)TrimString(random_string_1, random_string_2);
(void)urlDecode(random_string_1);
- (void)ValidAsCString(random_string_1);
+ (void)ContainsNoNUL(random_string_1);
(void)_(random_string_1.c_str());
try {
throw scriptnum_error{random_string_1};
diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp
index 1830ec05af..2fc71c2a6e 100644
--- a/src/test/util/setup_common.cpp
+++ b/src/test/util/setup_common.cpp
@@ -182,7 +182,6 @@ ChainTestingSetup::~ChainTestingSetup()
m_node.addrman.reset();
m_node.netgroupman.reset();
m_node.args = nullptr;
- WITH_LOCK(::cs_main, UnloadBlockIndex(m_node.mempool.get(), *m_node.chainman));
m_node.mempool.reset();
m_node.scheduler.reset();
m_node.chainman.reset();
diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp
index 779ed20032..1ca20fd848 100644
--- a/src/test/util_tests.cpp
+++ b/src/test/util_tests.cpp
@@ -226,17 +226,17 @@ BOOST_AUTO_TEST_CASE(util_Join)
BOOST_AUTO_TEST_CASE(util_TrimString)
{
BOOST_CHECK_EQUAL(TrimString(" foo bar "), "foo bar");
- BOOST_CHECK_EQUAL(TrimString("\t \n \n \f\n\r\t\v\tfoo \n \f\n\r\t\v\tbar\t \n \f\n\r\t\v\t\n "), "foo \n \f\n\r\t\v\tbar");
+ BOOST_CHECK_EQUAL(TrimStringView("\t \n \n \f\n\r\t\v\tfoo \n \f\n\r\t\v\tbar\t \n \f\n\r\t\v\t\n "), "foo \n \f\n\r\t\v\tbar");
BOOST_CHECK_EQUAL(TrimString("\t \n foo \n\tbar\t \n "), "foo \n\tbar");
- BOOST_CHECK_EQUAL(TrimString("\t \n foo \n\tbar\t \n ", "fobar"), "\t \n foo \n\tbar\t \n ");
+ BOOST_CHECK_EQUAL(TrimStringView("\t \n foo \n\tbar\t \n ", "fobar"), "\t \n foo \n\tbar\t \n ");
BOOST_CHECK_EQUAL(TrimString("foo bar"), "foo bar");
- BOOST_CHECK_EQUAL(TrimString("foo bar", "fobar"), " ");
+ BOOST_CHECK_EQUAL(TrimStringView("foo bar", "fobar"), " ");
BOOST_CHECK_EQUAL(TrimString(std::string("\0 foo \0 ", 8)), std::string("\0 foo \0", 7));
- BOOST_CHECK_EQUAL(TrimString(std::string(" foo ", 5)), std::string("foo", 3));
+ BOOST_CHECK_EQUAL(TrimStringView(std::string(" foo ", 5)), std::string("foo", 3));
BOOST_CHECK_EQUAL(TrimString(std::string("\t\t\0\0\n\n", 6)), std::string("\0\0", 2));
- BOOST_CHECK_EQUAL(TrimString(std::string("\x05\x04\x03\x02\x01\x00", 6)), std::string("\x05\x04\x03\x02\x01\x00", 6));
+ BOOST_CHECK_EQUAL(TrimStringView(std::string("\x05\x04\x03\x02\x01\x00", 6)), std::string("\x05\x04\x03\x02\x01\x00", 6));
BOOST_CHECK_EQUAL(TrimString(std::string("\x05\x04\x03\x02\x01\x00", 6), std::string("\x05\x04\x03\x02\x01", 5)), std::string("\0", 1));
- BOOST_CHECK_EQUAL(TrimString(std::string("\x05\x04\x03\x02\x01\x00", 6), std::string("\x05\x04\x03\x02\x01\x00", 6)), "");
+ BOOST_CHECK_EQUAL(TrimStringView(std::string("\x05\x04\x03\x02\x01\x00", 6), std::string("\x05\x04\x03\x02\x01\x00", 6)), "");
}
BOOST_AUTO_TEST_CASE(util_FormatParseISO8601DateTime)
@@ -2618,13 +2618,13 @@ BOOST_AUTO_TEST_CASE(message_hash)
BOOST_AUTO_TEST_CASE(remove_prefix)
{
BOOST_CHECK_EQUAL(RemovePrefix("./util/system.h", "./"), "util/system.h");
- BOOST_CHECK_EQUAL(RemovePrefix("foo", "foo"), "");
+ BOOST_CHECK_EQUAL(RemovePrefixView("foo", "foo"), "");
BOOST_CHECK_EQUAL(RemovePrefix("foo", "fo"), "o");
- BOOST_CHECK_EQUAL(RemovePrefix("foo", "f"), "oo");
+ BOOST_CHECK_EQUAL(RemovePrefixView("foo", "f"), "oo");
BOOST_CHECK_EQUAL(RemovePrefix("foo", ""), "foo");
- BOOST_CHECK_EQUAL(RemovePrefix("fo", "foo"), "fo");
+ BOOST_CHECK_EQUAL(RemovePrefixView("fo", "foo"), "fo");
BOOST_CHECK_EQUAL(RemovePrefix("f", "foo"), "f");
- BOOST_CHECK_EQUAL(RemovePrefix("", "foo"), "");
+ BOOST_CHECK_EQUAL(RemovePrefixView("", "foo"), "");
BOOST_CHECK_EQUAL(RemovePrefix("", ""), "");
}
diff --git a/src/test/validation_chainstate_tests.cpp b/src/test/validation_chainstate_tests.cpp
index b0d7389d39..2a3990bb7c 100644
--- a/src/test/validation_chainstate_tests.cpp
+++ b/src/test/validation_chainstate_tests.cpp
@@ -93,7 +93,7 @@ BOOST_FIXTURE_TEST_CASE(chainstate_update_tip, TestChain100Setup)
BOOST_REQUIRE(CreateAndActivateUTXOSnapshot(m_node, m_path_root));
// Ensure our active chain is the snapshot chainstate.
- BOOST_CHECK(chainman.IsSnapshotActive());
+ BOOST_CHECK(WITH_LOCK(::cs_main, return chainman.IsSnapshotActive()));
curr_tip = ::g_best_block;
diff --git a/src/test/validation_chainstatemanager_tests.cpp b/src/test/validation_chainstatemanager_tests.cpp
index 5d0ec593e3..6dc522b421 100644
--- a/src/test/validation_chainstatemanager_tests.cpp
+++ b/src/test/validation_chainstatemanager_tests.cpp
@@ -45,7 +45,7 @@ BOOST_AUTO_TEST_CASE(chainstatemanager)
WITH_LOCK(::cs_main, c1.InitCoinsCache(1 << 23));
BOOST_CHECK(!manager.IsSnapshotActive());
- BOOST_CHECK(!manager.IsSnapshotValidated());
+ BOOST_CHECK(WITH_LOCK(::cs_main, return !manager.IsSnapshotValidated()));
auto all = manager.GetAll();
BOOST_CHECK_EQUAL_COLLECTIONS(all.begin(), all.end(), chainstates.begin(), chainstates.end());
@@ -78,7 +78,7 @@ BOOST_AUTO_TEST_CASE(chainstatemanager)
BOOST_CHECK(c2.ActivateBestChain(_, nullptr));
BOOST_CHECK(manager.IsSnapshotActive());
- BOOST_CHECK(!manager.IsSnapshotValidated());
+ BOOST_CHECK(WITH_LOCK(::cs_main, return !manager.IsSnapshotValidated()));
BOOST_CHECK_EQUAL(&c2, &manager.ActiveChainstate());
BOOST_CHECK(&c1 != &manager.ActiveChainstate());
auto all2 = manager.GetAll();
diff --git a/src/util/check.h b/src/util/check.h
index 91d62e262d..aca957925a 100644
--- a/src/util/check.h
+++ b/src/util/check.h
@@ -30,7 +30,6 @@ T&& inline_check_non_fatal(T&& val, const char* file, int line, const char* func
throw NonFatalCheckError(
format_internal_error(assertion, file, line, func, PACKAGE_BUGREPORT));
}
-
return std::forward<T>(val);
}
diff --git a/src/util/message.cpp b/src/util/message.cpp
index 2c7f0406f0..f58876f915 100644
--- a/src/util/message.cpp
+++ b/src/util/message.cpp
@@ -35,14 +35,13 @@ MessageVerificationResult MessageVerify(
return MessageVerificationResult::ERR_ADDRESS_NO_KEY;
}
- bool invalid = false;
- std::vector<unsigned char> signature_bytes = DecodeBase64(signature.c_str(), &invalid);
- if (invalid) {
+ auto signature_bytes = DecodeBase64(signature);
+ if (!signature_bytes) {
return MessageVerificationResult::ERR_MALFORMED_SIGNATURE;
}
CPubKey pubkey;
- if (!pubkey.RecoverCompact(MessageHash(message), signature_bytes)) {
+ if (!pubkey.RecoverCompact(MessageHash(message), *signature_bytes)) {
return MessageVerificationResult::ERR_PUBKEY_NOT_RECOVERED;
}
diff --git a/src/util/moneystr.cpp b/src/util/moneystr.cpp
index 2cd7a426f8..8c4bc6e6f4 100644
--- a/src/util/moneystr.cpp
+++ b/src/util/moneystr.cpp
@@ -40,7 +40,7 @@ std::string FormatMoney(const CAmount n)
std::optional<CAmount> ParseMoney(const std::string& money_string)
{
- if (!ValidAsCString(money_string)) {
+ if (!ContainsNoNUL(money_string)) {
return std::nullopt;
}
const std::string str = TrimString(money_string);
diff --git a/src/util/strencodings.cpp b/src/util/strencodings.cpp
index 940fa90da2..35f62f0422 100644
--- a/src/util/strencodings.cpp
+++ b/src/util/strencodings.cpp
@@ -24,15 +24,15 @@ static const std::string SAFE_CHARS[] =
CHARS_ALPHA_NUM + "!*'();:@&=+$,/?#[]-_.~%", // SAFE_CHARS_URI
};
-std::string SanitizeString(const std::string& str, int rule)
+std::string SanitizeString(std::string_view str, int rule)
{
- std::string strResult;
- for (std::string::size_type i = 0; i < str.size(); i++)
- {
- if (SAFE_CHARS[rule].find(str[i]) != std::string::npos)
- strResult.push_back(str[i]);
+ std::string result;
+ for (char c : str) {
+ if (SAFE_CHARS[rule].find(c) != std::string::npos) {
+ result.push_back(c);
+ }
}
- return strResult;
+ return result;
}
const signed char p_util_hexdigit[256] =
@@ -58,56 +58,43 @@ signed char HexDigit(char c)
return p_util_hexdigit[(unsigned char)c];
}
-bool IsHex(const std::string& str)
+bool IsHex(std::string_view str)
{
- for(std::string::const_iterator it(str.begin()); it != str.end(); ++it)
- {
- if (HexDigit(*it) < 0)
- return false;
+ for (char c : str) {
+ if (HexDigit(c) < 0) return false;
}
return (str.size() > 0) && (str.size()%2 == 0);
}
-bool IsHexNumber(const std::string& str)
+bool IsHexNumber(std::string_view str)
{
- size_t starting_location = 0;
- if (str.size() > 2 && *str.begin() == '0' && *(str.begin()+1) == 'x') {
- starting_location = 2;
- }
- for (const char c : str.substr(starting_location)) {
+ if (str.substr(0, 2) == "0x") str.remove_prefix(2);
+ for (char c : str) {
if (HexDigit(c) < 0) return false;
}
// Return false for empty string or "0x".
- return (str.size() > starting_location);
+ return str.size() > 0;
}
-std::vector<unsigned char> ParseHex(const char* psz)
+std::vector<unsigned char> ParseHex(std::string_view str)
{
// convert hex dump to vector
std::vector<unsigned char> vch;
- while (true)
- {
- while (IsSpace(*psz))
- psz++;
- signed char c = HexDigit(*psz++);
- if (c == (signed char)-1)
- break;
- auto n{uint8_t(c << 4)};
- c = HexDigit(*psz++);
- if (c == (signed char)-1)
- break;
- n |= c;
- vch.push_back(n);
+ auto it = str.begin();
+ while (it != str.end() && it + 1 != str.end()) {
+ if (IsSpace(*it)) {
+ ++it;
+ continue;
+ }
+ auto c1 = HexDigit(*(it++));
+ auto c2 = HexDigit(*(it++));
+ if (c1 < 0 || c2 < 0) break;
+ vch.push_back(uint8_t(c1 << 4) | c2);
}
return vch;
}
-std::vector<unsigned char> ParseHex(const std::string& str)
-{
- return ParseHex(str.c_str());
-}
-
-void SplitHostPort(std::string in, uint16_t& portOut, std::string& hostOut)
+void SplitHostPort(std::string_view in, uint16_t& portOut, std::string& hostOut)
{
size_t colon = in.find_last_of(':');
// if a : is found, and it either follows a [...], or no other : is in the string, treat it as port separator
@@ -139,7 +126,7 @@ std::string EncodeBase64(Span<const unsigned char> input)
return str;
}
-std::vector<unsigned char> DecodeBase64(const char* p, bool* pf_invalid)
+std::optional<std::vector<unsigned char>> DecodeBase64(std::string_view str)
{
static const int8_t decode64_table[256]{
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
@@ -157,46 +144,23 @@ std::vector<unsigned char> DecodeBase64(const char* p, bool* pf_invalid)
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
};
- const char* e = p;
- std::vector<uint8_t> val;
- val.reserve(strlen(p));
- while (*p != 0) {
- int x = decode64_table[(unsigned char)*p];
- if (x == -1) break;
- val.push_back(uint8_t(x));
- ++p;
- }
+ if (str.size() % 4 != 0) return {};
+ /* One or two = characters at the end are permitted. */
+ if (str.size() >= 1 && str.back() == '=') str.remove_suffix(1);
+ if (str.size() >= 1 && str.back() == '=') str.remove_suffix(1);
std::vector<unsigned char> ret;
- ret.reserve((val.size() * 3) / 4);
- bool valid = ConvertBits<6, 8, false>([&](unsigned char c) { ret.push_back(c); }, val.begin(), val.end());
-
- const char* q = p;
- while (valid && *p != 0) {
- if (*p != '=') {
- valid = false;
- break;
- }
- ++p;
- }
- valid = valid && (p - e) % 4 == 0 && p - q < 4;
- if (pf_invalid) *pf_invalid = !valid;
+ ret.reserve((str.size() * 3) / 4);
+ bool valid = ConvertBits<6, 8, false>(
+ [&](unsigned char c) { ret.push_back(c); },
+ str.begin(), str.end(),
+ [](char c) { return decode64_table[uint8_t(c)]; }
+ );
+ if (!valid) return {};
return ret;
}
-std::string DecodeBase64(const std::string& str, bool* pf_invalid)
-{
- if (!ValidAsCString(str)) {
- if (pf_invalid) {
- *pf_invalid = true;
- }
- return {};
- }
- std::vector<unsigned char> vchRet = DecodeBase64(str.c_str(), pf_invalid);
- return std::string((const char*)vchRet.data(), vchRet.size());
-}
-
std::string EncodeBase32(Span<const unsigned char> input, bool pad)
{
static const char *pbase32 = "abcdefghijklmnopqrstuvwxyz234567";
@@ -212,12 +176,12 @@ std::string EncodeBase32(Span<const unsigned char> input, bool pad)
return str;
}
-std::string EncodeBase32(const std::string& str, bool pad)
+std::string EncodeBase32(std::string_view str, bool pad)
{
return EncodeBase32(MakeUCharSpan(str), pad);
}
-std::vector<unsigned char> DecodeBase32(const char* p, bool* pf_invalid)
+std::optional<std::vector<unsigned char>> DecodeBase32(std::string_view str)
{
static const int8_t decode32_table[256]{
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
@@ -235,49 +199,29 @@ std::vector<unsigned char> DecodeBase32(const char* p, bool* pf_invalid)
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
};
- const char* e = p;
- std::vector<uint8_t> val;
- val.reserve(strlen(p));
- while (*p != 0) {
- int x = decode32_table[(unsigned char)*p];
- if (x == -1) break;
- val.push_back(uint8_t(x));
- ++p;
- }
+ if (str.size() % 8 != 0) return {};
+ /* 1, 3, 4, or 6 padding '=' suffix characters are permitted. */
+ if (str.size() >= 1 && str.back() == '=') str.remove_suffix(1);
+ if (str.size() >= 2 && str.substr(str.size() - 2) == "==") str.remove_suffix(2);
+ if (str.size() >= 1 && str.back() == '=') str.remove_suffix(1);
+ if (str.size() >= 2 && str.substr(str.size() - 2) == "==") str.remove_suffix(2);
std::vector<unsigned char> ret;
- ret.reserve((val.size() * 5) / 8);
- bool valid = ConvertBits<5, 8, false>([&](unsigned char c) { ret.push_back(c); }, val.begin(), val.end());
-
- const char* q = p;
- while (valid && *p != 0) {
- if (*p != '=') {
- valid = false;
- break;
- }
- ++p;
- }
- valid = valid && (p - e) % 8 == 0 && p - q < 8;
- if (pf_invalid) *pf_invalid = !valid;
+ ret.reserve((str.size() * 5) / 8);
+ bool valid = ConvertBits<5, 8, false>(
+ [&](unsigned char c) { ret.push_back(c); },
+ str.begin(), str.end(),
+ [](char c) { return decode32_table[uint8_t(c)]; }
+ );
- return ret;
-}
+ if (!valid) return {};
-std::string DecodeBase32(const std::string& str, bool* pf_invalid)
-{
- if (!ValidAsCString(str)) {
- if (pf_invalid) {
- *pf_invalid = true;
- }
- return {};
- }
- std::vector<unsigned char> vchRet = DecodeBase32(str.c_str(), pf_invalid);
- return std::string((const char*)vchRet.data(), vchRet.size());
+ return ret;
}
namespace {
template <typename T>
-bool ParseIntegral(const std::string& str, T* out)
+bool ParseIntegral(std::string_view str, T* out)
{
static_assert(std::is_integral<T>::value);
// Replicate the exact behavior of strtol/strtoll/strtoul/strtoull when
@@ -296,37 +240,37 @@ bool ParseIntegral(const std::string& str, T* out)
}
}; // namespace
-bool ParseInt32(const std::string& str, int32_t* out)
+bool ParseInt32(std::string_view str, int32_t* out)
{
return ParseIntegral<int32_t>(str, out);
}
-bool ParseInt64(const std::string& str, int64_t* out)
+bool ParseInt64(std::string_view str, int64_t* out)
{
return ParseIntegral<int64_t>(str, out);
}
-bool ParseUInt8(const std::string& str, uint8_t* out)
+bool ParseUInt8(std::string_view str, uint8_t* out)
{
return ParseIntegral<uint8_t>(str, out);
}
-bool ParseUInt16(const std::string& str, uint16_t* out)
+bool ParseUInt16(std::string_view str, uint16_t* out)
{
return ParseIntegral<uint16_t>(str, out);
}
-bool ParseUInt32(const std::string& str, uint32_t* out)
+bool ParseUInt32(std::string_view str, uint32_t* out)
{
return ParseIntegral<uint32_t>(str, out);
}
-bool ParseUInt64(const std::string& str, uint64_t* out)
+bool ParseUInt64(std::string_view str, uint64_t* out)
{
return ParseIntegral<uint64_t>(str, out);
}
-std::string FormatParagraph(const std::string& in, size_t width, size_t indent)
+std::string FormatParagraph(std::string_view in, size_t width, size_t indent)
{
assert(width >= indent);
std::stringstream out;
@@ -395,7 +339,7 @@ static inline bool ProcessMantissaDigit(char ch, int64_t &mantissa, int &mantiss
return true;
}
-bool ParseFixedPoint(const std::string &val, int decimals, int64_t *amount_out)
+bool ParseFixedPoint(std::string_view val, int decimals, int64_t *amount_out)
{
int64_t mantissa = 0;
int64_t exponent = 0;
@@ -487,14 +431,14 @@ bool ParseFixedPoint(const std::string &val, int decimals, int64_t *amount_out)
return true;
}
-std::string ToLower(const std::string& str)
+std::string ToLower(std::string_view str)
{
std::string r;
for (auto ch : str) r += ToLower(ch);
return r;
}
-std::string ToUpper(const std::string& str)
+std::string ToUpper(std::string_view str)
{
std::string r;
for (auto ch : str) r += ToUpper(ch);
@@ -522,7 +466,7 @@ std::string HexStr(const Span<const uint8_t> s)
return rv;
}
-std::optional<uint64_t> ParseByteUnits(const std::string& str, ByteUnit default_multiplier)
+std::optional<uint64_t> ParseByteUnits(std::string_view str, ByteUnit default_multiplier)
{
if (str.empty()) {
return std::nullopt;
diff --git a/src/util/strencodings.h b/src/util/strencodings.h
index 1f83fa3ffa..ebb6d88952 100644
--- a/src/util/strencodings.h
+++ b/src/util/strencodings.h
@@ -54,24 +54,21 @@ enum class ByteUnit : uint64_t {
* @param[in] rule The set of safe chars to choose (default: least restrictive)
* @return A new string without unsafe chars
*/
-std::string SanitizeString(const std::string& str, int rule = SAFE_CHARS_DEFAULT);
-std::vector<unsigned char> ParseHex(const char* psz);
-std::vector<unsigned char> ParseHex(const std::string& str);
+std::string SanitizeString(std::string_view str, int rule = SAFE_CHARS_DEFAULT);
+std::vector<unsigned char> ParseHex(std::string_view str);
signed char HexDigit(char c);
/* Returns true if each character in str is a hex character, and has an even
* number of hex digits.*/
-bool IsHex(const std::string& str);
+bool IsHex(std::string_view str);
/**
* Return true if the string is a hex number, optionally prefixed with "0x"
*/
-bool IsHexNumber(const std::string& str);
-std::vector<unsigned char> DecodeBase64(const char* p, bool* pf_invalid = nullptr);
-std::string DecodeBase64(const std::string& str, bool* pf_invalid = nullptr);
+bool IsHexNumber(std::string_view str);
+std::optional<std::vector<unsigned char>> DecodeBase64(std::string_view str);
std::string EncodeBase64(Span<const unsigned char> input);
inline std::string EncodeBase64(Span<const std::byte> input) { return EncodeBase64(MakeUCharSpan(input)); }
-inline std::string EncodeBase64(const std::string& str) { return EncodeBase64(MakeUCharSpan(str)); }
-std::vector<unsigned char> DecodeBase32(const char* p, bool* pf_invalid = nullptr);
-std::string DecodeBase32(const std::string& str, bool* pf_invalid = nullptr);
+inline std::string EncodeBase64(std::string_view str) { return EncodeBase64(MakeUCharSpan(str)); }
+std::optional<std::vector<unsigned char>> DecodeBase32(std::string_view str);
/**
* Base32 encode.
@@ -85,9 +82,9 @@ std::string EncodeBase32(Span<const unsigned char> input, bool pad = true);
* If `pad` is true, then the output will be padded with '=' so that its length
* is a multiple of 8.
*/
-std::string EncodeBase32(const std::string& str, bool pad = true);
+std::string EncodeBase32(std::string_view str, bool pad = true);
-void SplitHostPort(std::string in, uint16_t& portOut, std::string& hostOut);
+void SplitHostPort(std::string_view in, uint16_t& portOut, std::string& hostOut);
// LocaleIndependentAtoi is provided for backwards compatibility reasons.
//
@@ -101,12 +98,12 @@ void SplitHostPort(std::string in, uint16_t& portOut, std::string& hostOut);
// undefined behavior, while this function returns the maximum or minimum
// values, respectively.
template <typename T>
-T LocaleIndependentAtoi(const std::string& str)
+T LocaleIndependentAtoi(std::string_view str)
{
static_assert(std::is_integral<T>::value);
T result;
// Emulate atoi(...) handling of white space and leading +/-.
- std::string s = TrimString(str);
+ std::string_view s = TrimStringView(str);
if (!s.empty() && s[0] == '+') {
if (s.length() >= 2 && s[1] == '-') {
return 0;
@@ -162,7 +159,7 @@ constexpr inline bool IsSpace(char c) noexcept {
* parsed value is not in the range representable by the type T.
*/
template <typename T>
-std::optional<T> ToIntegral(const std::string& str)
+std::optional<T> ToIntegral(std::string_view str)
{
static_assert(std::is_integral<T>::value);
T result;
@@ -178,42 +175,42 @@ std::optional<T> ToIntegral(const std::string& str)
* @returns true if the entire string could be parsed as valid integer,
* false if not the entire string could be parsed or when overflow or underflow occurred.
*/
-[[nodiscard]] bool ParseInt32(const std::string& str, int32_t *out);
+[[nodiscard]] bool ParseInt32(std::string_view str, int32_t *out);
/**
* Convert string to signed 64-bit integer with strict parse error feedback.
* @returns true if the entire string could be parsed as valid integer,
* false if not the entire string could be parsed or when overflow or underflow occurred.
*/
-[[nodiscard]] bool ParseInt64(const std::string& str, int64_t *out);
+[[nodiscard]] bool ParseInt64(std::string_view str, int64_t *out);
/**
* Convert decimal string to unsigned 8-bit integer with strict parse error feedback.
* @returns true if the entire string could be parsed as valid integer,
* false if not the entire string could be parsed or when overflow or underflow occurred.
*/
-[[nodiscard]] bool ParseUInt8(const std::string& str, uint8_t *out);
+[[nodiscard]] bool ParseUInt8(std::string_view str, uint8_t *out);
/**
* Convert decimal string to unsigned 16-bit integer with strict parse error feedback.
* @returns true if the entire string could be parsed as valid integer,
* false if the entire string could not be parsed or if overflow or underflow occurred.
*/
-[[nodiscard]] bool ParseUInt16(const std::string& str, uint16_t* out);
+[[nodiscard]] bool ParseUInt16(std::string_view str, uint16_t* out);
/**
* Convert decimal string to unsigned 32-bit integer with strict parse error feedback.
* @returns true if the entire string could be parsed as valid integer,
* false if not the entire string could be parsed or when overflow or underflow occurred.
*/
-[[nodiscard]] bool ParseUInt32(const std::string& str, uint32_t *out);
+[[nodiscard]] bool ParseUInt32(std::string_view str, uint32_t *out);
/**
* Convert decimal string to unsigned 64-bit integer with strict parse error feedback.
* @returns true if the entire string could be parsed as valid integer,
* false if not the entire string could be parsed or when overflow or underflow occurred.
*/
-[[nodiscard]] bool ParseUInt64(const std::string& str, uint64_t *out);
+[[nodiscard]] bool ParseUInt64(std::string_view str, uint64_t *out);
/**
* Convert a span of bytes to a lower-case hexadecimal string.
@@ -226,7 +223,7 @@ inline std::string HexStr(const Span<const std::byte> s) { return HexStr(MakeUCh
* Format a paragraph of text to a fixed width, adding spaces for
* indentation to any added line.
*/
-std::string FormatParagraph(const std::string& in, size_t width = 79, size_t indent = 0);
+std::string FormatParagraph(std::string_view in, size_t width = 79, size_t indent = 0);
/**
* Timing-attack-resistant comparison.
@@ -248,17 +245,28 @@ bool TimingResistantEqual(const T& a, const T& b)
* @returns true on success, false on error.
* @note The result must be in the range (-10^18,10^18), otherwise an overflow error will trigger.
*/
-[[nodiscard]] bool ParseFixedPoint(const std::string &val, int decimals, int64_t *amount_out);
+[[nodiscard]] bool ParseFixedPoint(std::string_view, int decimals, int64_t *amount_out);
+
+namespace {
+/** Helper class for the default infn argument to ConvertBits (just returns the input). */
+struct IntIdentity
+{
+ [[maybe_unused]] int operator()(int x) const { return x; }
+};
+
+} // namespace
/** Convert from one power-of-2 number base to another. */
-template<int frombits, int tobits, bool pad, typename O, typename I>
-bool ConvertBits(const O& outfn, I it, I end) {
+template<int frombits, int tobits, bool pad, typename O, typename It, typename I = IntIdentity>
+bool ConvertBits(O outfn, It it, It end, I infn = {}) {
size_t acc = 0;
size_t bits = 0;
constexpr size_t maxv = (1 << tobits) - 1;
constexpr size_t max_acc = (1 << (frombits + tobits - 1)) - 1;
while (it != end) {
- acc = ((acc << frombits) | *it) & max_acc;
+ int v = infn(*it);
+ if (v < 0) return false;
+ acc = ((acc << frombits) | v) & max_acc;
bits += frombits;
while (bits >= tobits) {
bits -= tobits;
@@ -298,7 +306,7 @@ constexpr char ToLower(char c)
* @param[in] str the string to convert to lowercase.
* @returns lowercased equivalent of str
*/
-std::string ToLower(const std::string& str);
+std::string ToLower(std::string_view str);
/**
* Converts the given character to its uppercase equivalent.
@@ -324,7 +332,7 @@ constexpr char ToUpper(char c)
* @param[in] str the string to convert to uppercase.
* @returns UPPERCASED EQUIVALENT OF str
*/
-std::string ToUpper(const std::string& str);
+std::string ToUpper(std::string_view str);
/**
* Capitalizes the first character of the given string.
@@ -348,6 +356,6 @@ std::string Capitalize(std::string str);
* @returns optional uint64_t bytes from str or nullopt
* if ToIntegral is false, str is empty, trailing whitespace or overflow
*/
-std::optional<uint64_t> ParseByteUnits(const std::string& str, ByteUnit default_multiplier);
+std::optional<uint64_t> ParseByteUnits(std::string_view str, ByteUnit default_multiplier);
#endif // BITCOIN_UTIL_STRENCODINGS_H
diff --git a/src/util/string.h b/src/util/string.h
index bcd6905fd5..36b9787db4 100644
--- a/src/util/string.h
+++ b/src/util/string.h
@@ -21,17 +21,22 @@
return spanparsing::Split<std::string>(str, sep);
}
-[[nodiscard]] inline std::string TrimString(const std::string& str, const std::string& pattern = " \f\n\r\t\v")
+[[nodiscard]] inline std::string_view TrimStringView(std::string_view str, std::string_view pattern = " \f\n\r\t\v")
{
std::string::size_type front = str.find_first_not_of(pattern);
if (front == std::string::npos) {
- return std::string();
+ return {};
}
std::string::size_type end = str.find_last_not_of(pattern);
return str.substr(front, end - front + 1);
}
-[[nodiscard]] inline std::string RemovePrefix(const std::string& str, const std::string& prefix)
+[[nodiscard]] inline std::string TrimString(std::string_view str, std::string_view pattern = " \f\n\r\t\v")
+{
+ return std::string(TrimStringView(str, pattern));
+}
+
+[[nodiscard]] inline std::string_view RemovePrefixView(std::string_view str, std::string_view prefix)
{
if (str.substr(0, prefix.size()) == prefix) {
return str.substr(prefix.size());
@@ -39,6 +44,11 @@
return str;
}
+[[nodiscard]] inline std::string RemovePrefix(std::string_view str, std::string_view prefix)
+{
+ return std::string(RemovePrefixView(str, prefix));
+}
+
/**
* Join a list of items
*
@@ -58,14 +68,14 @@ auto Join(const std::vector<T>& list, const BaseType& separator, UnaryOp unary_o
return ret;
}
-template <typename T>
-T Join(const std::vector<T>& list, const T& separator)
+template <typename T, typename T2>
+T Join(const std::vector<T>& list, const T2& separator)
{
return Join(list, separator, [](const T& i) { return i; });
}
// Explicit overload needed for c_str arguments, which would otherwise cause a substitution failure in the template above.
-inline std::string Join(const std::vector<std::string>& list, const std::string& separator)
+inline std::string Join(const std::vector<std::string>& list, std::string_view separator)
{
return Join<std::string>(list, separator);
}
@@ -81,9 +91,12 @@ inline std::string MakeUnorderedList(const std::vector<std::string>& items)
/**
* Check if a string does not contain any embedded NUL (\0) characters
*/
-[[nodiscard]] inline bool ValidAsCString(const std::string& str) noexcept
+[[nodiscard]] inline bool ContainsNoNUL(std::string_view str) noexcept
{
- return str.size() == strlen(str.c_str());
+ for (auto c : str) {
+ if (c == 0) return false;
+ }
+ return true;
}
/**
diff --git a/src/util/system.cpp b/src/util/system.cpp
index a7e66defcd..f9a9ad3e20 100644
--- a/src/util/system.cpp
+++ b/src/util/system.cpp
@@ -853,8 +853,8 @@ static bool GetConfigOptions(std::istream& stream, const std::string& filepath,
error = strprintf("parse error on line %i: %s, options in configuration file must be specified without leading -", linenr, str);
return false;
} else if ((pos = str.find('=')) != std::string::npos) {
- std::string name = prefix + TrimString(str.substr(0, pos), pattern);
- std::string value = TrimString(str.substr(pos + 1), pattern);
+ std::string name = prefix + TrimString(std::string_view{str}.substr(0, pos), pattern);
+ std::string_view value = TrimStringView(std::string_view{str}.substr(pos + 1), pattern);
if (used_hash && name.find("rpcpassword") != std::string::npos) {
error = strprintf("parse error on line %i, using # in rpcpassword can be ambiguous and should be avoided", linenr);
return false;
diff --git a/src/validation.cpp b/src/validation.cpp
index 05c21c703f..e2eb6a1f7a 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -1924,7 +1924,7 @@ public:
}
};
-static ThresholdConditionCache warningcache[VERSIONBITS_NUM_BITS] GUARDED_BY(cs_main);
+static std::array<ThresholdConditionCache, VERSIONBITS_NUM_BITS> warningcache GUARDED_BY(cs_main);
static unsigned int GetBlockScriptFlags(const CBlockIndex& block_index, const Consensus::Params& consensusparams)
{
@@ -2553,7 +2553,7 @@ void CChainState::UpdateTip(const CBlockIndex* pindexNew)
const CBlockIndex* pindex = pindexNew;
for (int bit = 0; bit < VERSIONBITS_NUM_BITS; bit++) {
WarningBitsConditionChecker checker(bit);
- ThresholdState state = checker.GetStateFor(pindex, m_params.GetConsensus(), warningcache[bit]);
+ ThresholdState state = checker.GetStateFor(pindex, m_params.GetConsensus(), warningcache.at(bit));
if (state == ThresholdState::ACTIVE || state == ThresholdState::LOCKED_IN) {
const bilingual_str warning = strprintf(_("Unknown new rules activated (versionbit %i)"), bit);
if (state == ThresholdState::ACTIVE) {
@@ -4146,20 +4146,6 @@ void CChainState::UnloadBlockIndex()
setBlockIndexCandidates.clear();
}
-// May NOT be used after any connections are up as much
-// of the peer-processing logic assumes a consistent
-// block index state
-void UnloadBlockIndex(CTxMemPool* mempool, ChainstateManager& chainman)
-{
- AssertLockHeld(::cs_main);
- chainman.Unload();
- if (mempool) mempool->clear();
- g_versionbitscache.Clear();
- for (int b = 0; b < VERSIONBITS_NUM_BITS; b++) {
- warningcache[b].clear();
- }
-}
-
bool ChainstateManager::LoadBlockIndex()
{
AssertLockHeld(cs_main);
@@ -5190,20 +5176,6 @@ bool ChainstateManager::IsSnapshotActive() const
return m_snapshot_chainstate && m_active_chainstate == m_snapshot_chainstate.get();
}
-void ChainstateManager::Unload()
-{
- AssertLockHeld(::cs_main);
- for (CChainState* chainstate : this->GetAll()) {
- chainstate->m_chain.SetTip(nullptr);
- chainstate->UnloadBlockIndex();
- }
-
- m_failed_blocks.clear();
- m_blockman.Unload();
- m_best_header = nullptr;
- m_best_invalid = nullptr;
-}
-
void ChainstateManager::MaybeRebalanceCaches()
{
AssertLockHeld(::cs_main);
@@ -5234,3 +5206,15 @@ void ChainstateManager::MaybeRebalanceCaches()
}
}
}
+
+ChainstateManager::~ChainstateManager()
+{
+ LOCK(::cs_main);
+
+ // TODO: The version bits cache and warning cache should probably become
+ // non-globals
+ g_versionbitscache.Clear();
+ for (auto& i : warningcache) {
+ i.clear();
+ }
+}
diff --git a/src/validation.h b/src/validation.h
index 38d3d98465..e3ea8617e7 100644
--- a/src/validation.h
+++ b/src/validation.h
@@ -134,8 +134,6 @@ extern arith_uint256 nMinimumChainWork;
/** Documentation for argument 'checklevel'. */
extern const std::vector<std::string> CHECKLEVEL_DOC;
-/** Unload database information */
-void UnloadBlockIndex(CTxMemPool* mempool, ChainstateManager& chainman) EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
/** Run instances of script checking worker threads */
void StartScriptCheckWorkerThreads(int threads_num);
/** Stop all of the script checking worker threads */
@@ -831,9 +829,9 @@ private:
//! If true, the assumed-valid chainstate has been fully validated
//! by the background validation chainstate.
- bool m_snapshot_validated{false};
+ bool m_snapshot_validated GUARDED_BY(::cs_main){false};
- CBlockIndex* m_best_invalid;
+ CBlockIndex* m_best_invalid GUARDED_BY(::cs_main){nullptr};
//! Internal helper for ActivateSnapshot().
[[nodiscard]] bool PopulateAndValidateSnapshot(
@@ -940,7 +938,7 @@ public:
std::optional<uint256> SnapshotBlockhash() const;
//! Is there a snapshot in use and has it been fully validated?
- bool IsSnapshotValidated() const { return m_snapshot_validated; }
+ bool IsSnapshotValidated() const EXCLUSIVE_LOCKS_REQUIRED(::cs_main) { return m_snapshot_validated; }
/**
* Process an incoming block. This only returns after the best known valid
@@ -988,17 +986,11 @@ public:
//! Load the block tree and coins database from disk, initializing state if we're running with -reindex
bool LoadBlockIndex() EXCLUSIVE_LOCKS_REQUIRED(cs_main);
- //! Unload block index and chain data before shutdown.
- void Unload() EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
-
//! Check to see if caches are out of balance and if so, call
//! ResizeCoinsCaches() as needed.
void MaybeRebalanceCaches() EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
- ~ChainstateManager() {
- LOCK(::cs_main);
- UnloadBlockIndex(/*mempool=*/nullptr, *this);
- }
+ ~ChainstateManager();
};
using FopenFn = std::function<FILE*(const fs::path&, const char*)>;
diff --git a/src/wallet/init.cpp b/src/wallet/init.cpp
index 7e21126298..7f038eda84 100644
--- a/src/wallet/init.cpp
+++ b/src/wallet/init.cpp
@@ -94,6 +94,7 @@ void WalletInit::AddWalletOptions(ArgsManager& argsman) const
#endif
argsman.AddArg("-walletrejectlongchains", strprintf("Wallet will not create transactions that violate mempool chain limits (default: %u)", DEFAULT_WALLET_REJECT_LONG_CHAINS), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::WALLET_DEBUG_TEST);
+ argsman.AddArg("-walletcrosschain", strprintf("Allow reusing wallet files across chains (default: %u)", DEFAULT_WALLETCROSSCHAIN), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::WALLET_DEBUG_TEST);
argsman.AddHiddenArgs({"-zapwallettxes"});
}
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 489599e2a0..79faf29907 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -523,6 +523,11 @@ bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase,
void CWallet::chainStateFlushed(const CBlockLocator& loc)
{
+ // Don't update the best block until the chain is attached so that in case of a shutdown,
+ // the rescan will be restarted at next startup.
+ if (m_attaching_chain) {
+ return;
+ }
WalletBatch batch(GetDatabase());
batch.WriteBestBlock(loc);
}
@@ -2934,12 +2939,28 @@ bool CWallet::AttachChain(const std::shared_ptr<CWallet>& walletInstance, interf
assert(!walletInstance->m_chain || walletInstance->m_chain == &chain);
walletInstance->m_chain = &chain;
+ // Unless allowed, ensure wallet files are not reused across chains:
+ if (!gArgs.GetBoolArg("-walletcrosschain", DEFAULT_WALLETCROSSCHAIN)) {
+ WalletBatch batch(walletInstance->GetDatabase());
+ CBlockLocator locator;
+ if (batch.ReadBestBlock(locator) && locator.vHave.size() > 0 && chain.getHeight()) {
+ // Wallet is assumed to be from another chain, if genesis block in the active
+ // chain differs from the genesis block known to the wallet.
+ if (chain.getBlockHash(0) != locator.vHave.back()) {
+ error = Untranslated("Wallet files should not be reused across chains. Restart bitcoind with -walletcrosschain to override.");
+ return false;
+ }
+ }
+ }
+
// Register wallet with validationinterface. It's done before rescan to avoid
// missing block connections between end of rescan and validation subscribing.
// Because of wallet lock being hold, block connection notifications are going to
// be pending on the validation-side until lock release. It's likely to have
// block processing duplicata (if rescan block range overlaps with notification one)
// but we guarantee at least than wallet state is correct after notifications delivery.
+ // However, chainStateFlushed notifications are ignored until the rescan is finished
+ // so that in case of a shutdown event, the rescan will be repeated at the next start.
// This is temporary until rescan and notifications delivery are unified under same
// interface.
walletInstance->m_chain_notifications_handler = walletInstance->chain().handleNotifications(walletInstance);
@@ -2968,6 +2989,7 @@ bool CWallet::AttachChain(const std::shared_ptr<CWallet>& walletInstance, interf
if (tip_height && *tip_height != rescan_height)
{
+ walletInstance->m_attaching_chain = true; //ignores chainStateFlushed notifications
if (chain.havePruned()) {
int block_height = *tip_height;
while (block_height > 0 && chain.haveBlockOnDisk(block_height - 1) && rescan_height != block_height) {
@@ -3007,6 +3029,7 @@ bool CWallet::AttachChain(const std::shared_ptr<CWallet>& walletInstance, interf
return false;
}
}
+ walletInstance->m_attaching_chain = false;
walletInstance->chainStateFlushed(chain.getTipLocator());
walletInstance->GetDatabase().IncrementUpdateCounter();
}
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index 26b7f97b5f..4e81a2b957 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -102,6 +102,7 @@ static const unsigned int DEFAULT_TX_CONFIRM_TARGET = 6;
static const bool DEFAULT_WALLET_RBF = false;
static const bool DEFAULT_WALLETBROADCAST = true;
static const bool DEFAULT_DISABLE_WALLET = false;
+static const bool DEFAULT_WALLETCROSSCHAIN = false;
//! -maxtxfee default
constexpr CAmount DEFAULT_TRANSACTION_MAXFEE{COIN / 10};
//! Discourage users to set fees higher than this amount (in satoshis) per kB
@@ -237,6 +238,7 @@ private:
std::atomic<bool> fAbortRescan{false};
std::atomic<bool> fScanningWallet{false}; // controlled by WalletRescanReserver
+ std::atomic<bool> m_attaching_chain{false};
std::atomic<int64_t> m_scanning_start{0};
std::atomic<double> m_scanning_progress{0};
friend class WalletRescanReserver;
diff --git a/test/README.md b/test/README.md
index e5a184d23c..d69e515acf 100644
--- a/test/README.md
+++ b/test/README.md
@@ -327,7 +327,7 @@ test/lint/lint-files.py
You can run all the shell-based lint tests by running:
```
-test/lint/lint-all.sh
+test/lint/lint-all.py
```
# Writing functional tests
diff --git a/test/functional/feature_taproot.py b/test/functional/feature_taproot.py
index c3925dbb00..0e44038196 100755
--- a/test/functional/feature_taproot.py
+++ b/test/functional/feature_taproot.py
@@ -10,7 +10,6 @@ from test_framework.blocktools import (
create_block,
add_witness_commitment,
MAX_BLOCK_SIGOPS_WEIGHT,
- NORMAL_GBT_REQUEST_PARAMS,
WITNESS_SCALE_FACTOR,
)
from test_framework.messages import (
@@ -96,10 +95,9 @@ from test_framework.util import assert_raises_rpc_error, assert_equal
from test_framework.key import generate_privkey, compute_xonly_pubkey, sign_schnorr, tweak_add_privkey, ECKey
from test_framework.address import (
hash160,
- program_to_witness
+ program_to_witness,
)
from collections import OrderedDict, namedtuple
-from enum import Enum
from io import BytesIO
import json
import hashlib
@@ -458,7 +456,7 @@ def spend(tx, idx, utxos, **kwargs):
# Each spender is a tuple of:
# - A scriptPubKey which is to be spent from (CScript)
# - A comment describing the test (string)
-# - Whether the spending (on itself) is expected to be standard (Enum.Standard)
+# - Whether the spending (on itself) is expected to be standard (bool)
# - A tx-signing lambda returning (scriptsig, witness_stack), taking as inputs:
# - A transaction to sign (CTransaction)
# - An input position (int)
@@ -470,14 +468,9 @@ def spend(tx, idx, utxos, **kwargs):
# - Whether this test demands being placed in a txin with no corresponding txout (for testing SIGHASH_SINGLE behavior)
Spender = namedtuple("Spender", "script,comment,is_standard,sat_function,err_msg,sigops_weight,no_fail,need_vin_vout_mismatch")
-# The full node versions that treat the tx standard.
-# ALL means any version
-# V23 means the major version 23.0 and any later version
-# NONE means no version
-Standard = Enum('Standard', 'ALL V23 NONE')
-def make_spender(comment, *, tap=None, witv0=False, script=None, pkh=None, p2sh=False, spk_mutate_pre_p2sh=None, failure=None, standard=Standard.ALL, err_msg=None, sigops_weight=0, need_vin_vout_mismatch=False, **kwargs):
+def make_spender(comment, *, tap=None, witv0=False, script=None, pkh=None, p2sh=False, spk_mutate_pre_p2sh=None, failure=None, standard=True, err_msg=None, sigops_weight=0, need_vin_vout_mismatch=False, **kwargs):
"""Helper for constructing Spender objects using the context signing framework.
* tap: a TaprootInfo object (see taproot_construct), for Taproot spends (cannot be combined with pkh, witv0, or script)
@@ -487,18 +480,13 @@ def make_spender(comment, *, tap=None, witv0=False, script=None, pkh=None, p2sh=
* p2sh: whether the output is P2SH wrapper (this is supported even for Taproot, where it makes the output unencumbered)
* spk_mutate_pre_psh: a callable to be applied to the script (before potentially P2SH-wrapping it)
* failure: a dict of entries to override in the context when intentionally failing to spend (if None, no_fail will be set)
- * standard: whether the (valid version of) spending is expected to be standard (True is mapped to Standard.ALL, False is mapped to Standard.NONE)
+ * standard: whether the (valid version of) spending is expected to be standard
* err_msg: a string with an expected error message for failure (or None, if not cared about)
* sigops_weight: the pre-taproot sigops weight consumed by a successful spend
* need_vin_vout_mismatch: whether this test requires being tested in a transaction input that has no corresponding
transaction output.
"""
- if standard == True:
- standard = Standard.ALL
- elif standard == False:
- standard = Standard.NONE
-
conf = dict()
# Compute scriptPubKey and set useful defaults based on the inputs.
@@ -1168,24 +1156,20 @@ def spenders_taproot_active():
return spenders
-def spenders_taproot_inactive():
- """Spenders for testing that pre-activation Taproot rules don't apply."""
+
+def spenders_taproot_nonstandard():
+ """Spenders for testing that post-activation Taproot rules may be nonstandard."""
spenders = []
sec = generate_privkey()
pub, _ = compute_xonly_pubkey(sec)
scripts = [
- ("pk", CScript([pub, OP_CHECKSIG])),
("future_leaf", CScript([pub, OP_CHECKSIG]), 0xc2),
("op_success", CScript([pub, OP_CHECKSIG, OP_0, OP_IF, CScriptOp(0x50), OP_ENDIF])),
]
tap = taproot_construct(pub, scripts)
- # Test that valid spending is standard.
- add_spender(spenders, "inactive/keypath_valid", key=sec, tap=tap, standard=Standard.V23)
- add_spender(spenders, "inactive/scriptpath_valid", key=sec, tap=tap, leaf="pk", standard=Standard.V23, inputs=[getter("sign")])
-
# Test that features like annex, leaf versions, or OP_SUCCESS are valid but non-standard
add_spender(spenders, "inactive/scriptpath_valid_unkleaf", key=sec, tap=tap, leaf="future_leaf", standard=False, inputs=[getter("sign")])
add_spender(spenders, "inactive/scriptpath_invalid_unkleaf", key=sec, tap=tap, leaf="future_leaf", standard=False, inputs=[getter("sign")], sighash=bitflipper(default_sighash))
@@ -1214,7 +1198,7 @@ def dump_json_test(tx, input_utxos, idx, success, failure):
# The "final" field indicates that a spend should be always valid, even with more validation flags enabled
# than the listed ones. Use standardness as a proxy for this (which gives a conservative underestimate).
- if spender.is_standard == Standard.ALL:
+ if spender.is_standard:
fields.append(("final", True))
def dump_witness(wit):
@@ -1241,31 +1225,14 @@ class TaprootTest(BitcoinTestFramework):
def add_options(self, parser):
parser.add_argument("--dumptests", dest="dump_tests", default=False, action="store_true",
help="Dump generated test cases to directory set by TEST_DUMP_DIR environment variable")
- parser.add_argument("--previous_release", dest="previous_release", default=False, action="store_true",
- help="Use a previous release as taproot-inactive node")
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
- if self.options.previous_release:
- self.skip_if_no_previous_releases()
def set_test_params(self):
- self.num_nodes = 2
+ self.num_nodes = 1
self.setup_clean_chain = True
- # Node 0 has Taproot inactive, Node 1 active.
- self.extra_args = [["-par=1"], ["-par=1"]]
- if self.options.previous_release:
- self.wallet_names = [None, self.default_wallet_name]
- else:
- self.extra_args[0].append("-vbparams=taproot:1:1")
-
- def setup_nodes(self):
- self.add_nodes(self.num_nodes, self.extra_args, versions=[
- 200100 if self.options.previous_release else None,
- None,
- ])
- self.start_nodes()
- self.import_deterministic_coinbase_privkeys()
+ self.extra_args = [["-par=1"]]
def block_submit(self, node, txs, msg, err_msg, cb_pubkey=None, fees=0, sigops_weight=0, witness=False, accept=False):
@@ -1479,11 +1446,10 @@ class TaprootTest(BitcoinTestFramework):
for i in range(len(input_utxos)):
tx.vin[i].scriptSig = input_data[i][i != fail_input][0]
tx.wit.vtxinwit[i].scriptWitness.stack = input_data[i][i != fail_input][1]
- taproot_spend_policy = Standard.V23 if node.version is None else Standard.ALL
# Submit to mempool to check standardness
is_standard_tx = (
fail_input is None # Must be valid to be standard
- and (all(utxo.spender.is_standard == Standard.ALL or utxo.spender.is_standard == taproot_spend_policy for utxo in input_utxos)) # All inputs must be standard
+ and (all(utxo.spender.is_standard for utxo in input_utxos)) # All inputs must be standard
and tx.nVersion >= 1 # The tx version must be standard
and tx.nVersion <= 2)
tx.rehash()
@@ -1510,7 +1476,7 @@ class TaprootTest(BitcoinTestFramework):
self.log.info("Unit test scenario...")
# Deterministically mine coins to OP_TRUE in block 1
- assert self.nodes[1].getblockcount() == 0
+ assert_equal(self.nodes[0].getblockcount(), 0)
coinbase = CTransaction()
coinbase.nVersion = 1
coinbase.vin = [CTxIn(COutPoint(0, 0xffffffff), CScript([OP_1, OP_1]), SEQUENCE_FINAL)]
@@ -1519,12 +1485,12 @@ class TaprootTest(BitcoinTestFramework):
coinbase.rehash()
assert coinbase.hash == "f60c73405d499a956d3162e3483c395526ef78286458a4cb17b125aa92e49b20"
# Mine it
- block = create_block(hashprev=int(self.nodes[1].getbestblockhash(), 16), coinbase=coinbase)
+ block = create_block(hashprev=int(self.nodes[0].getbestblockhash(), 16), coinbase=coinbase)
block.rehash()
block.solve()
- self.nodes[1].submitblock(block.serialize().hex())
- assert self.nodes[1].getblockcount() == 1
- self.generate(self.nodes[1], COINBASE_MATURITY)
+ self.nodes[0].submitblock(block.serialize().hex())
+ assert_equal(self.nodes[0].getblockcount(), 1)
+ self.generate(self.nodes[0], COINBASE_MATURITY)
SEED = 317
VALID_LEAF_VERS = list(range(0xc0, 0x100, 2)) + [0x66, 0x7e, 0x80, 0x84, 0x96, 0x98, 0xba, 0xbc, 0xbe]
@@ -1613,8 +1579,8 @@ class TaprootTest(BitcoinTestFramework):
spend_info[spk]['prevout'] = COutPoint(tx.sha256, i & 1)
spend_info[spk]['utxo'] = CTxOut(val, spk)
# Mine those transactions
- self.init_blockinfo(self.nodes[1])
- self.block_submit(self.nodes[1], txn, "Crediting txn", None, sigops_weight=10, accept=True)
+ self.init_blockinfo(self.nodes[0])
+ self.block_submit(self.nodes[0], txn, "Crediting txn", None, sigops_weight=10, accept=True)
# scriptPubKey computation
tests = {"version": 1}
@@ -1726,53 +1692,21 @@ class TaprootTest(BitcoinTestFramework):
keypath_tests.append(tx_test)
assert_equal(hashlib.sha256(tx.serialize()).hexdigest(), "24bab662cb55a7f3bae29b559f651674c62bcc1cd442d44715c0133939107b38")
# Mine the spending transaction
- self.block_submit(self.nodes[1], [tx], "Spending txn", None, sigops_weight=10000, accept=True, witness=True)
+ self.block_submit(self.nodes[0], [tx], "Spending txn", None, sigops_weight=10000, accept=True, witness=True)
if GEN_TEST_VECTORS:
print(json.dumps(tests, indent=4, sort_keys=False))
-
def run_test(self):
self.gen_test_vectors()
- # Post-taproot activation tests go first (pre-taproot tests' blocks are invalid post-taproot).
self.log.info("Post-activation tests...")
- self.test_spenders(self.nodes[1], spenders_taproot_active(), input_counts=[1, 2, 2, 2, 2, 3])
-
- # Re-connect nodes in case they have been disconnected
- self.disconnect_nodes(0, 1)
- self.connect_nodes(0, 1)
-
- # 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 unsp],
- outputs={addr: sum(i['amount'] for i in unsp)}
- )
- rawtx = self.nodes[1].signrawtransactionwithwallet(rawtx)['hex']
-
- # 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.solve()
- assert_equal(None, self.nodes[1].submitblock(block.serialize().hex()))
- self.sync_blocks()
-
- # Pre-taproot activation tests.
- self.log.info("Pre-activation tests...")
+ self.test_spenders(self.nodes[0], spenders_taproot_active(), input_counts=[1, 2, 2, 2, 2, 3])
# Run each test twice; once in isolation, and once combined with others. Testing in isolation
# means that the standardness is verified in every test (as combined transactions are only standard
# when all their inputs are standard).
- self.test_spenders(self.nodes[0], spenders_taproot_inactive(), input_counts=[1])
- self.test_spenders(self.nodes[0], spenders_taproot_inactive(), input_counts=[2, 3])
+ self.test_spenders(self.nodes[0], spenders_taproot_nonstandard(), input_counts=[1])
+ self.test_spenders(self.nodes[0], spenders_taproot_nonstandard(), input_counts=[2, 3])
if __name__ == '__main__':
diff --git a/test/functional/p2p_addr_relay.py b/test/functional/p2p_addr_relay.py
index 3218a9b14a..e2e9b6dcb2 100755
--- a/test/functional/p2p_addr_relay.py
+++ b/test/functional/p2p_addr_relay.py
@@ -21,8 +21,19 @@ from test_framework.p2p import (
P2P_SERVICES,
)
from test_framework.test_framework import BitcoinTestFramework
-from test_framework.util import assert_equal, assert_greater_than
+from test_framework.util import (
+ assert_equal,
+ assert_greater_than,
+ assert_greater_than_or_equal
+)
+
+ONE_MINUTE = 60
+TEN_MINUTES = 10 * ONE_MINUTE
+ONE_HOUR = 60 * ONE_MINUTE
+TWO_HOURS = 2 * ONE_HOUR
+ONE_DAY = 24 * ONE_HOUR
+ADDR_DESTINATIONS_THRESHOLD = 4
class AddrReceiver(P2PInterface):
num_ipv4_received = 0
@@ -85,6 +96,9 @@ class AddrTest(BitcoinTestFramework):
self.relay_tests()
self.inbound_blackhole_tests()
+ self.destination_rotates_once_in_24_hours_test()
+ self.destination_rotates_more_than_once_over_several_days_test()
+
# This test populates the addrman, which can impact the node's behavior
# in subsequent tests
self.getaddr_tests()
@@ -362,6 +376,56 @@ class AddrTest(BitcoinTestFramework):
self.nodes[0].disconnect_p2ps()
+ def get_nodes_that_received_addr(self, peer, receiver_peer, addr_receivers,
+ time_interval_1, time_interval_2):
+
+ # Clean addr response related to the initial getaddr. There is no way to avoid initial
+ # getaddr because the peer won't self-announce then.
+ for addr_receiver in addr_receivers:
+ addr_receiver.num_ipv4_received = 0
+
+ for _ in range(10):
+ self.mocktime += time_interval_1
+ self.msg.addrs[0].time = self.mocktime + TEN_MINUTES
+ self.nodes[0].setmocktime(self.mocktime)
+ with self.nodes[0].assert_debug_log(['received: addr (31 bytes) peer=0']):
+ peer.send_and_ping(self.msg)
+ self.mocktime += time_interval_2
+ self.nodes[0].setmocktime(self.mocktime)
+ receiver_peer.sync_with_ping()
+ return [node for node in addr_receivers if node.addr_received()]
+
+ def destination_rotates_once_in_24_hours_test(self):
+ self.restart_node(0, [])
+
+ self.log.info('Test within 24 hours an addr relay destination is rotated at most once')
+ self.mocktime = int(time.time())
+ self.msg = self.setup_addr_msg(1)
+ self.addr_receivers = []
+ peer = self.nodes[0].add_p2p_connection(P2PInterface())
+ receiver_peer = self.nodes[0].add_p2p_connection(AddrReceiver())
+ addr_receivers = [self.nodes[0].add_p2p_connection(AddrReceiver()) for _ in range(20)]
+ nodes_received_addr = self.get_nodes_that_received_addr(peer, receiver_peer, addr_receivers, 0, TWO_HOURS) # 10 intervals of 2 hours
+ # Per RelayAddress, we would announce these addrs to 2 destinations per day.
+ # Since it's at most one rotation, at most 4 nodes can receive ADDR.
+ assert_greater_than_or_equal(ADDR_DESTINATIONS_THRESHOLD, len(nodes_received_addr))
+ self.nodes[0].disconnect_p2ps()
+
+ def destination_rotates_more_than_once_over_several_days_test(self):
+ self.restart_node(0, [])
+
+ self.log.info('Test after several days an addr relay destination is rotated more than once')
+ self.msg = self.setup_addr_msg(1)
+ peer = self.nodes[0].add_p2p_connection(P2PInterface())
+ receiver_peer = self.nodes[0].add_p2p_connection(AddrReceiver())
+ addr_receivers = [self.nodes[0].add_p2p_connection(AddrReceiver()) for _ in range(20)]
+ # 10 intervals of 1 day (+ 1 hour, which should be enough to cover 30-min Poisson in most cases)
+ nodes_received_addr = self.get_nodes_that_received_addr(peer, receiver_peer, addr_receivers, ONE_DAY, ONE_HOUR)
+ # Now that there should have been more than one rotation, more than
+ # ADDR_DESTINATIONS_THRESHOLD nodes should have received ADDR.
+ assert_greater_than(len(nodes_received_addr), ADDR_DESTINATIONS_THRESHOLD)
+ self.nodes[0].disconnect_p2ps()
+
if __name__ == '__main__':
AddrTest().main()
diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py
index d845e5e034..7d6397d193 100755
--- a/test/functional/test_runner.py
+++ b/test/functional/test_runner.py
@@ -112,7 +112,6 @@ BASE_SCRIPTS = [
'p2p_tx_download.py',
'mempool_updatefromblock.py',
'wallet_dump.py --legacy-wallet',
- 'feature_taproot.py --previous_release',
'feature_taproot.py',
'rpc_signer.py',
'wallet_signer.py --descriptors',
@@ -256,6 +255,7 @@ BASE_SCRIPTS = [
'rpc_bind.py --ipv4',
'rpc_bind.py --ipv6',
'rpc_bind.py --nonloopback',
+ 'wallet_crosschain.py',
'mining_basic.py',
'feature_signet.py',
'wallet_bumpfee.py --legacy-wallet',
diff --git a/test/functional/wallet_createwallet.py b/test/functional/wallet_createwallet.py
index dcf2e98638..12480d4d1e 100755
--- a/test/functional/wallet_createwallet.py
+++ b/test/functional/wallet_createwallet.py
@@ -29,7 +29,7 @@ class CreateWalletTest(BitcoinTestFramework):
self.log.info("Run createwallet with invalid parameters.")
# Run createwallet with invalid parameters. This must not prevent a new wallet with the same name from being created with the correct parameters.
assert_raises_rpc_error(-4, "Passphrase provided but private keys are disabled. A passphrase is only used to encrypt private keys, so cannot be used for wallets with private keys disabled.",
- self.nodes[0].createwallet, wallet_name='w0', descriptors=True, disable_private_keys=True, passphrase="passphrase")
+ self.nodes[0].createwallet, wallet_name='w0', disable_private_keys=True, passphrase="passphrase")
self.nodes[0].createwallet(wallet_name='w0')
w0 = node.get_wallet_rpc('w0')
diff --git a/test/functional/wallet_crosschain.py b/test/functional/wallet_crosschain.py
new file mode 100755
index 0000000000..b6d0c87985
--- /dev/null
+++ b/test/functional/wallet_crosschain.py
@@ -0,0 +1,60 @@
+#!/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 os
+
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import assert_raises_rpc_error
+
+class WalletCrossChain(BitcoinTestFramework):
+ def set_test_params(self):
+ self.num_nodes = 2
+ self.setup_clean_chain = True
+
+ def skip_test_if_missing_module(self):
+ self.skip_if_no_wallet()
+
+ def setup_network(self):
+ self.add_nodes(self.num_nodes)
+
+ # Switch node 1 to testnet before starting it.
+ self.nodes[1].chain = 'testnet3'
+ self.nodes[1].extra_args = ['-maxconnections=0'] # disable testnet sync
+ with open(self.nodes[1].bitcoinconf, 'r', encoding='utf8') as conf:
+ conf_data = conf.read()
+ with open (self.nodes[1].bitcoinconf, 'w', encoding='utf8') as conf:
+ conf.write(conf_data.replace('regtest=', 'testnet=').replace('[regtest]', '[test]'))
+
+ self.start_nodes()
+
+ def run_test(self):
+ self.log.info("Creating wallets")
+
+ node0_wallet = os.path.join(self.nodes[0].datadir, 'node0_wallet')
+ self.nodes[0].createwallet(node0_wallet)
+ self.nodes[0].unloadwallet(node0_wallet)
+ node1_wallet = os.path.join(self.nodes[1].datadir, 'node1_wallet')
+ self.nodes[1].createwallet(node1_wallet)
+ self.nodes[1].unloadwallet(node1_wallet)
+
+ self.log.info("Loading wallets into nodes with a different genesis blocks")
+
+ if self.options.descriptors:
+ assert_raises_rpc_error(-18, 'Wallet file verification failed.', self.nodes[0].loadwallet, node1_wallet)
+ assert_raises_rpc_error(-18, 'Wallet file verification failed.', self.nodes[1].loadwallet, node0_wallet)
+ else:
+ assert_raises_rpc_error(-4, 'Wallet files should not be reused across chains.', self.nodes[0].loadwallet, node1_wallet)
+ assert_raises_rpc_error(-4, 'Wallet files should not be reused across chains.', self.nodes[1].loadwallet, node0_wallet)
+
+ if not self.options.descriptors:
+ self.log.info("Override cross-chain wallet load protection")
+ self.stop_nodes()
+ self.start_nodes([['-walletcrosschain']] * self.num_nodes)
+ self.nodes[0].loadwallet(node1_wallet)
+ self.nodes[1].loadwallet(node0_wallet)
+
+
+if __name__ == '__main__':
+ WalletCrossChain().main()
diff --git a/test/lint/README.md b/test/lint/README.md
index f4165f908e..1f683c10b3 100644
--- a/test/lint/README.md
+++ b/test/lint/README.md
@@ -39,6 +39,6 @@ To do so, add the upstream repository as remote:
git remote add --fetch secp256k1 https://github.com/bitcoin-core/secp256k1.git
```
-lint-all.sh
+lint-all.py
===========
Calls other scripts with the `lint-` prefix.
diff --git a/test/lint/lint-all.py b/test/lint/lint-all.py
new file mode 100755
index 0000000000..c280ba2db2
--- /dev/null
+++ b/test/lint/lint-all.py
@@ -0,0 +1,23 @@
+#!/usr/bin/env python3
+#
+# Copyright (c) 2017-2022 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#
+# This script runs all test/lint/lint-* files, and fails if any exit
+# with a non-zero status code.
+
+from glob import glob
+from pathlib import Path
+from subprocess import run
+
+exit_code = 0
+mod_path = Path(__file__).parent
+for lint in glob(f"{mod_path}/lint-*"):
+ if lint != __file__:
+ result = run([lint])
+ if result.returncode != 0:
+ print(f"^---- failure generated from {lint.split('/')[-1]}")
+ exit_code |= result.returncode
+
+exit(exit_code)
diff --git a/test/lint/lint-all.sh b/test/lint/lint-all.sh
deleted file mode 100755
index fa37fa51c6..0000000000
--- a/test/lint/lint-all.sh
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/usr/bin/env bash
-#
-# Copyright (c) 2017-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.
-#
-# This script runs all contrib/devtools/lint-* files, and fails if any exit
-# with a non-zero status code.
-
-# This script is intentionally locale dependent by not setting "export LC_ALL=C"
-# in order to allow for the executed lint scripts to opt in or opt out of locale
-# dependence themselves.
-
-set -u
-
-SCRIPTDIR=$(dirname "${BASH_SOURCE[0]}")
-LINTALL=$(basename "${BASH_SOURCE[0]}")
-
-EXIT_CODE=0
-
-for f in "${SCRIPTDIR}"/lint-*; do
- if [ "$(basename "$f")" != "$LINTALL" ]; then
- if ! "$f"; then
- echo "^---- failure generated from $f"
- EXIT_CODE=1
- fi
- fi
-done
-
-exit ${EXIT_CODE}
diff --git a/test/lint/lint-assertions.py b/test/lint/lint-assertions.py
index a8d2b3927c..195ff33d11 100755
--- a/test/lint/lint-assertions.py
+++ b/test/lint/lint-assertions.py
@@ -30,20 +30,20 @@ def main():
r"[^_]assert\(.*(\+\+|\-\-|[^=!<>]=[^=!<>]).*\);",
"--",
"*.cpp",
- "*.h"
+ "*.h",
], "Assertions should not have side effects:")
- # Macro CHECK_NONFATAL(condition) should be used instead of assert for RPC code, where it
- # is undesirable to crash the whole program. See: src/util/check.h
+ # Aborting the whole process is undesirable for RPC code. So nonfatal
+ # checks should be used over assert. See: src/util/check.h
# src/rpc/server.cpp is excluded from this check since it's mostly meta-code.
exit_code |= git_grep([
"-nE",
- r"\<(A|a)ssert *\(.*\);",
+ r"\<(A|a)ss(ume|ert) *\(.*\);",
"--",
"src/rpc/",
"src/wallet/rpc*",
- ":(exclude)src/rpc/server.cpp"
- ], "CHECK_NONFATAL(condition) should be used instead of assert for RPC code.")
+ ":(exclude)src/rpc/server.cpp",
+ ], "CHECK_NONFATAL(condition) or NONFATAL_UNREACHABLE should be used instead of assert for RPC code.")
sys.exit(exit_code)