diff options
106 files changed, 1796 insertions, 757 deletions
diff --git a/.cirrus.yml b/.cirrus.yml index fec4975080..5624c97d56 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -286,7 +286,7 @@ task: brew_install_script: - brew install boost libevent qt@5 miniupnpc libnatpmp ccache zeromq qrencode libtool automake gnu-getopt << : *GLOBAL_TASK_TEMPLATE - osx_instance: + macos_instance: # Use latest image, but hardcode version to avoid silent upgrades (and breaks) image: monterey-xcode-13.2 # https://cirrus-ci.org/guide/macOS env: diff --git a/build-aux/m4/ax_boost_unit_test_framework.m4 b/build-aux/m4/ax_boost_unit_test_framework.m4 deleted file mode 100644 index 4cca32fcfd..0000000000 --- a/build-aux/m4/ax_boost_unit_test_framework.m4 +++ /dev/null @@ -1,137 +0,0 @@ -# ================================================================================= -# https://www.gnu.org/software/autoconf-archive/ax_boost_unit_test_framework.html -# ================================================================================= -# -# SYNOPSIS -# -# AX_BOOST_UNIT_TEST_FRAMEWORK -# -# DESCRIPTION -# -# Test for Unit_Test_Framework library from the Boost C++ libraries. The -# macro requires a preceding call to AX_BOOST_BASE. Further documentation -# is available at <http://randspringer.de/boost/index.html>. -# -# This macro calls: -# -# AC_SUBST(BOOST_UNIT_TEST_FRAMEWORK_LIB) -# -# And sets: -# -# HAVE_BOOST_UNIT_TEST_FRAMEWORK -# -# LICENSE -# -# Copyright (c) 2008 Thomas Porschberg <thomas@randspringer.de> -# -# Copying and distribution of this file, with or without modification, are -# permitted in any medium without royalty provided the copyright notice -# and this notice are preserved. This file is offered as-is, without any -# warranty. - -#serial 22 - -AC_DEFUN([AX_BOOST_UNIT_TEST_FRAMEWORK], -[ - AC_ARG_WITH([boost-unit-test-framework], - AS_HELP_STRING([--with-boost-unit-test-framework@<:@=special-lib@:>@], - [use the Unit_Test_Framework library from boost - it is possible to specify a certain library for the linker - e.g. --with-boost-unit-test-framework=boost_unit_test_framework-gcc ]), - [ - if test "$withval" = "no"; then - want_boost="no" - elif test "$withval" = "yes"; then - want_boost="yes" - ax_boost_user_unit_test_framework_lib="" - else - want_boost="yes" - ax_boost_user_unit_test_framework_lib="$withval" - fi - ], - [want_boost="yes"] - ) - - if test "x$want_boost" = "xyes"; then - AC_REQUIRE([AC_PROG_CC]) - CPPFLAGS_SAVED="$CPPFLAGS" - CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" - export CPPFLAGS - - LDFLAGS_SAVED="$LDFLAGS" - LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" - export LDFLAGS - - AC_CACHE_CHECK(whether the Boost::Unit_Test_Framework library is available, - ax_cv_boost_unit_test_framework, - [AC_LANG_PUSH([C++]) - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include <boost/test/unit_test.hpp>]], - [[using boost::unit_test::test_suite; - test_suite* test= BOOST_TEST_SUITE( "Unit test example 1" ); if (test == NULL) { return 1; } else { return 0; }]])], - ax_cv_boost_unit_test_framework=yes, ax_cv_boost_unit_test_framework=no) - AC_LANG_POP([C++]) - ]) - if test "x$ax_cv_boost_unit_test_framework" = "xyes"; then - AC_DEFINE(HAVE_BOOST_UNIT_TEST_FRAMEWORK,,[define if the Boost::Unit_Test_Framework library is available]) - BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'` - - if test "x$ax_boost_user_unit_test_framework_lib" = "x"; then - saved_ldflags="${LDFLAGS}" - for monitor_library in `ls $BOOSTLIBDIR/libboost_unit_test_framework*.so* $BOOSTLIBDIR/libboost_unit_test_framework*.dylib* $BOOSTLIBDIR/libboost_unit_test_framework*.a* 2>/dev/null` ; do - if test -r $monitor_library ; then - libextension=`echo $monitor_library | sed 's,.*/,,' | sed -e 's;^lib\(boost_unit_test_framework.*\)\.so.*$;\1;' -e 's;^lib\(boost_unit_test_framework.*\)\.dylib.*$;\1;' -e 's;^lib\(boost_unit_test_framework.*\)\.a.*$;\1;'` - ax_lib=${libextension} - link_unit_test_framework="yes" - else - link_unit_test_framework="no" - fi - - if test "x$link_unit_test_framework" = "xyes"; then - BOOST_UNIT_TEST_FRAMEWORK_LIB="-l$ax_lib" - AC_SUBST(BOOST_UNIT_TEST_FRAMEWORK_LIB) - break - fi - done - if test "x$link_unit_test_framework" != "xyes"; then - for libextension in `ls $BOOSTLIBDIR/boost_unit_test_framework*.dll* $BOOSTLIBDIR/boost_unit_test_framework*.a* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^\(boost_unit_test_framework.*\)\.dll.*$;\1;' -e 's;^\(boost_unit_test_framework.*\)\.a.*$;\1;'` ; do - ax_lib=${libextension} - AC_CHECK_LIB($ax_lib, exit, - [BOOST_UNIT_TEST_FRAMEWORK_LIB="-l$ax_lib"; AC_SUBST(BOOST_UNIT_TEST_FRAMEWORK_LIB) link_unit_test_framework="yes"; break], - [link_unit_test_framework="no"]) - done - fi - else - link_unit_test_framework="no" - saved_ldflags="${LDFLAGS}" - for ax_lib in boost_unit_test_framework-$ax_boost_user_unit_test_framework_lib $ax_boost_user_unit_test_framework_lib ; do - if test "x$link_unit_test_framework" = "xyes"; then - break; - fi - for unittest_library in `ls $BOOSTLIBDIR/lib${ax_lib}.so* $BOOSTLIBDIR/lib${ax_lib}.a* 2>/dev/null` ; do - if test -r $unittest_library ; then - libextension=`echo $unittest_library | sed 's,.*/,,' | sed -e 's;^lib\(boost_unit_test_framework.*\)\.so.*$;\1;' -e 's;^lib\(boost_unit_test_framework.*\)\.a*$;\1;'` - ax_lib=${libextension} - link_unit_test_framework="yes" - else - link_unit_test_framework="no" - fi - - if test "x$link_unit_test_framework" = "xyes"; then - BOOST_UNIT_TEST_FRAMEWORK_LIB="-l$ax_lib" - AC_SUBST(BOOST_UNIT_TEST_FRAMEWORK_LIB) - break - fi - done - done - fi - if test "x$ax_lib" = "x"; then - AC_MSG_ERROR(Could not find a version of the Boost::Unit_Test_Framework library!) - fi - if test "x$link_unit_test_framework" != "xyes"; then - AC_MSG_ERROR(Could not link against $ax_lib !) - fi - fi - - CPPFLAGS="$CPPFLAGS_SAVED" - LDFLAGS="$LDFLAGS_SAVED" - fi -]) diff --git a/build_msvc/bitcoin_config.h.in b/build_msvc/bitcoin_config.h.in index c5ed6eb903..e25024e871 100644 --- a/build_msvc/bitcoin_config.h.in +++ b/build_msvc/bitcoin_config.h.in @@ -47,9 +47,6 @@ /* define if external signer support is enabled (requires Boost::Process) */ #define ENABLE_EXTERNAL_SIGNER /**/ -/* define if the Boost::Unit_Test_Framework library is available */ -#define HAVE_BOOST_UNIT_TEST_FRAMEWORK /**/ - /* Define this symbol if the consensus lib has been built */ #define HAVE_CONSENSUS_LIB 1 diff --git a/ci/test/00_setup_env_native_asan.sh b/ci/test/00_setup_env_native_asan.sh index 79caa607a8..b03a7edb54 100755 --- a/ci/test/00_setup_env_native_asan.sh +++ b/ci/test/00_setup_env_native_asan.sh @@ -7,7 +7,7 @@ export LC_ALL=C.UTF-8 export CONTAINER_NAME=ci_native_asan -export PACKAGES="clang llvm python3-zmq qtbase5-dev qttools5-dev-tools libevent-dev bsdmainutils libboost-dev libboost-test-dev libdb5.3++-dev libminiupnpc-dev libnatpmp-dev libzmq3-dev libqrencode-dev libsqlite3-dev" +export PACKAGES="clang llvm python3-zmq qtbase5-dev qttools5-dev-tools libevent-dev bsdmainutils libboost-dev libdb5.3++-dev libminiupnpc-dev libnatpmp-dev libzmq3-dev libqrencode-dev libsqlite3-dev" export DOCKER_NAME_TAG=ubuntu:22.04 export NO_DEPENDS=1 export GOAL="install" diff --git a/ci/test/00_setup_env_native_fuzz.sh b/ci/test/00_setup_env_native_fuzz.sh index af03ac4f5d..a36063c11f 100755 --- a/ci/test/00_setup_env_native_fuzz.sh +++ b/ci/test/00_setup_env_native_fuzz.sh @@ -8,7 +8,7 @@ export LC_ALL=C.UTF-8 export DOCKER_NAME_TAG="ubuntu:20.04" export CONTAINER_NAME=ci_native_fuzz -export PACKAGES="clang llvm python3 libevent-dev bsdmainutils libboost-dev libboost-test-dev libsqlite3-dev" +export PACKAGES="clang llvm python3 libevent-dev bsdmainutils libboost-dev libsqlite3-dev" export NO_DEPENDS=1 export RUN_UNIT_TESTS=false export RUN_FUNCTIONAL_TESTS=false diff --git a/ci/test/00_setup_env_native_fuzz_with_valgrind.sh b/ci/test/00_setup_env_native_fuzz_with_valgrind.sh index 607c0a43d0..4657259771 100755 --- a/ci/test/00_setup_env_native_fuzz_with_valgrind.sh +++ b/ci/test/00_setup_env_native_fuzz_with_valgrind.sh @@ -8,7 +8,7 @@ export LC_ALL=C.UTF-8 export DOCKER_NAME_TAG="ubuntu:20.04" export CONTAINER_NAME=ci_native_fuzz_valgrind -export PACKAGES="clang llvm python3 libevent-dev bsdmainutils libboost-dev libboost-test-dev libsqlite3-dev valgrind" +export PACKAGES="clang llvm python3 libevent-dev bsdmainutils libboost-dev libsqlite3-dev valgrind" export NO_DEPENDS=1 export RUN_UNIT_TESTS=false export RUN_FUNCTIONAL_TESTS=false diff --git a/ci/test/00_setup_env_native_valgrind.sh b/ci/test/00_setup_env_native_valgrind.sh index b0852f52a7..646070a84e 100755 --- a/ci/test/00_setup_env_native_valgrind.sh +++ b/ci/test/00_setup_env_native_valgrind.sh @@ -6,11 +6,11 @@ export LC_ALL=C.UTF-8 -export DOCKER_NAME_TAG="ubuntu:20.04" +export DOCKER_NAME_TAG="ubuntu:22.04" export CONTAINER_NAME=ci_native_valgrind -export PACKAGES="valgrind clang llvm python3-zmq libevent-dev bsdmainutils libboost-dev libboost-test-dev libdb5.3++-dev libminiupnpc-dev libnatpmp-dev libzmq3-dev libsqlite3-dev" +export PACKAGES="valgrind clang llvm python3-zmq libevent-dev bsdmainutils libboost-dev libdb5.3++-dev libminiupnpc-dev libnatpmp-dev libzmq3-dev libsqlite3-dev" export USE_VALGRIND=1 export NO_DEPENDS=1 -export TEST_RUNNER_EXTRA="--nosandbox --exclude rpc_bind,feature_bind_extra" # Excluded for now, see https://github.com/bitcoin/bitcoin/issues/17765#issuecomment-602068547 +export TEST_RUNNER_EXTRA="--nosandbox --exclude feature_init,rpc_bind,feature_bind_extra" # Excluded for now, see https://github.com/bitcoin/bitcoin/issues/17765#issuecomment-602068547 export GOAL="install" export BITCOIN_CONFIG="--enable-zmq --with-incompatible-bdb --with-gui=no CC=clang CXX=clang++" # TODO enable GUI diff --git a/ci/test/00_setup_env_s390x.sh b/ci/test/00_setup_env_s390x.sh index 0ec557ee46..136edb6662 100755 --- a/ci/test/00_setup_env_s390x.sh +++ b/ci/test/00_setup_env_s390x.sh @@ -20,7 +20,7 @@ fi export CONTAINER_NAME=ci_s390x export DOCKER_NAME_TAG="debian:bookworm" export TEST_RUNNER_ENV="LC_ALL=C" -export TEST_RUNNER_EXTRA="--exclude rpc_bind,feature_bind_extra" # Excluded for now, see https://github.com/bitcoin/bitcoin/issues/17765#issuecomment-602068547 +export TEST_RUNNER_EXTRA="--exclude feature_init,rpc_bind,feature_bind_extra" # Excluded for now, see https://github.com/bitcoin/bitcoin/issues/17765#issuecomment-602068547 export RUN_FUNCTIONAL_TESTS=true export GOAL="install" export BITCOIN_CONFIG="--enable-reduce-exports --disable-gui-tests" # GUI tests disabled for now, see https://github.com/bitcoin/bitcoin/issues/23730 diff --git a/configure.ac b/configure.ac index 078e113e95..222fa94946 100644 --- a/configure.ac +++ b/configure.ac @@ -469,7 +469,7 @@ AX_CHECK_COMPILE_FLAG([-fno-extended-identifiers], [CXXFLAGS="$CXXFLAGS -fno-ext enable_sse42=no enable_sse41=no enable_avx2=no -enable_shani=no +enable_x86_shani=no if test "$use_asm" = "yes"; then @@ -481,7 +481,7 @@ dnl x86 AX_CHECK_COMPILE_FLAG([-msse4.2], [SSE42_CXXFLAGS="-msse4.2"], [], [$CXXFLAG_WERROR]) AX_CHECK_COMPILE_FLAG([-msse4.1], [SSE41_CXXFLAGS="-msse4.1"], [], [$CXXFLAG_WERROR]) AX_CHECK_COMPILE_FLAG([-mavx -mavx2], [AVX2_CXXFLAGS="-mavx -mavx2"], [], [$CXXFLAG_WERROR]) -AX_CHECK_COMPILE_FLAG([-msse4 -msha], [SHANI_CXXFLAGS="-msse4 -msha"], [], [$CXXFLAG_WERROR]) +AX_CHECK_COMPILE_FLAG([-msse4 -msha], [X86_SHANI_CXXFLAGS="-msse4 -msha"], [], [$CXXFLAG_WERROR]) enable_clmul= AX_CHECK_COMPILE_FLAG([-mpclmul], [enable_clmul=yes], [], [$CXXFLAG_WERROR], [AC_LANG_PROGRAM([ @@ -554,8 +554,8 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ CXXFLAGS="$TEMP_CXXFLAGS" TEMP_CXXFLAGS="$CXXFLAGS" -CXXFLAGS="$CXXFLAGS $SHANI_CXXFLAGS" -AC_MSG_CHECKING([for SHA-NI intrinsics]) +CXXFLAGS="$CXXFLAGS $X86_SHANI_CXXFLAGS" +AC_MSG_CHECKING([for x86 SHA-NI intrinsics]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <stdint.h> #include <immintrin.h> @@ -565,17 +565,18 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ __m128i k = _mm_set1_epi32(2); return _mm_extract_epi32(_mm_sha256rnds2_epu32(i, i, k), 0); ]])], - [ AC_MSG_RESULT([yes]); enable_shani=yes; AC_DEFINE([ENABLE_SHANI], [1], [Define this symbol to build code that uses SHA-NI intrinsics]) ], + [ AC_MSG_RESULT([yes]); enable_x86_shani=yes; AC_DEFINE([ENABLE_X86_SHANI], [1], [Define this symbol to build code that uses x86 SHA-NI intrinsics]) ], [ AC_MSG_RESULT([no])] ) CXXFLAGS="$TEMP_CXXFLAGS" # ARM AX_CHECK_COMPILE_FLAG([-march=armv8-a+crc+crypto], [ARM_CRC_CXXFLAGS="-march=armv8-a+crc+crypto"], [], [$CXXFLAG_WERROR]) +AX_CHECK_COMPILE_FLAG([-march=armv8-a+crc+crypto], [ARM_SHANI_CXXFLAGS="-march=armv8-a+crc+crypto"], [], [$CXXFLAG_WERROR]) TEMP_CXXFLAGS="$CXXFLAGS" CXXFLAGS="$CXXFLAGS $ARM_CRC_CXXFLAGS" -AC_MSG_CHECKING([for AArch64 CRC32 intrinsics]) +AC_MSG_CHECKING([for ARMv8 CRC32 intrinsics]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <arm_acle.h> #include <arm_neon.h> @@ -592,6 +593,24 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ ) CXXFLAGS="$TEMP_CXXFLAGS" +TEMP_CXXFLAGS="$CXXFLAGS" +CXXFLAGS="$CXXFLAGS $ARM_SHANI_CXXFLAGS" +AC_MSG_CHECKING([for ARMv8 SHA-NI intrinsics]) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ + #include <arm_acle.h> + #include <arm_neon.h> + ]],[[ + uint32x4_t a, b, c; + vsha256h2q_u32(a, b, c); + vsha256hq_u32(a, b, c); + vsha256su0q_u32(a, b); + vsha256su1q_u32(a, b, c); + ]])], + [ AC_MSG_RESULT([yes]); enable_arm_shani=yes; AC_DEFINE([ENABLE_ARM_SHANI], [1], [Define this symbol to build code that uses ARMv8 SHA-NI intrinsics]) ], + [ AC_MSG_RESULT([no])] +) +CXXFLAGS="$TEMP_CXXFLAGS" + fi CPPFLAGS="$CPPFLAGS -DHAVE_BUILD_INFO" @@ -1112,13 +1131,6 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <unistd.h> [ AC_MSG_RESULT([no])] ) -AC_MSG_CHECKING([for getentropy]) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <unistd.h>]], - [[ getentropy(nullptr, 32) ]])], - [ AC_MSG_RESULT([yes]); AC_DEFINE([HAVE_GETENTROPY], [1], [Define this symbol if the BSD getentropy system call is available]) ], - [ AC_MSG_RESULT([no])] -) - AC_MSG_CHECKING([for getentropy via random.h]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <unistd.h> #include <sys/random.h>]], @@ -1411,8 +1423,6 @@ if test "$use_boost" = "yes"; then if test "$suppress_external_warnings" != "no"; then BOOST_CPPFLAGS=SUPPRESS_WARNINGS($BOOST_CPPFLAGS) fi - - BOOST_LIBS="$BOOST_LDFLAGS" fi if test "$use_external_signer" != "no"; then @@ -1427,8 +1437,20 @@ if test "$use_external_signer" != "no"; then use_external_signer="no"; ;; *) - use_external_signer="yes" - AC_DEFINE([ENABLE_EXTERNAL_SIGNER], [1], [Define if external signer support is enabled]) + AC_MSG_CHECKING([whether Boost.Process can be used]) + AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <boost/process.hpp>]])], + [have_boost_process="yes"], + [have_boost_process="no"]) + AC_MSG_RESULT([$have_boost_process]) + if test "$have_boost_process" == "yes"; then + use_external_signer="yes" + AC_DEFINE([ENABLE_EXTERNAL_SIGNER], [1], [Define if external signer support is enabled]) + else + if test "$use_external_signer" = "yes"; then + AC_MSG_ERROR([External signing is not supported for this Boost version]) + fi + use_external_signer="no"; + fi ;; esac fi @@ -1476,30 +1498,6 @@ if test "$use_tests" = "yes"; then if test "$HEXDUMP" = ""; then AC_MSG_ERROR([hexdump is required for tests]) fi - - if test "$use_boost" = "yes"; then - - AX_BOOST_UNIT_TEST_FRAMEWORK - - dnl Determine if -DBOOST_TEST_DYN_LINK is needed - AC_MSG_CHECKING([for dynamic linked boost test]) - TEMP_LIBS="$LIBS" - LIBS="$LIBS $BOOST_LDFLAGS $BOOST_UNIT_TEST_FRAMEWORK_LIB" - TEMP_CPPFLAGS="$CPPFLAGS" - CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" - AC_LINK_IFELSE([AC_LANG_SOURCE([ - #define BOOST_TEST_DYN_LINK - #define BOOST_TEST_MAIN - #include <boost/test/unit_test.hpp> - - ])], - [AC_MSG_RESULT([yes])] - [TESTDEFS="$TESTDEFS -DBOOST_TEST_DYN_LINK"], - [AC_MSG_RESULT([no])]) - LIBS="$TEMP_LIBS" - CPPFLAGS="$TEMP_CPPFLAGS" - - fi fi dnl libevent check @@ -1807,8 +1805,9 @@ AM_CONDITIONAL([HARDEN], [test "$use_hardening" = "yes"]) AM_CONDITIONAL([ENABLE_SSE42], [test "$enable_sse42" = "yes"]) AM_CONDITIONAL([ENABLE_SSE41], [test "$enable_sse41" = "yes"]) AM_CONDITIONAL([ENABLE_AVX2], [test "$enable_avx2" = "yes"]) -AM_CONDITIONAL([ENABLE_SHANI], [test "$enable_shani" = "yes"]) +AM_CONDITIONAL([ENABLE_X86_SHANI], [test "$enable_x86_shani" = "yes"]) AM_CONDITIONAL([ENABLE_ARM_CRC], [test "$enable_arm_crc" = "yes"]) +AM_CONDITIONAL([ENABLE_ARM_SHANI], [test "$enable_arm_shani" = "yes"]) AM_CONDITIONAL([USE_ASM], [test "$use_asm" = "yes"]) AM_CONDITIONAL([WORDS_BIGENDIAN], [test "$ac_cv_c_bigendian" = "yes"]) AM_CONDITIONAL([USE_NATPMP], [test "$use_natpmp" = "yes"]) @@ -1865,15 +1864,15 @@ AC_SUBST(SSE42_CXXFLAGS) AC_SUBST(SSE41_CXXFLAGS) AC_SUBST(CLMUL_CXXFLAGS) AC_SUBST(AVX2_CXXFLAGS) -AC_SUBST(SHANI_CXXFLAGS) +AC_SUBST(X86_SHANI_CXXFLAGS) AC_SUBST(ARM_CRC_CXXFLAGS) +AC_SUBST(ARM_SHANI_CXXFLAGS) AC_SUBST(LIBTOOL_APP_LDFLAGS) AC_SUBST(USE_SQLITE) AC_SUBST(USE_BDB) AC_SUBST(ENABLE_EXTERNAL_SIGNER) AC_SUBST(USE_UPNP) AC_SUBST(USE_QRCODE) -AC_SUBST(BOOST_LIBS) AC_SUBST(TESTDEFS) AC_SUBST(MINIUPNPC_CPPFLAGS) AC_SUBST(MINIUPNPC_LIBS) @@ -1958,8 +1957,8 @@ if test $enable_fuzz = "no"; then echo " with test = $use_tests" else echo " with test = not building test_bitcoin because fuzzing is enabled" - echo " with fuzz = $enable_fuzz" fi +echo " with fuzz binary = $enable_fuzz_binary" echo " with bench = $use_bench" echo " with upnp = $use_upnp" echo " with natpmp = $use_natpmp" diff --git a/contrib/guix/guix-build b/contrib/guix/guix-build index bfffbda742..2d44ad0365 100755 --- a/contrib/guix/guix-build +++ b/contrib/guix/guix-build @@ -239,7 +239,7 @@ SOURCE_DATE_EPOCH="${SOURCE_DATE_EPOCH:-$(git -c log.showSignature=false log --f time-machine() { # shellcheck disable=SC2086 guix time-machine --url=https://git.savannah.gnu.org/git/guix.git \ - --commit=1ef7a03a148cf5f83ab1820444f6bd50d8e732d1 \ + --commit=ae03f401381e956c4c41b4cf495cbde964fa43d0 \ --cores="$JOBS" \ --keep-failed \ --fallback \ diff --git a/contrib/guix/manifest.scm b/contrib/guix/manifest.scm index 22b922dc9b..d296eb9543 100644 --- a/contrib/guix/manifest.scm +++ b/contrib/guix/manifest.scm @@ -162,13 +162,17 @@ desirable for building Bitcoin Core release binaries." (define (make-gcc-with-pthreads gcc) (package-with-extra-configure-variable gcc "--enable-threads" "posix")) +;; Required to support std::filesystem for mingw-w64 target. +(define (make-gcc-without-newlib gcc) + (package-with-extra-configure-variable gcc "--with-newlib" "no")) + (define (make-mingw-pthreads-cross-toolchain target) "Create a cross-compilation toolchain package for TARGET" (let* ((xbinutils (cross-binutils target)) (pthreads-xlibc mingw-w64-x86_64-winpthreads) (pthreads-xgcc (make-gcc-with-pthreads (cross-gcc target - #:xgcc (make-ssp-fixed-gcc base-gcc) + #:xgcc (make-gcc-without-newlib (make-ssp-fixed-gcc base-gcc)) #:xbinutils xbinutils #:libc pthreads-xlibc)))) ;; Define a meta-package that propagates the resulting XBINUTILS, XLIBC, and diff --git a/contrib/macdeploy/README.md b/contrib/macdeploy/README.md index df7eac3ec8..ce69079e29 100644 --- a/contrib/macdeploy/README.md +++ b/contrib/macdeploy/README.md @@ -12,12 +12,14 @@ When complete, it will have produced `Bitcoin-Core.dmg`. ### Step 1: Obtaining `Xcode.app` +A free Apple Developer Account is required to proceed. + Our current macOS SDK (`Xcode-12.2-12B45b-extracted-SDK-with-libcxx-headers.tar.gz`) can be extracted from [Xcode_12.2.xip](https://download.developer.apple.com/Developer_Tools/Xcode_12.2/Xcode_12.2.xip). Alternatively, after logging in to your account go to 'Downloads', then 'More' -and look for [`Xcode_12.2`](https://download.developer.apple.com/Developer_Tools/Xcode_12.2/Xcode_12.2.xip). +and search for [`Xcode_12.2`](https://developer.apple.com/download/all/?q=Xcode%2012.2). An Apple ID and cookies enabled for the hostname are needed to download this. The `sha256sum` of the archive should be `28d352f8c14a43d9b8a082ac6338dc173cb153f964c6e8fb6ba389e5be528bd0`. @@ -78,19 +80,9 @@ This version of `cctools` has been patched to use the current version of `clang` and its `libLTO.so` rather than those from `llvmgcc`, as it was originally done in `toolchain4`. To complicate things further, all builds must target an Apple SDK. These SDKs are free to -download, but not redistributable. To obtain it, register for an Apple Developer Account, -then download [Xcode_12.1](https://download.developer.apple.com/Developer_Tools/Xcode_12.1/Xcode_12.1.xip). - -This file is many gigabytes in size, but most (but not all) of what we need is -contained only in a single directory: - -```bash -Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk -``` - -See the SDK Extraction notes above for how to obtain it. +download, but not redistributable. See the SDK Extraction notes above for how to obtain it. -The Guix process build 2 sets of files: Linux tools, then Apple binaries which are +The Guix process builds 2 sets of files: Linux tools, then Apple binaries which are created using these tools. The build process has been designed to avoid including the SDK's files in Guix's outputs. All interim tarballs are fully deterministic and may be freely redistributed. diff --git a/contrib/signet/getcoins.py b/contrib/signet/getcoins.py index f1d1de9cfd..147d12600d 100755 --- a/contrib/signet/getcoins.py +++ b/contrib/signet/getcoins.py @@ -8,6 +8,7 @@ import io import requests import subprocess import sys +import xml.etree.ElementTree DEFAULT_GLOBAL_FAUCET = 'https://signetfaucet.com/claim' DEFAULT_GLOBAL_CAPTCHA = 'https://signetfaucet.com/captcha' @@ -88,20 +89,17 @@ def bitcoin_cli(rpc_command_and_params): try: return subprocess.check_output(argv).strip().decode() except FileNotFoundError: - print('The binary', args.cmd, 'could not be found.') - exit(1) + raise SystemExit(f"The binary {args.cmd} could not be found") except subprocess.CalledProcessError: cmdline = ' '.join(argv) - print(f'-----\nError while calling "{cmdline}" (see output above).') - exit(1) + raise SystemExit(f"-----\nError while calling {cmdline} (see output above).") if args.faucet.lower() == DEFAULT_GLOBAL_FAUCET: # Get the hash of the block at height 1 of the currently active signet chain curr_signet_hash = bitcoin_cli(['getblockhash', '1']) if curr_signet_hash != GLOBAL_FIRST_BLOCK_HASH: - print('The global faucet cannot be used with a custom Signet network. Please use the global signet or setup your custom faucet to use this functionality.\n') - exit(1) + raise SystemExit('The global faucet cannot be used with a custom Signet network. Please use the global signet or setup your custom faucet to use this functionality.\n') else: # For custom faucets, don't request captcha by default. if args.captcha == DEFAULT_GLOBAL_CAPTCHA: @@ -120,28 +118,32 @@ session = requests.Session() if args.captcha != '': # Retrieve a captcha try: res = session.get(args.captcha) - except: - print('Unexpected error when contacting faucet:', sys.exc_info()[0]) - exit(1) + res.raise_for_status() + except requests.exceptions.RequestException as e: + raise SystemExit(f"Unexpected error when contacting faucet: {e}") + + # Size limitation + svg = xml.etree.ElementTree.fromstring(res.content) + if svg.attrib.get('width') != '150' or svg.attrib.get('height') != '50': + raise SystemExit("Captcha size doesn't match expected dimensions 150x50") # Convert SVG image to PPM, and load it try: - rv = subprocess.run([args.imagemagick, '-', '-depth', '8', 'ppm:-'], input=res.content, check=True, capture_output=True) + rv = subprocess.run([args.imagemagick, 'svg:-', '-depth', '8', 'ppm:-'], input=res.content, check=True, capture_output=True) except FileNotFoundError: - print('The binary', args.imagemagick, 'could not be found. Please make sure ImageMagick (or a compatible fork) is installed and that the correct path is specified.') - exit(1) + raise SystemExit(f"The binary {args.imagemagick} could not be found. Please make sure ImageMagick (or a compatible fork) is installed and that the correct path is specified.") + img = PPMImage(io.BytesIO(rv.stdout)) # Terminal interaction print_image(img) - print('Enter captcha: ', end='') - data['captcha'] = input() + print(f"Captcha from URL {args.captcha}") + data['captcha'] = input('Enter captcha: ') try: res = session.post(args.faucet, data=data) except: - print('Unexpected error when contacting faucet:', sys.exc_info()[0]) - exit(1) + raise SystemExit(f"Unexpected error when contacting faucet: {sys.exc_info()[0]}") # Display the output as per the returned status code if res: diff --git a/contrib/valgrind.supp b/contrib/valgrind.supp index 35f3d792ff..99ca305fe7 100644 --- a/contrib/valgrind.supp +++ b/contrib/valgrind.supp @@ -13,8 +13,8 @@ # # Note that suppressions may depend on OS and/or library versions. # Tested on: -# * aarch64 (Ubuntu 20.04 system libs, without gui) -# * x86_64 (Ubuntu 18.04 system libs, without gui) +# * aarch64 (Ubuntu 22.04 system libs, clang, without gui) +# * x86_64 (Ubuntu 22.04 system libs, clang, without gui) { Suppress libstdc++ warning - https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65434 Memcheck:Leak @@ -113,12 +113,6 @@ fun:GetCoin } { - Suppress wcsnrtombs glibc SSE4 warning (could be related: https://stroika.atlassian.net/browse/STK-626) - Memcheck:Addr16 - fun:__wcsnlen_sse4_1 - fun:wcsnrtombs -} -{ Suppress boost warning Memcheck:Leak fun:_Znwm @@ -129,17 +123,6 @@ fun:main } { - Suppress boost still reachable memory warning - Memcheck:Leak - match-leak-kinds: reachable - fun:_Znwm - ... - fun:_M_construct_aux<char*> - fun:_M_construct<char*> - fun:basic_string - fun:path -} -{ Suppress LogInstance still reachable memory warning Memcheck:Leak match-leak-kinds: reachable diff --git a/depends/Makefile b/depends/Makefile index 003778b375..723509c81d 100644 --- a/depends/Makefile +++ b/depends/Makefile @@ -77,6 +77,8 @@ full_build_os:=$(subst $(build_arch)-$(build_vendor)-,,$(build)) build_os:=$(findstring linux,$(full_build_os)) build_os+=$(findstring darwin,$(full_build_os)) build_os+=$(findstring freebsd,$(full_build_os)) +build_os+=$(findstring netbsd,$(full_build_os)) +build_os+=$(findstring openbsd,$(full_build_os)) build_os:=$(strip $(build_os)) ifeq ($(build_os),) build_os=$(full_build_os) @@ -88,6 +90,8 @@ full_host_os:=$(subst $(host_arch)-$(host_vendor)-,,$(canonical_host)) host_os:=$(findstring linux,$(full_host_os)) host_os+=$(findstring darwin,$(full_host_os)) host_os+=$(findstring freebsd,$(full_host_os)) +host_os+=$(findstring netbsd,$(full_host_os)) +host_os+=$(findstring openbsd,$(full_host_os)) host_os+=$(findstring mingw32,$(full_host_os)) ifeq (android,$(findstring android,$(full_host_os))) @@ -182,7 +186,7 @@ $(host_prefix)/.stamp_$(final_build_id): $(native_packages) $(packages) mkdir -p $(@D) echo copying packages: $^ echo to: $(@D) - cd $(@D); $(foreach package,$^, tar xf $($(package)_cached); ) + cd $(@D); $(foreach package,$^, $(build_TAR) xf $($(package)_cached); ) touch $@ # $PATH is not preserved between ./configure and make by convention. Its diff --git a/depends/README.md b/depends/README.md index 6b6af99dee..f7647198c6 100644 --- a/depends/README.md +++ b/depends/README.md @@ -84,6 +84,10 @@ For linux S390X cross compilation: sudo apt-get install g++-s390x-linux-gnu binutils-s390x-linux-gnu +### Install the required dependencies: OpenBSD + + pkg_add bash gtar + ### Dependency Options The following can be set when running make: `make FOO=bar` diff --git a/depends/builders/default.mk b/depends/builders/default.mk index f097db65d6..0370fb9acb 100644 --- a/depends/builders/default.mk +++ b/depends/builders/default.mk @@ -1,6 +1,7 @@ default_build_CC = gcc default_build_CXX = g++ default_build_AR = ar +default_build_TAR = tar default_build_RANLIB = ranlib default_build_STRIP = strip default_build_NM = nm @@ -12,7 +13,7 @@ build_$(build_os)_$1 ?= $$(default_build_$1) build_$(build_arch)_$(build_os)_$1 ?= $$(build_$(build_os)_$1) build_$1=$$(build_$(build_arch)_$(build_os)_$1) endef -$(foreach var,CC CXX AR RANLIB NM STRIP SHA256SUM DOWNLOAD OTOOL INSTALL_NAME_TOOL,$(eval $(call add_build_tool_func,$(var)))) +$(foreach var,CC CXX AR TAR RANLIB NM STRIP SHA256SUM DOWNLOAD OTOOL INSTALL_NAME_TOOL,$(eval $(call add_build_tool_func,$(var)))) define add_build_flags_func build_$(build_arch)_$(build_os)_$1 += $(build_$(build_os)_$1) build_$1=$$(build_$(build_arch)_$(build_os)_$1) diff --git a/depends/builders/netbsd.mk b/depends/builders/netbsd.mk new file mode 100644 index 0000000000..b7cf1f7514 --- /dev/null +++ b/depends/builders/netbsd.mk @@ -0,0 +1,2 @@ +build_netbsd_SHA256SUM = shasum -a 256 +build_netbsd_DOWNLOAD = curl --location --fail --connect-timeout $(DOWNLOAD_CONNECT_TIMEOUT) --retry $(DOWNLOAD_RETRIES) -o diff --git a/depends/builders/openbsd.mk b/depends/builders/openbsd.mk new file mode 100644 index 0000000000..44825d106a --- /dev/null +++ b/depends/builders/openbsd.mk @@ -0,0 +1,7 @@ +build_openbsd_CC = clang +build_openbsd_CXX = clang++ + +build_openbsd_SHA256SUM = sha256 +build_openbsd_DOWNLOAD = curl --location --fail --connect-timeout $(DOWNLOAD_CONNECT_TIMEOUT) --retry $(DOWNLOAD_RETRIES) -o + +build_openbsd_TAR = gtar diff --git a/depends/funcs.mk b/depends/funcs.mk index 453d92cfb2..c4ad109c69 100644 --- a/depends/funcs.mk +++ b/depends/funcs.mk @@ -84,7 +84,7 @@ $(1)_download_path_fixed=$(subst :,\:,$$($(1)_download_path)) #default commands # The default behavior for tar will try to set ownership when running as uid 0 and may not succeed, --no-same-owner disables this behavior $(1)_fetch_cmds ?= $(call fetch_file,$(1),$(subst \:,:,$$($(1)_download_path_fixed)),$$($(1)_download_file),$($(1)_file_name),$($(1)_sha256_hash)) -$(1)_extract_cmds ?= mkdir -p $$($(1)_extract_dir) && echo "$$($(1)_sha256_hash) $$($(1)_source)" > $$($(1)_extract_dir)/.$$($(1)_file_name).hash && $(build_SHA256SUM) -c $$($(1)_extract_dir)/.$$($(1)_file_name).hash && tar --no-same-owner --strip-components=1 -xf $$($(1)_source) +$(1)_extract_cmds ?= mkdir -p $$($(1)_extract_dir) && echo "$$($(1)_sha256_hash) $$($(1)_source)" > $$($(1)_extract_dir)/.$$($(1)_file_name).hash && $(build_SHA256SUM) -c $$($(1)_extract_dir)/.$$($(1)_file_name).hash && $(build_TAR) --no-same-owner --strip-components=1 -xf $$($(1)_source) $(1)_preprocess_cmds ?= $(1)_build_cmds ?= $(1)_config_cmds ?= @@ -207,7 +207,7 @@ $($(1)_preprocessed): | $($(1)_extracted) touch $$@ $($(1)_configured): | $($(1)_dependencies) $($(1)_preprocessed) echo Configuring $(1)... - rm -rf $(host_prefix); mkdir -p $(host_prefix)/lib; cd $(host_prefix); $(foreach package,$($(1)_all_dependencies), tar --no-same-owner -xf $($(package)_cached); ) + rm -rf $(host_prefix); mkdir -p $(host_prefix)/lib; cd $(host_prefix); $(foreach package,$($(1)_all_dependencies), $(build_TAR) --no-same-owner -xf $($(package)_cached); ) mkdir -p $$(@D) +cd $$(@D); $($(1)_config_env) $(call $(1)_config_cmds, $(1)) touch $$@ @@ -228,7 +228,7 @@ $($(1)_postprocessed): | $($(1)_staged) touch $$@ $($(1)_cached): | $($(1)_dependencies) $($(1)_postprocessed) echo Caching $(1)... - cd $$($(1)_staging_dir)/$(host_prefix); find . | sort | tar --no-recursion -czf $$($(1)_staging_dir)/$$(@F) -T - + cd $$($(1)_staging_dir)/$(host_prefix); find . | sort | $(build_TAR) --no-recursion -czf $$($(1)_staging_dir)/$$(@F) -T - mkdir -p $$(@D) rm -rf $$(@D) && mkdir -p $$(@D) mv $$($(1)_staging_dir)/$$(@F) $$(@) diff --git a/depends/hosts/freebsd.mk b/depends/hosts/freebsd.mk index 307f844331..0a62347b57 100644 --- a/depends/hosts/freebsd.mk +++ b/depends/hosts/freebsd.mk @@ -1,11 +1,11 @@ freebsd_CFLAGS=-pipe -freebsd_CFLAGS_CXXFLAGS=$(freebsd_CFLAGS) +freebsd_CXXFLAGS=$(freebsd_CFLAGS) -freebsd_CFLAGS_release_CFLAGS=-O2 -freebsd_CFLAGS_release_CXXFLAGS=$(freebsd_release_CFLAGS) +freebsd_release_CFLAGS=-O2 +freebsd_release_CXXFLAGS=$(freebsd_release_CFLAGS) -freebsd_CFLAGS_debug_CFLAGS=-O1 -freebsd_CFLAGS_debug_CXXFLAGS=$(freebsd_debug_CFLAGS) +freebsd_debug_CFLAGS=-O1 +freebsd_debug_CXXFLAGS=$(freebsd_debug_CFLAGS) ifeq (86,$(findstring 86,$(build_arch))) i686_freebsd_CC=clang -m32 diff --git a/depends/hosts/netbsd.mk b/depends/hosts/netbsd.mk new file mode 100644 index 0000000000..b3e4545a64 --- /dev/null +++ b/depends/hosts/netbsd.mk @@ -0,0 +1,31 @@ +netbsd_CFLAGS=-pipe +netbsd_CXXFLAGS=$(netbsd_CFLAGS) + +netbsd_release_CFLAGS=-O2 +netbsd_release_CXXFLAGS=$(netbsd_release_CFLAGS) + +netbsd_debug_CFLAGS=-O1 +netbsd_debug_CXXFLAGS=$(netbsd_debug_CFLAGS) + +ifeq (86,$(findstring 86,$(build_arch))) +i686_netbsd_CC=gcc -m32 +i686_netbsd_CXX=g++ -m32 +i686_netbsd_AR=ar +i686_netbsd_RANLIB=ranlib +i686_netbsd_NM=nm +i686_netbsd_STRIP=strip + +x86_64_netbsd_CC=gcc -m64 +x86_64_netbsd_CXX=g++ -m64 +x86_64_netbsd_AR=ar +x86_64_netbsd_RANLIB=ranlib +x86_64_netbsd_NM=nm +x86_64_netbsd_STRIP=strip +else +i686_netbsd_CC=$(default_host_CC) -m32 +i686_netbsd_CXX=$(default_host_CXX) -m32 +x86_64_netbsd_CC=$(default_host_CC) -m64 +x86_64_netbsd_CXX=$(default_host_CXX) -m64 +endif + +netbsd_cmake_system=NetBSD diff --git a/depends/hosts/openbsd.mk b/depends/hosts/openbsd.mk new file mode 100644 index 0000000000..dc8393e04c --- /dev/null +++ b/depends/hosts/openbsd.mk @@ -0,0 +1,31 @@ +openbsd_CFLAGS=-pipe +openbsd_CFLAGS_CXXFLAGS=$(openbsd_CFLAGS) + +openbsd_CFLAGS_release_CFLAGS=-O2 +openbsd_CFLAGS_release_CXXFLAGS=$(openbsd_release_CFLAGS) + +openbsd_CFLAGS_debug_CFLAGS=-O1 +openbsd_CFLAGS_debug_CXXFLAGS=$(openbsd_debug_CFLAGS) + +ifeq (86,$(findstring 86,$(build_arch))) +i686_openbsd_CC=clang -m32 +i686_openbsd_CXX=clang++ -m32 +i686_openbsd_AR=ar +i686_openbsd_RANLIB=ranlib +i686_openbsd_NM=nm +i686_openbsd_STRIP=strip + +x86_64_openbsd_CC=clang -m64 +x86_64_openbsd_CXX=clang++ -m64 +x86_64_openbsd_AR=ar +x86_64_openbsd_RANLIB=ranlib +x86_64_openbsd_NM=nm +x86_64_openbsd_STRIP=strip +else +i686_openbsd_CC=$(default_host_CC) -m32 +i686_openbsd_CXX=$(default_host_CXX) -m32 +x86_64_openbsd_CC=$(default_host_CC) -m64 +x86_64_openbsd_CXX=$(default_host_CXX) -m64 +endif + +openbsd_cmake_system=OpenBSD diff --git a/depends/packages/bdb.mk b/depends/packages/bdb.mk index 4e74c95a8e..dc536fd399 100644 --- a/depends/packages/bdb.mk +++ b/depends/packages/bdb.mk @@ -11,6 +11,8 @@ $(package)_config_opts=--disable-shared --enable-cxx --disable-replication --ena $(package)_config_opts_mingw32=--enable-mingw $(package)_config_opts_linux=--with-pic $(package)_config_opts_freebsd=--with-pic +$(package)_config_opts_netbsd=--with-pic +$(package)_config_opts_openbsd=--with-pic $(package)_config_opts_android=--with-pic $(package)_cflags+=-Wno-error=implicit-function-declaration $(package)_cxxflags+=-std=c++17 diff --git a/depends/packages/boost.mk b/depends/packages/boost.mk index 820a7ff4e7..11fed2ea13 100644 --- a/depends/packages/boost.mk +++ b/depends/packages/boost.mk @@ -1,47 +1,10 @@ package=boost -$(package)_version=1_71_0 -$(package)_download_path=https://boostorg.jfrog.io/artifactory/main/release/$(subst _,.,$($(package)_version))/source/ -$(package)_file_name=boost_$($(package)_version).tar.bz2 +$(package)_version=1.71.0 +$(package)_download_path=https://boostorg.jfrog.io/artifactory/main/release/$($(package)_version)/source/ +$(package)_file_name=boost_$(subst .,_,$($(package)_version)).tar.bz2 $(package)_sha256_hash=d73a8da01e8bf8c7eda40b4c84915071a8c8a0df4a6734537ddde4a8580524ee -$(package)_dependencies=native_b2 - -define $(package)_set_vars -$(package)_config_opts_release=variant=release -$(package)_config_opts_debug=variant=debug -$(package)_config_opts=--layout=tagged --build-type=complete --user-config=user-config.jam -$(package)_config_opts+=threading=multi link=static -sNO_COMPRESSION=1 -$(package)_config_opts_linux=target-os=linux threadapi=pthread runtime-link=shared -$(package)_config_opts_darwin=target-os=darwin runtime-link=shared -$(package)_config_opts_mingw32=target-os=windows binary-format=pe threadapi=win32 runtime-link=static -$(package)_config_opts_x86_64=architecture=x86 address-model=64 -$(package)_config_opts_i686=architecture=x86 address-model=32 -$(package)_config_opts_aarch64=address-model=64 -$(package)_config_opts_armv7a=address-model=32 -ifneq (,$(findstring clang,$($(package)_cxx))) -$(package)_toolset_$(host_os)=clang -else -$(package)_toolset_$(host_os)=gcc -endif -$(package)_config_libraries=test -$(package)_cxxflags+=-std=c++17 -$(package)_cxxflags_linux=-fPIC -$(package)_cxxflags_freebsd=-fPIC -$(package)_cxxflags_android=-fPIC -$(package)_cxxflags_x86_64=-fcf-protection=full -endef - -define $(package)_preprocess_cmds - echo "using $($(package)_toolset_$(host_os)) : : $($(package)_cxx) : <cflags>\"$($(package)_cflags)\" <cxxflags>\"$($(package)_cxxflags)\" <compileflags>\"$($(package)_cppflags)\" <linkflags>\"$($(package)_ldflags)\" <archiver>\"$($(package)_ar)\" <striper>\"$(host_STRIP)\" <ranlib>\"$(host_RANLIB)\" <rc>\"$(host_WINDRES)\" : ;" > user-config.jam -endef - -define $(package)_config_cmds - ./bootstrap.sh --without-icu --with-libraries=$($(package)_config_libraries) --with-toolset=$($(package)_toolset_$(host_os)) --with-bjam=b2 -endef - -define $(package)_build_cmds - b2 -d2 -j2 -d1 --prefix=$($(package)_staging_prefix_dir) $($(package)_config_opts) toolset=$($(package)_toolset_$(host_os)) stage -endef define $(package)_stage_cmds - b2 -d0 -j4 --prefix=$($(package)_staging_prefix_dir) $($(package)_config_opts) toolset=$($(package)_toolset_$(host_os)) --no-cmake-config install + mkdir -p $($(package)_staging_prefix_dir)/include && \ + cp -r boost $($(package)_staging_prefix_dir)/include endef diff --git a/depends/packages/expat.mk b/depends/packages/expat.mk index c2089d1ccb..50791ebc6e 100644 --- a/depends/packages/expat.mk +++ b/depends/packages/expat.mk @@ -1,6 +1,6 @@ package=expat $(package)_version=2.4.1 -$(package)_download_path=https://github.com/libexpat/libexpat/releases/download/R_2_4_1/ +$(package)_download_path=https://github.com/libexpat/libexpat/releases/download/R_$(subst .,_,$($(package)_version))/ $(package)_file_name=$(package)-$($(package)_version).tar.xz $(package)_sha256_hash=cf032d0dba9b928636548e32b327a2d66b1aab63c4f4a13dd132c2d1d2f2fb6a diff --git a/depends/packages/libevent.mk b/depends/packages/libevent.mk index 2305f96d27..748ed510c1 100644 --- a/depends/packages/libevent.mk +++ b/depends/packages/libevent.mk @@ -13,6 +13,8 @@ define $(package)_set_vars $(package)_config_opts_release=--disable-debug-mode $(package)_config_opts_linux=--with-pic $(package)_config_opts_freebsd=--with-pic + $(package)_config_opts_netbsd=--with-pic + $(package)_config_opts_openbsd=--with-pic $(package)_config_opts_android=--with-pic $(package)_cppflags_mingw32=-D_WIN32_WINNT=0x0601 endef diff --git a/depends/packages/native_b2.mk b/depends/packages/native_b2.mk deleted file mode 100644 index aaa37cdcfa..0000000000 --- a/depends/packages/native_b2.mk +++ /dev/null @@ -1,20 +0,0 @@ -package=native_b2 -$(package)_version=$(boost_version) -$(package)_download_path=$(boost_download_path) -$(package)_file_name=$(boost_file_name) -$(package)_sha256_hash=$(boost_sha256_hash) -$(package)_build_subdir=tools/build/src/engine -ifneq (,$(findstring clang,$($(package)_cxx))) -$(package)_toolset_$(host_os)=clang -else -$(package)_toolset_$(host_os)=gcc -endif - -define $(package)_build_cmds - CXX="$($(package)_cxx)" CXXFLAGS="$($(package)_cxxflags)" ./build.sh "$($(package)_toolset_$(host_os))" -endef - -define $(package)_stage_cmds - mkdir -p "$($(package)_staging_prefix_dir)"/bin/ && \ - cp b2 "$($(package)_staging_prefix_dir)"/bin/ -endef diff --git a/depends/packages/native_clang.mk b/depends/packages/native_clang.mk index 25ac77c1a3..245269a9d3 100644 --- a/depends/packages/native_clang.mk +++ b/depends/packages/native_clang.mk @@ -2,11 +2,9 @@ package=native_clang $(package)_version=10.0.1 $(package)_download_path=https://github.com/llvm/llvm-project/releases/download/llvmorg-$($(package)_version) ifneq (,$(findstring aarch64,$(BUILD))) -$(package)_download_file=clang+llvm-$($(package)_version)-aarch64-linux-gnu.tar.xz $(package)_file_name=clang+llvm-$($(package)_version)-aarch64-linux-gnu.tar.xz $(package)_sha256_hash=90dc69a4758ca15cd0ffa45d07fbf5bf4309d47d2c7745a9f0735ecffde9c31f else -$(package)_download_file=clang+llvm-$($(package)_version)-x86_64-linux-gnu-ubuntu-16.04.tar.xz $(package)_file_name=clang+llvm-$($(package)_version)-x86_64-linux-gnu-ubuntu-16.04.tar.xz $(package)_sha256_hash=48b83ef827ac2c213d5b64f5ad7ed082c8bcb712b46644e0dc5045c6f462c231 endif @@ -18,15 +16,10 @@ endef define $(package)_stage_cmds mkdir -p $($(package)_staging_prefix_dir)/lib/clang/$($(package)_version)/include && \ mkdir -p $($(package)_staging_prefix_dir)/bin && \ - mkdir -p $($(package)_staging_prefix_dir)/include && \ cp bin/clang $($(package)_staging_prefix_dir)/bin/ && \ cp -P bin/clang++ $($(package)_staging_prefix_dir)/bin/ && \ cp bin/dsymutil $($(package)_staging_prefix_dir)/bin/$(host)-dsymutil && \ cp bin/llvm-config $($(package)_staging_prefix_dir)/bin/ && \ cp lib/libLTO.so $($(package)_staging_prefix_dir)/lib/ && \ - cp -rf lib/clang/$($(package)_version)/include/* $($(package)_staging_prefix_dir)/lib/clang/$($(package)_version)/include/ -endef - -define $(package)_postprocess_cmds - rmdir include + cp -r lib/clang/$($(package)_version)/include/* $($(package)_staging_prefix_dir)/lib/clang/$($(package)_version)/include/ endef diff --git a/depends/packages/native_libtapi.mk b/depends/packages/native_libtapi.mk index 60b898da5f..1633213a42 100644 --- a/depends/packages/native_libtapi.mk +++ b/depends/packages/native_libtapi.mk @@ -1,7 +1,6 @@ package=native_libtapi $(package)_version=664b8414f89612f2dfd35a9b679c345aa5389026 $(package)_download_path=https://github.com/tpoechtrager/apple-libtapi/archive -$(package)_download_file=$($(package)_version).tar.gz $(package)_file_name=$($(package)_version).tar.gz $(package)_sha256_hash=62e419c12d1c9fad67cc1cd523132bc00db050998337c734c15bc8d73cc02b61 diff --git a/depends/packages/packages.mk b/depends/packages/packages.mk index 4c66b3bdb9..991db7f46e 100644 --- a/depends/packages/packages.mk +++ b/depends/packages/packages.mk @@ -25,8 +25,6 @@ usdt_linux_packages=systemtap darwin_native_packages = native_ds_store native_mac_alias -$(host_arch)_$(host_os)_native_packages += native_b2 - ifneq ($(build_os),darwin) darwin_native_packages += native_cctools native_libtapi native_libdmg-hfsplus diff --git a/depends/packages/qt.mk b/depends/packages/qt.mk index 313b22218c..9cdfd21d2c 100644 --- a/depends/packages/qt.mk +++ b/depends/packages/qt.mk @@ -201,11 +201,11 @@ define $(package)_extract_cmds echo "$($(package)_qttools_sha256_hash) $($(package)_source_dir)/$($(package)_qttools_file_name)" >> $($(package)_extract_dir)/.$($(package)_file_name).hash && \ $(build_SHA256SUM) -c $($(package)_extract_dir)/.$($(package)_file_name).hash && \ mkdir qtbase && \ - tar --no-same-owner --strip-components=1 -xf $($(package)_source) -C qtbase && \ + $(build_TAR) --no-same-owner --strip-components=1 -xf $($(package)_source) -C qtbase && \ mkdir qttranslations && \ - tar --no-same-owner --strip-components=1 -xf $($(package)_source_dir)/$($(package)_qttranslations_file_name) -C qttranslations && \ + $(build_TAR) --no-same-owner --strip-components=1 -xf $($(package)_source_dir)/$($(package)_qttranslations_file_name) -C qttranslations && \ mkdir qttools && \ - tar --no-same-owner --strip-components=1 -xf $($(package)_source_dir)/$($(package)_qttools_file_name) -C qttools + $(build_TAR) --no-same-owner --strip-components=1 -xf $($(package)_source_dir)/$($(package)_qttools_file_name) -C qttools endef # Preprocessing steps work as follows: diff --git a/depends/packages/sqlite.mk b/depends/packages/sqlite.mk index 36b6df7f6e..126781ceeb 100644 --- a/depends/packages/sqlite.mk +++ b/depends/packages/sqlite.mk @@ -8,6 +8,8 @@ define $(package)_set_vars $(package)_config_opts=--disable-shared --disable-readline --disable-dynamic-extensions --enable-option-checking $(package)_config_opts_linux=--with-pic $(package)_config_opts_freebsd=--with-pic +$(package)_config_opts_netbsd=--with-pic +$(package)_config_opts_openbsd=--with-pic endef define $(package)_preprocess_cmds diff --git a/depends/packages/zeromq.mk b/depends/packages/zeromq.mk index c56ec5c2bd..c74ae15b31 100644 --- a/depends/packages/zeromq.mk +++ b/depends/packages/zeromq.mk @@ -13,6 +13,8 @@ define $(package)_set_vars $(package)_config_opts += --disable-Werror --disable-drafts --enable-option-checking $(package)_config_opts_linux=--with-pic $(package)_config_opts_freebsd=--with-pic + $(package)_config_opts_netbsd=--with-pic + $(package)_config_opts_openbsd=--with-pic $(package)_config_opts_android=--with-pic $(package)_cxxflags+=-std=c++17 endef diff --git a/doc/build-unix.md b/doc/build-unix.md index 38844cdf81..15fe63d047 100644 --- a/doc/build-unix.md +++ b/doc/build-unix.md @@ -82,7 +82,7 @@ Build requirements: Now, you can either build from self-compiled [depends](/depends/README.md) or install the required dependencies: - sudo apt-get install libevent-dev libboost-dev libboost-test-dev + sudo apt-get install libevent-dev libboost-dev SQLite is required for the descriptor wallet: diff --git a/doc/descriptors.md b/doc/descriptors.md index 57a0f99d70..318d065fdb 100644 --- a/doc/descriptors.md +++ b/doc/descriptors.md @@ -90,12 +90,12 @@ Descriptors consist of several types of expressions. The top level expression is - Optionally followed by a single `/*` or `/*'` final step to denote all (direct) unhardened or hardened children. - The usage of hardened derivation steps requires providing the private key. +(Anywhere a `'` suffix is permitted to denote hardened derivation, the suffix `h` can be used instead.) + `TREE` expressions: - any `SCRIPT` expression - An open brace `{`, a `TREE` expression, a comma `,`, a `TREE` expression, and a closing brace `}` -(Anywhere a `'` suffix is permitted to denote hardened derivation, the suffix `h` can be used instead.) - `ADDR` expressions are any type of supported address: - P2PKH addresses (base58, of the form `1...` for mainnet or `[nm]...` for testnet). Note that P2PKH addresses in descriptors cannot be used for P2PK outputs (use the `pk` function instead). - P2SH addresses (base58, of the form `3...` for mainnet or `2...` for testnet, defined in [BIP 13](https://github.com/bitcoin/bips/blob/master/bip-0013.mediawiki)). diff --git a/doc/release-notes-23508.md b/doc/release-notes-23508.md deleted file mode 100644 index 098654e00b..0000000000 --- a/doc/release-notes-23508.md +++ /dev/null @@ -1,9 +0,0 @@ -Updated RPCs ------------- - -- Information on soft fork status has been moved from `getblockchaininfo` - to `getdeploymentinfo` which allows querying soft fork status at any - block, rather than just at the chain tip. Inclusion of soft fork - status in `getblockchaininfo` can currently be restored using the - configuration `-deprecatedrpc=softforks`, but this will be removed in - a future release. (#23508) diff --git a/doc/release-notes.md b/doc/release-notes.md index 7a47d76bba..f50e5ce138 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -115,6 +115,15 @@ Updated RPCs New RPCs -------- +- Information on soft fork status has been moved from `getblockchaininfo` + to the new `getdeploymentinfo` RPC which allows querying soft fork status at any + block, rather than just at the chain tip. Inclusion of soft fork + status in `getblockchaininfo` can currently be restored using the + configuration `-deprecatedrpc=softforks`, but this will be removed in + a future release. Note that in either case, the `status` field + now reflects the status of the current block rather than the next + block. (#23508) + Build System ------------ diff --git a/doc/release-process.md b/doc/release-process.md index f786b345b1..c5dba46238 100644 --- a/doc/release-process.md +++ b/doc/release-process.md @@ -97,7 +97,7 @@ Checkout the Bitcoin Core version you'd like to build: pushd ./bitcoin SIGNER='(your builder key, ie bluematt, sipa, etc)' VERSION='(new version without v-prefix, e.g. 0.20.0)' -git fetch "v${VERSION}" +git fetch origin "v${VERSION}" git checkout "v${VERSION}" popd ``` @@ -118,7 +118,7 @@ details. ### Build and attest to build outputs: Follow the relevant Guix README.md sections: -- [Performing a build](/contrib/guix/README.md#performing-a-build) +- [Building](/contrib/guix/README.md#building) - [Attesting to build outputs](/contrib/guix/README.md#attesting-to-build-outputs) ### Verify other builders' signatures to your own. (Optional) diff --git a/share/setup.nsi.in b/share/setup.nsi.in index c7b149345c..b31ba7a5b4 100644 --- a/share/setup.nsi.in +++ b/share/setup.nsi.in @@ -72,14 +72,14 @@ ShowUninstDetails show Section -Main SEC0000 SetOutPath $INSTDIR SetOverwrite on - File @abs_top_srcdir@/release/@BITCOIN_GUI_NAME@@EXEEXT@ + File @abs_top_builddir@/release/@BITCOIN_GUI_NAME@@EXEEXT@ File /oname=COPYING.txt @abs_top_srcdir@/COPYING File /oname=readme.txt @abs_top_srcdir@/doc/README_windows.txt SetOutPath $INSTDIR\daemon - File @abs_top_srcdir@/release/@BITCOIN_DAEMON_NAME@@EXEEXT@ - File @abs_top_srcdir@/release/@BITCOIN_CLI_NAME@@EXEEXT@ - File @abs_top_srcdir@/release/@BITCOIN_TX_NAME@@EXEEXT@ - File @abs_top_srcdir@/release/@BITCOIN_WALLET_TOOL_NAME@@EXEEXT@ + File @abs_top_builddir@/release/@BITCOIN_DAEMON_NAME@@EXEEXT@ + File @abs_top_builddir@/release/@BITCOIN_CLI_NAME@@EXEEXT@ + File @abs_top_builddir@/release/@BITCOIN_TX_NAME@@EXEEXT@ + File @abs_top_builddir@/release/@BITCOIN_WALLET_TOOL_NAME@@EXEEXT@ SetOutPath $INSTDIR\doc File /r /x Makefile* @abs_top_srcdir@/doc\*.* SetOutPath $INSTDIR diff --git a/src/Makefile.am b/src/Makefile.am index 0b177480c8..417a611181 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -46,9 +46,13 @@ if ENABLE_AVX2 LIBBITCOIN_CRYPTO_AVX2 = crypto/libbitcoin_crypto_avx2.a LIBBITCOIN_CRYPTO += $(LIBBITCOIN_CRYPTO_AVX2) endif -if ENABLE_SHANI -LIBBITCOIN_CRYPTO_SHANI = crypto/libbitcoin_crypto_shani.a -LIBBITCOIN_CRYPTO += $(LIBBITCOIN_CRYPTO_SHANI) +if ENABLE_X86_SHANI +LIBBITCOIN_CRYPTO_X86_SHANI = crypto/libbitcoin_crypto_x86_shani.a +LIBBITCOIN_CRYPTO += $(LIBBITCOIN_CRYPTO_X86_SHANI) +endif +if ENABLE_ARM_SHANI +LIBBITCOIN_CRYPTO_ARM_SHANI = crypto/libbitcoin_crypto_arm_shani.a +LIBBITCOIN_CRYPTO += $(LIBBITCOIN_CRYPTO_ARM_SHANI) endif $(LIBSECP256K1): $(wildcard secp256k1/src/*.h) $(wildcard secp256k1/src/*.c) $(wildcard secp256k1/include/*) @@ -498,11 +502,17 @@ 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_shani_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) -crypto_libbitcoin_crypto_shani_a_CPPFLAGS = $(AM_CPPFLAGS) -crypto_libbitcoin_crypto_shani_a_CXXFLAGS += $(SHANI_CXXFLAGS) -crypto_libbitcoin_crypto_shani_a_CPPFLAGS += -DENABLE_SHANI -crypto_libbitcoin_crypto_shani_a_SOURCES = crypto/sha256_shani.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 # consensus: shared between all executables that validate any consensus rules. libbitcoin_consensus_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) @@ -665,7 +675,7 @@ bitcoin_bin_ldadd = \ $(LIBMEMENV) \ $(LIBSECP256K1) -bitcoin_bin_ldadd += $(BOOST_LIBS) $(BDB_LIBS) $(MINIUPNPC_LIBS) $(NATPMP_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(ZMQ_LIBS) $(SQLITE_LIBS) +bitcoin_bin_ldadd += $(BDB_LIBS) $(MINIUPNPC_LIBS) $(NATPMP_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(ZMQ_LIBS) $(SQLITE_LIBS) bitcoind_SOURCES = $(bitcoin_daemon_sources) init/bitcoind.cpp bitcoind_CPPFLAGS = $(bitcoin_bin_cppflags) @@ -695,7 +705,7 @@ bitcoin_cli_LDADD = \ $(LIBBITCOIN_UTIL) \ $(LIBBITCOIN_CRYPTO) -bitcoin_cli_LDADD += $(BOOST_LIBS) $(EVENT_LIBS) +bitcoin_cli_LDADD += $(EVENT_LIBS) # # bitcoin-tx binary # @@ -715,8 +725,6 @@ bitcoin_tx_LDADD = \ $(LIBBITCOIN_CONSENSUS) \ $(LIBBITCOIN_CRYPTO) \ $(LIBSECP256K1) - -bitcoin_tx_LDADD += $(BOOST_LIBS) # # bitcoin-wallet binary # @@ -734,7 +742,6 @@ bitcoin_wallet_LDADD = \ $(LIBBITCOIN_CONSENSUS) \ $(LIBBITCOIN_CRYPTO) \ $(LIBSECP256K1) \ - $(BOOST_LIBS) \ $(BDB_LIBS) \ $(SQLITE_LIBS) @@ -760,8 +767,6 @@ bitcoin_util_LDADD = \ $(LIBBITCOIN_CONSENSUS) \ $(LIBBITCOIN_CRYPTO) \ $(LIBSECP256K1) - -bitcoin_util_LDADD += $(BOOST_LIBS) # # bitcoinconsensus library # diff --git a/src/Makefile.bench.include b/src/Makefile.bench.include index 2feb31a9e9..0bcce6ebe1 100644 --- a/src/Makefile.bench.include +++ b/src/Makefile.bench.include @@ -75,7 +75,7 @@ bench_bench_bitcoin_SOURCES += bench/coin_selection.cpp bench_bench_bitcoin_SOURCES += bench/wallet_balance.cpp endif -bench_bench_bitcoin_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(MINIUPNPC_LIBS) $(NATPMP_LIBS) $(SQLITE_LIBS) +bench_bench_bitcoin_LDADD += $(BDB_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(MINIUPNPC_LIBS) $(NATPMP_LIBS) $(SQLITE_LIBS) bench_bench_bitcoin_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) $(PTHREAD_FLAGS) CLEAN_BITCOIN_BENCH = bench/*.gcda bench/*.gcno $(GENERATED_BENCH_FILES) diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index 85e3a6e16a..3491f07ee0 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -331,7 +331,7 @@ 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) \ - $(BOOST_LIBS) $(QT_LIBS) $(QT_DBUS_LIBS) $(QR_LIBS) $(BDB_LIBS) $(MINIUPNPC_LIBS) $(NATPMP_LIBS) $(LIBSECP256K1) \ + $(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) bitcoin_qt_libtoolflags = $(AM_LIBTOOLFLAGS) --tag CXX diff --git a/src/Makefile.qttest.include b/src/Makefile.qttest.include index b92d2cb6e2..8e6fa2eb0d 100644 --- a/src/Makefile.qttest.include +++ b/src/Makefile.qttest.include @@ -52,7 +52,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) $(BOOST_LIBS) $(QT_LIBS) $(QT_DBUS_LIBS) $(QT_TEST_LIBS) \ + $(LIBLEVELDB_SSE42) $(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 801745d0c6..e2e08468a7 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -48,7 +48,6 @@ FUZZ_SUITE_LD_COMMON = \ $(LIBUNIVALUE) \ $(LIBLEVELDB) \ $(LIBLEVELDB_SSE42) \ - $(BOOST_LIBS) \ $(LIBMEMENV) \ $(LIBSECP256K1) \ $(MINISKETCH_LIBS) \ @@ -198,7 +197,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) $(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) $(LIBSECP256K1) $(EVENT_LIBS) $(EVENT_PTHREADS_LIBS) $(MINISKETCH_LIBS) + $(LIBLEVELDB) $(LIBLEVELDB_SSE42) $(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) @@ -295,6 +294,7 @@ test_fuzz_fuzz_SOURCES = \ test/fuzz/script_bitcoin_consensus.cpp \ test/fuzz/script_descriptor_cache.cpp \ test/fuzz/script_flags.cpp \ + test/fuzz/script_format.cpp \ test/fuzz/script_interpreter.cpp \ test/fuzz/script_ops.cpp \ test/fuzz/script_sigcache.cpp \ diff --git a/src/core_write.cpp b/src/core_write.cpp index 5ea62cf3ed..c4b6b8d27e 100644 --- a/src/core_write.cpp +++ b/src/core_write.cpp @@ -65,7 +65,7 @@ std::string FormatScript(const CScript& script) ret += strprintf("0x%x ", HexStr(std::vector<uint8_t>(it2, script.end()))); break; } - return ret.substr(0, ret.size() - 1); + return ret.substr(0, ret.empty() ? ret.npos : ret.size() - 1); } const std::map<unsigned char, std::string> mapSigHashTypes = { diff --git a/src/crypto/sha256.cpp b/src/crypto/sha256.cpp index e35d526d35..cde543e68c 100644 --- a/src/crypto/sha256.cpp +++ b/src/crypto/sha256.cpp @@ -10,6 +10,16 @@ #include <compat/cpuid.h> +#if defined(__linux__) && defined(ENABLE_ARM_SHANI) && !defined(BUILD_BITCOIN_INTERNAL) +#include <sys/auxv.h> +#include <asm/hwcap.h> +#endif + +#if defined(MAC_OSX) && defined(ENABLE_ARM_SHANI) && !defined(BUILD_BITCOIN_INTERNAL) +#include <sys/types.h> +#include <sys/sysctl.h> +#endif + #if defined(__x86_64__) || defined(__amd64__) || defined(__i386__) #if defined(USE_ASM) namespace sha256_sse4 @@ -29,16 +39,26 @@ namespace sha256d64_avx2 void Transform_8way(unsigned char* out, const unsigned char* in); } -namespace sha256d64_shani +namespace sha256d64_x86_shani { void Transform_2way(unsigned char* out, const unsigned char* in); } -namespace sha256_shani +namespace sha256_x86_shani { void Transform(uint32_t* s, const unsigned char* chunk, size_t blocks); } +namespace sha256_arm_shani +{ +void Transform(uint32_t* s, const unsigned char* chunk, size_t blocks); +} + +namespace sha256d64_arm_shani +{ +void Transform_2way(unsigned char* out, const unsigned char* in); +} + // Internal implementation code. namespace { @@ -567,7 +587,7 @@ std::string SHA256AutoDetect() bool have_xsave = false; bool have_avx = false; bool have_avx2 = false; - bool have_shani = false; + bool have_x86_shani = false; bool enabled_avx = false; (void)AVXEnabled; @@ -575,7 +595,7 @@ std::string SHA256AutoDetect() (void)have_avx; (void)have_xsave; (void)have_avx2; - (void)have_shani; + (void)have_x86_shani; (void)enabled_avx; uint32_t eax, ebx, ecx, edx; @@ -589,15 +609,15 @@ std::string SHA256AutoDetect() if (have_sse4) { GetCPUID(7, 0, eax, ebx, ecx, edx); have_avx2 = (ebx >> 5) & 1; - have_shani = (ebx >> 29) & 1; + have_x86_shani = (ebx >> 29) & 1; } -#if defined(ENABLE_SHANI) && !defined(BUILD_BITCOIN_INTERNAL) - if (have_shani) { - Transform = sha256_shani::Transform; - TransformD64 = TransformD64Wrapper<sha256_shani::Transform>; - TransformD64_2way = sha256d64_shani::Transform_2way; - ret = "shani(1way,2way)"; +#if defined(ENABLE_X86_SHANI) && !defined(BUILD_BITCOIN_INTERNAL) + if (have_x86_shani) { + Transform = sha256_x86_shani::Transform; + TransformD64 = TransformD64Wrapper<sha256_x86_shani::Transform>; + TransformD64_2way = sha256d64_x86_shani::Transform_2way; + ret = "x86_shani(1way,2way)"; have_sse4 = false; // Disable SSE4/AVX2; have_avx2 = false; } @@ -623,6 +643,38 @@ std::string SHA256AutoDetect() #endif #endif +#if defined(ENABLE_ARM_SHANI) && !defined(BUILD_BITCOIN_INTERNAL) + bool have_arm_shani = false; + +#if defined(__linux__) +#if defined(__arm__) // 32-bit + if (getauxval(AT_HWCAP2) & HWCAP2_SHA2) { + have_arm_shani = true; + } +#endif +#if defined(__aarch64__) // 64-bit + if (getauxval(AT_HWCAP) & HWCAP_SHA2) { + have_arm_shani = true; + } +#endif +#endif + +#if defined(MAC_OSX) + int val = 0; + size_t len = sizeof(val); + if (sysctlbyname("hw.optional.arm.FEAT_SHA256", &val, &len, nullptr, 0) == 0) { + have_arm_shani = val != 0; + } +#endif + + if (have_arm_shani) { + Transform = sha256_arm_shani::Transform; + TransformD64 = TransformD64Wrapper<sha256_arm_shani::Transform>; + TransformD64_2way = sha256d64_arm_shani::Transform_2way; + ret = "arm_shani(1way,2way)"; + } +#endif + assert(SelfTest()); return ret; } diff --git a/src/crypto/sha256_arm_shani.cpp b/src/crypto/sha256_arm_shani.cpp new file mode 100644 index 0000000000..2ea1d9c2ac --- /dev/null +++ b/src/crypto/sha256_arm_shani.cpp @@ -0,0 +1,899 @@ +// 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. +// +// Based on https://github.com/noloader/SHA-Intrinsics/blob/master/sha256-arm.c, +// Written and placed in public domain by Jeffrey Walton. +// Based on code from ARM, and by Johannes Schneiders, Skip Hovsmith and +// Barry O'Rourke for the mbedTLS project. +// Variant specialized for 64-byte inputs added by Pieter Wuille. + +#ifdef ENABLE_ARM_SHANI + +#include <array> +#include <cstdint> +#include <cstddef> +#include <arm_acle.h> +#include <arm_neon.h> + +namespace { +alignas(uint32x4_t) static constexpr std::array<uint32_t, 64> K = +{ + 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, + 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, + 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, + 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, + 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC, + 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, + 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, + 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967, + 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, + 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, + 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, + 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, + 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, + 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, + 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, + 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2, +}; +} + +namespace sha256_arm_shani { +void Transform(uint32_t* s, const unsigned char* chunk, size_t blocks) +{ + uint32x4_t STATE0, STATE1, ABEF_SAVE, CDGH_SAVE; + uint32x4_t MSG0, MSG1, MSG2, MSG3; + uint32x4_t TMP0, TMP2; + + // Load state + STATE0 = vld1q_u32(&s[0]); + STATE1 = vld1q_u32(&s[4]); + + while (blocks--) + { + // Save state + ABEF_SAVE = STATE0; + CDGH_SAVE = STATE1; + + // Load and convert input chunk to Big Endian + MSG0 = vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(chunk + 0))); + MSG1 = vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(chunk + 16))); + MSG2 = vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(chunk + 32))); + MSG3 = vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(chunk + 48))); + chunk += 64; + + // Original implementation preloaded message and constant addition which was 1-3% slower. + // Now included as first step in quad round code saving one Q Neon register + // "TMP0 = vaddq_u32(MSG0, vld1q_u32(&K[0]));" + + // Rounds 1-4 + TMP0 = vaddq_u32(MSG0, vld1q_u32(&K[0])); + TMP2 = STATE0; + MSG0 = vsha256su0q_u32(MSG0, MSG1); + STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0); + STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0); + MSG0 = vsha256su1q_u32(MSG0, MSG2, MSG3); + + // Rounds 5-8 + TMP0 = vaddq_u32(MSG1, vld1q_u32(&K[4])); + TMP2 = STATE0; + MSG1 = vsha256su0q_u32(MSG1, MSG2); + STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0); + STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0); + MSG1 = vsha256su1q_u32(MSG1, MSG3, MSG0); + + // Rounds 9-12 + TMP0 = vaddq_u32(MSG2, vld1q_u32(&K[8])); + TMP2 = STATE0; + MSG2 = vsha256su0q_u32(MSG2, MSG3); + STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0); + STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0); + MSG2 = vsha256su1q_u32(MSG2, MSG0, MSG1); + + // Rounds 13-16 + TMP0 = vaddq_u32(MSG3, vld1q_u32(&K[12])); + TMP2 = STATE0; + MSG3 = vsha256su0q_u32(MSG3, MSG0); + STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0); + STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0); + MSG3 = vsha256su1q_u32(MSG3, MSG1, MSG2); + + // Rounds 17-20 + TMP0 = vaddq_u32(MSG0, vld1q_u32(&K[16])); + TMP2 = STATE0; + MSG0 = vsha256su0q_u32(MSG0, MSG1); + STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0); + STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0); + MSG0 = vsha256su1q_u32(MSG0, MSG2, MSG3); + + // Rounds 21-24 + TMP0 = vaddq_u32(MSG1, vld1q_u32(&K[20])); + TMP2 = STATE0; + MSG1 = vsha256su0q_u32(MSG1, MSG2); + STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0); + STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0); + MSG1 = vsha256su1q_u32(MSG1, MSG3, MSG0); + + // Rounds 25-28 + TMP0 = vaddq_u32(MSG2, vld1q_u32(&K[24])); + TMP2 = STATE0; + MSG2 = vsha256su0q_u32(MSG2, MSG3); + STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0); + STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0); + MSG2 = vsha256su1q_u32(MSG2, MSG0, MSG1); + + // Rounds 29-32 + TMP0 = vaddq_u32(MSG3, vld1q_u32(&K[28])); + TMP2 = STATE0; + MSG3 = vsha256su0q_u32(MSG3, MSG0); + STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0); + STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0); + MSG3 = vsha256su1q_u32(MSG3, MSG1, MSG2); + + // Rounds 33-36 + TMP0 = vaddq_u32(MSG0, vld1q_u32(&K[32])); + TMP2 = STATE0; + MSG0 = vsha256su0q_u32(MSG0, MSG1); + STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0); + STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0); + MSG0 = vsha256su1q_u32(MSG0, MSG2, MSG3); + + // Rounds 37-40 + TMP0 = vaddq_u32(MSG1, vld1q_u32(&K[36])); + TMP2 = STATE0; + MSG1 = vsha256su0q_u32(MSG1, MSG2); + STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0); + STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0); + MSG1 = vsha256su1q_u32(MSG1, MSG3, MSG0); + + // Rounds 41-44 + TMP0 = vaddq_u32(MSG2, vld1q_u32(&K[40])); + TMP2 = STATE0; + MSG2 = vsha256su0q_u32(MSG2, MSG3); + STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0); + STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0); + MSG2 = vsha256su1q_u32(MSG2, MSG0, MSG1); + + // Rounds 45-48 + TMP0 = vaddq_u32(MSG3, vld1q_u32(&K[44])); + TMP2 = STATE0; + MSG3 = vsha256su0q_u32(MSG3, MSG0); + STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0); + STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0); + MSG3 = vsha256su1q_u32(MSG3, MSG1, MSG2); + + // Rounds 49-52 + TMP0 = vaddq_u32(MSG0, vld1q_u32(&K[48])); + TMP2 = STATE0; + STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0); + STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0); + + // Rounds 53-56 + TMP0 = vaddq_u32(MSG1, vld1q_u32(&K[52])); + TMP2 = STATE0; + STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0); + STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0); + + // Rounds 57-60 + TMP0 = vaddq_u32(MSG2, vld1q_u32(&K[56])); + TMP2 = STATE0; + STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0); + STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0); + + // Rounds 61-64 + TMP0 = vaddq_u32(MSG3, vld1q_u32(&K[60])); + TMP2 = STATE0; + STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0); + STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0); + + // Update state + STATE0 = vaddq_u32(STATE0, ABEF_SAVE); + STATE1 = vaddq_u32(STATE1, CDGH_SAVE); + } + + // Save final state + vst1q_u32(&s[0], STATE0); + vst1q_u32(&s[4], STATE1); +} +} + +namespace sha256d64_arm_shani { +void Transform_2way(unsigned char* output, const unsigned char* input) +{ + /* Initial state. */ + alignas(uint32x4_t) static constexpr std::array<uint32_t, 8> INIT = { + 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, + 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 + }; + + /* Precomputed message schedule for the 2nd transform. */ + alignas(uint32x4_t) static constexpr std::array<uint32_t, 64> MIDS = { + 0xc28a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf374, + 0x649b69c1, 0xf0fe4786, 0x0fe1edc6, 0x240cf254, + 0x4fe9346f, 0x6cc984be, 0x61b9411e, 0x16f988fa, + 0xf2c65152, 0xa88e5a6d, 0xb019fc65, 0xb9d99ec7, + 0x9a1231c3, 0xe70eeaa0, 0xfdb1232b, 0xc7353eb0, + 0x3069bad5, 0xcb976d5f, 0x5a0f118f, 0xdc1eeefd, + 0x0a35b689, 0xde0b7a04, 0x58f4ca9d, 0xe15d5b16, + 0x007f3e86, 0x37088980, 0xa507ea32, 0x6fab9537, + 0x17406110, 0x0d8cd6f1, 0xcdaa3b6d, 0xc0bbbe37, + 0x83613bda, 0xdb48a363, 0x0b02e931, 0x6fd15ca7, + 0x521afaca, 0x31338431, 0x6ed41a95, 0x6d437890, + 0xc39c91f2, 0x9eccabbd, 0xb5c9a0e6, 0x532fb63c, + 0xd2c741c6, 0x07237ea3, 0xa4954b68, 0x4c191d76 + }; + + /* A few precomputed message schedule values for the 3rd transform. */ + alignas(uint32x4_t) static constexpr std::array<uint32_t, 12> FINS = { + 0x5807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x80000000, 0x00000000, 0x00000000, 0x00000000, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf274 + }; + + /* Padding processed in the 3rd transform (byteswapped). */ + alignas(uint32x4_t) static constexpr std::array<uint32_t, 8> FINAL = {0x80000000, 0, 0, 0, 0, 0, 0, 0x100}; + + uint32x4_t STATE0A, STATE0B, STATE1A, STATE1B, ABEF_SAVEA, ABEF_SAVEB, CDGH_SAVEA, CDGH_SAVEB; + uint32x4_t MSG0A, MSG0B, MSG1A, MSG1B, MSG2A, MSG2B, MSG3A, MSG3B; + uint32x4_t TMP0A, TMP0B, TMP2A, TMP2B, TMP; + + // Transform 1: Load state + STATE0A = vld1q_u32(&INIT[0]); + STATE0B = STATE0A; + STATE1A = vld1q_u32(&INIT[4]); + STATE1B = STATE1A; + + // Transform 1: Load and convert input chunk to Big Endian + MSG0A = vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(input + 0))); + MSG1A = vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(input + 16))); + MSG2A = vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(input + 32))); + MSG3A = vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(input + 48))); + MSG0B = vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(input + 64))); + MSG1B = vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(input + 80))); + MSG2B = vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(input + 96))); + MSG3B = vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(input + 112))); + + // Transform 1: Rounds 1-4 + TMP = vld1q_u32(&K[0]); + TMP0A = vaddq_u32(MSG0A, TMP); + TMP0B = vaddq_u32(MSG0B, TMP); + TMP2A = STATE0A; + TMP2B = STATE0B; + MSG0A = vsha256su0q_u32(MSG0A, MSG1A); + MSG0B = vsha256su0q_u32(MSG0B, MSG1B); + STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A); + STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B); + STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A); + STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B); + MSG0A = vsha256su1q_u32(MSG0A, MSG2A, MSG3A); + MSG0B = vsha256su1q_u32(MSG0B, MSG2B, MSG3B); + + // Transform 1: Rounds 5-8 + TMP = vld1q_u32(&K[4]); + TMP0A = vaddq_u32(MSG1A, TMP); + TMP0B = vaddq_u32(MSG1B, TMP); + TMP2A = STATE0A; + TMP2B = STATE0B; + MSG1A = vsha256su0q_u32(MSG1A, MSG2A); + MSG1B = vsha256su0q_u32(MSG1B, MSG2B); + STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A); + STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B); + STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A); + STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B); + MSG1A = vsha256su1q_u32(MSG1A, MSG3A, MSG0A); + MSG1B = vsha256su1q_u32(MSG1B, MSG3B, MSG0B); + + // Transform 1: Rounds 9-12 + TMP = vld1q_u32(&K[8]); + TMP0A = vaddq_u32(MSG2A, TMP); + TMP0B = vaddq_u32(MSG2B, TMP); + TMP2A = STATE0A; + TMP2B = STATE0B; + MSG2A = vsha256su0q_u32(MSG2A, MSG3A); + MSG2B = vsha256su0q_u32(MSG2B, MSG3B); + STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A); + STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B); + STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A); + STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B); + MSG2A = vsha256su1q_u32(MSG2A, MSG0A, MSG1A); + MSG2B = vsha256su1q_u32(MSG2B, MSG0B, MSG1B); + + // Transform 1: Rounds 13-16 + TMP = vld1q_u32(&K[12]); + TMP0A = vaddq_u32(MSG3A, TMP); + TMP0B = vaddq_u32(MSG3B, TMP); + TMP2A = STATE0A; + TMP2B = STATE0B; + MSG3A = vsha256su0q_u32(MSG3A, MSG0A); + MSG3B = vsha256su0q_u32(MSG3B, MSG0B); + STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A); + STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B); + STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A); + STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B); + MSG3A = vsha256su1q_u32(MSG3A, MSG1A, MSG2A); + MSG3B = vsha256su1q_u32(MSG3B, MSG1B, MSG2B); + + // Transform 1: Rounds 17-20 + TMP = vld1q_u32(&K[16]); + TMP0A = vaddq_u32(MSG0A, TMP); + TMP0B = vaddq_u32(MSG0B, TMP); + TMP2A = STATE0A; + TMP2B = STATE0B; + MSG0A = vsha256su0q_u32(MSG0A, MSG1A); + MSG0B = vsha256su0q_u32(MSG0B, MSG1B); + STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A); + STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B); + STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A); + STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B); + MSG0A = vsha256su1q_u32(MSG0A, MSG2A, MSG3A); + MSG0B = vsha256su1q_u32(MSG0B, MSG2B, MSG3B); + + // Transform 1: Rounds 21-24 + TMP = vld1q_u32(&K[20]); + TMP0A = vaddq_u32(MSG1A, TMP); + TMP0B = vaddq_u32(MSG1B, TMP); + TMP2A = STATE0A; + TMP2B = STATE0B; + MSG1A = vsha256su0q_u32(MSG1A, MSG2A); + MSG1B = vsha256su0q_u32(MSG1B, MSG2B); + STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A); + STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B); + STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A); + STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B); + MSG1A = vsha256su1q_u32(MSG1A, MSG3A, MSG0A); + MSG1B = vsha256su1q_u32(MSG1B, MSG3B, MSG0B); + + // Transform 1: Rounds 25-28 + TMP = vld1q_u32(&K[24]); + TMP0A = vaddq_u32(MSG2A, TMP); + TMP0B = vaddq_u32(MSG2B, TMP); + TMP2A = STATE0A; + TMP2B = STATE0B; + MSG2A = vsha256su0q_u32(MSG2A, MSG3A); + MSG2B = vsha256su0q_u32(MSG2B, MSG3B); + STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A); + STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B); + STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A); + STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B); + MSG2A = vsha256su1q_u32(MSG2A, MSG0A, MSG1A); + MSG2B = vsha256su1q_u32(MSG2B, MSG0B, MSG1B); + + // Transform 1: Rounds 29-32 + TMP = vld1q_u32(&K[28]); + TMP0A = vaddq_u32(MSG3A, TMP); + TMP0B = vaddq_u32(MSG3B, TMP); + TMP2A = STATE0A; + TMP2B = STATE0B; + MSG3A = vsha256su0q_u32(MSG3A, MSG0A); + MSG3B = vsha256su0q_u32(MSG3B, MSG0B); + STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A); + STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B); + STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A); + STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B); + MSG3A = vsha256su1q_u32(MSG3A, MSG1A, MSG2A); + MSG3B = vsha256su1q_u32(MSG3B, MSG1B, MSG2B); + + // Transform 1: Rounds 33-36 + TMP = vld1q_u32(&K[32]); + TMP0A = vaddq_u32(MSG0A, TMP); + TMP0B = vaddq_u32(MSG0B, TMP); + TMP2A = STATE0A; + TMP2B = STATE0B; + MSG0A = vsha256su0q_u32(MSG0A, MSG1A); + MSG0B = vsha256su0q_u32(MSG0B, MSG1B); + STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A); + STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B); + STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A); + STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B); + MSG0A = vsha256su1q_u32(MSG0A, MSG2A, MSG3A); + MSG0B = vsha256su1q_u32(MSG0B, MSG2B, MSG3B); + + // Transform 1: Rounds 37-40 + TMP = vld1q_u32(&K[36]); + TMP0A = vaddq_u32(MSG1A, TMP); + TMP0B = vaddq_u32(MSG1B, TMP); + TMP2A = STATE0A; + TMP2B = STATE0B; + MSG1A = vsha256su0q_u32(MSG1A, MSG2A); + MSG1B = vsha256su0q_u32(MSG1B, MSG2B); + STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A); + STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B); + STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A); + STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B); + MSG1A = vsha256su1q_u32(MSG1A, MSG3A, MSG0A); + MSG1B = vsha256su1q_u32(MSG1B, MSG3B, MSG0B); + + // Transform 1: Rounds 41-44 + TMP = vld1q_u32(&K[40]); + TMP0A = vaddq_u32(MSG2A, TMP); + TMP0B = vaddq_u32(MSG2B, TMP); + TMP2A = STATE0A; + TMP2B = STATE0B; + MSG2A = vsha256su0q_u32(MSG2A, MSG3A); + MSG2B = vsha256su0q_u32(MSG2B, MSG3B); + STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A); + STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B); + STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A); + STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B); + MSG2A = vsha256su1q_u32(MSG2A, MSG0A, MSG1A); + MSG2B = vsha256su1q_u32(MSG2B, MSG0B, MSG1B); + + // Transform 1: Rounds 45-48 + TMP = vld1q_u32(&K[44]); + TMP0A = vaddq_u32(MSG3A, TMP); + TMP0B = vaddq_u32(MSG3B, TMP); + TMP2A = STATE0A; + TMP2B = STATE0B; + MSG3A = vsha256su0q_u32(MSG3A, MSG0A); + MSG3B = vsha256su0q_u32(MSG3B, MSG0B); + STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A); + STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B); + STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A); + STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B); + MSG3A = vsha256su1q_u32(MSG3A, MSG1A, MSG2A); + MSG3B = vsha256su1q_u32(MSG3B, MSG1B, MSG2B); + + // Transform 1: Rounds 49-52 + TMP = vld1q_u32(&K[48]); + TMP0A = vaddq_u32(MSG0A, TMP); + TMP0B = vaddq_u32(MSG0B, TMP); + TMP2A = STATE0A; + TMP2B = STATE0B; + STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A); + STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B); + STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A); + STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B); + + // Transform 1: Rounds 53-56 + TMP = vld1q_u32(&K[52]); + TMP0A = vaddq_u32(MSG1A, TMP); + TMP0B = vaddq_u32(MSG1B, TMP); + TMP2A = STATE0A; + TMP2B = STATE0B; + STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A); + STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B); + STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A); + STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B); + + // Transform 1: Rounds 57-60 + TMP = vld1q_u32(&K[56]); + TMP0A = vaddq_u32(MSG2A, TMP); + TMP0B = vaddq_u32(MSG2B, TMP); + TMP2A = STATE0A; + TMP2B = STATE0B; + STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A); + STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B); + STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A); + STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B); + + // Transform 1: Rounds 61-64 + TMP = vld1q_u32(&K[60]); + TMP0A = vaddq_u32(MSG3A, TMP); + TMP0B = vaddq_u32(MSG3B, TMP); + TMP2A = STATE0A; + TMP2B = STATE0B; + STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A); + STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B); + STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A); + STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B); + + // Transform 1: Update state + TMP = vld1q_u32(&INIT[0]); + STATE0A = vaddq_u32(STATE0A, TMP); + STATE0B = vaddq_u32(STATE0B, TMP); + TMP = vld1q_u32(&INIT[4]); + STATE1A = vaddq_u32(STATE1A, TMP); + STATE1B = vaddq_u32(STATE1B, TMP); + + // Transform 2: Save state + ABEF_SAVEA = STATE0A; + ABEF_SAVEB = STATE0B; + CDGH_SAVEA = STATE1A; + CDGH_SAVEB = STATE1B; + + // Transform 2: Rounds 1-4 + TMP = vld1q_u32(&MIDS[0]); + TMP2A = STATE0A; + TMP2B = STATE0B; + STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP); + STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP); + STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP); + STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP); + + // Transform 2: Rounds 5-8 + TMP = vld1q_u32(&MIDS[4]); + TMP2A = STATE0A; + TMP2B = STATE0B; + STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP); + STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP); + STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP); + STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP); + + // Transform 2: Rounds 9-12 + TMP = vld1q_u32(&MIDS[8]); + TMP2A = STATE0A; + TMP2B = STATE0B; + STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP); + STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP); + STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP); + STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP); + + // Transform 2: Rounds 13-16 + TMP = vld1q_u32(&MIDS[12]); + TMP2A = STATE0A; + TMP2B = STATE0B; + STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP); + STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP); + STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP); + STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP); + + // Transform 2: Rounds 17-20 + TMP = vld1q_u32(&MIDS[16]); + TMP2A = STATE0A; + TMP2B = STATE0B; + STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP); + STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP); + STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP); + STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP); + + // Transform 2: Rounds 21-24 + TMP = vld1q_u32(&MIDS[20]); + TMP2A = STATE0A; + TMP2B = STATE0B; + STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP); + STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP); + STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP); + STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP); + + // Transform 2: Rounds 25-28 + TMP = vld1q_u32(&MIDS[24]); + TMP2A = STATE0A; + TMP2B = STATE0B; + STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP); + STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP); + STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP); + STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP); + + // Transform 2: Rounds 29-32 + TMP = vld1q_u32(&MIDS[28]); + TMP2A = STATE0A; + TMP2B = STATE0B; + STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP); + STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP); + STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP); + STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP); + + // Transform 2: Rounds 33-36 + TMP = vld1q_u32(&MIDS[32]); + TMP2A = STATE0A; + TMP2B = STATE0B; + STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP); + STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP); + STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP); + STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP); + + // Transform 2: Rounds 37-40 + TMP = vld1q_u32(&MIDS[36]); + TMP2A = STATE0A; + TMP2B = STATE0B; + STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP); + STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP); + STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP); + STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP); + + // Transform 2: Rounds 41-44 + TMP = vld1q_u32(&MIDS[40]); + TMP2A = STATE0A; + TMP2B = STATE0B; + STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP); + STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP); + STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP); + STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP); + + // Transform 2: Rounds 45-48 + TMP = vld1q_u32(&MIDS[44]); + TMP2A = STATE0A; + TMP2B = STATE0B; + STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP); + STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP); + STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP); + STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP); + + // Transform 2: Rounds 49-52 + TMP = vld1q_u32(&MIDS[48]); + TMP2A = STATE0A; + TMP2B = STATE0B; + STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP); + STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP); + STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP); + STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP); + + // Transform 2: Rounds 53-56 + TMP = vld1q_u32(&MIDS[52]); + TMP2A = STATE0A; + TMP2B = STATE0B; + STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP); + STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP); + STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP); + STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP); + + // Transform 2: Rounds 57-60 + TMP = vld1q_u32(&MIDS[56]); + TMP2A = STATE0A; + TMP2B = STATE0B; + STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP); + STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP); + STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP); + STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP); + + // Transform 2: Rounds 61-64 + TMP = vld1q_u32(&MIDS[60]); + TMP2A = STATE0A; + TMP2B = STATE0B; + STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP); + STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP); + STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP); + STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP); + + // Transform 2: Update state + STATE0A = vaddq_u32(STATE0A, ABEF_SAVEA); + STATE0B = vaddq_u32(STATE0B, ABEF_SAVEB); + STATE1A = vaddq_u32(STATE1A, CDGH_SAVEA); + STATE1B = vaddq_u32(STATE1B, CDGH_SAVEB); + + // Transform 3: Pad previous output + MSG0A = STATE0A; + MSG0B = STATE0B; + MSG1A = STATE1A; + MSG1B = STATE1B; + MSG2A = vld1q_u32(&FINAL[0]); + MSG2B = MSG2A; + MSG3A = vld1q_u32(&FINAL[4]); + MSG3B = MSG3A; + + // Transform 3: Load state + STATE0A = vld1q_u32(&INIT[0]); + STATE0B = STATE0A; + STATE1A = vld1q_u32(&INIT[4]); + STATE1B = STATE1A; + + // Transform 3: Rounds 1-4 + TMP = vld1q_u32(&K[0]); + TMP0A = vaddq_u32(MSG0A, TMP); + TMP0B = vaddq_u32(MSG0B, TMP); + TMP2A = STATE0A; + TMP2B = STATE0B; + MSG0A = vsha256su0q_u32(MSG0A, MSG1A); + MSG0B = vsha256su0q_u32(MSG0B, MSG1B); + STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A); + STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B); + STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A); + STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B); + MSG0A = vsha256su1q_u32(MSG0A, MSG2A, MSG3A); + MSG0B = vsha256su1q_u32(MSG0B, MSG2B, MSG3B); + + // Transform 3: Rounds 5-8 + TMP = vld1q_u32(&K[4]); + TMP0A = vaddq_u32(MSG1A, TMP); + TMP0B = vaddq_u32(MSG1B, TMP); + TMP2A = STATE0A; + TMP2B = STATE0B; + MSG1A = vsha256su0q_u32(MSG1A, MSG2A); + MSG1B = vsha256su0q_u32(MSG1B, MSG2B); + STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A); + STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B); + STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A); + STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B); + MSG1A = vsha256su1q_u32(MSG1A, MSG3A, MSG0A); + MSG1B = vsha256su1q_u32(MSG1B, MSG3B, MSG0B); + + // Transform 3: Rounds 9-12 + TMP = vld1q_u32(&FINS[0]); + TMP2A = STATE0A; + TMP2B = STATE0B; + MSG2A = vld1q_u32(&FINS[4]); + MSG2B = MSG2A; + STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP); + STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP); + STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP); + STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP); + MSG2A = vsha256su1q_u32(MSG2A, MSG0A, MSG1A); + MSG2B = vsha256su1q_u32(MSG2B, MSG0B, MSG1B); + + // Transform 3: Rounds 13-16 + TMP = vld1q_u32(&FINS[8]); + TMP2A = STATE0A; + TMP2B = STATE0B; + MSG3A = vsha256su0q_u32(MSG3A, MSG0A); + MSG3B = vsha256su0q_u32(MSG3B, MSG0B); + STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP); + STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP); + STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP); + STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP); + MSG3A = vsha256su1q_u32(MSG3A, MSG1A, MSG2A); + MSG3B = vsha256su1q_u32(MSG3B, MSG1B, MSG2B); + + // Transform 3: Rounds 17-20 + TMP = vld1q_u32(&K[16]); + TMP0A = vaddq_u32(MSG0A, TMP); + TMP0B = vaddq_u32(MSG0B, TMP); + TMP2A = STATE0A; + TMP2B = STATE0B; + MSG0A = vsha256su0q_u32(MSG0A, MSG1A); + MSG0B = vsha256su0q_u32(MSG0B, MSG1B); + STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A); + STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B); + STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A); + STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B); + MSG0A = vsha256su1q_u32(MSG0A, MSG2A, MSG3A); + MSG0B = vsha256su1q_u32(MSG0B, MSG2B, MSG3B); + + // Transform 3: Rounds 21-24 + TMP = vld1q_u32(&K[20]); + TMP0A = vaddq_u32(MSG1A, TMP); + TMP0B = vaddq_u32(MSG1B, TMP); + TMP2A = STATE0A; + TMP2B = STATE0B; + MSG1A = vsha256su0q_u32(MSG1A, MSG2A); + MSG1B = vsha256su0q_u32(MSG1B, MSG2B); + STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A); + STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B); + STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A); + STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B); + MSG1A = vsha256su1q_u32(MSG1A, MSG3A, MSG0A); + MSG1B = vsha256su1q_u32(MSG1B, MSG3B, MSG0B); + + // Transform 3: Rounds 25-28 + TMP = vld1q_u32(&K[24]); + TMP0A = vaddq_u32(MSG2A, TMP); + TMP0B = vaddq_u32(MSG2B, TMP); + TMP2A = STATE0A; + TMP2B = STATE0B; + MSG2A = vsha256su0q_u32(MSG2A, MSG3A); + MSG2B = vsha256su0q_u32(MSG2B, MSG3B); + STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A); + STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B); + STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A); + STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B); + MSG2A = vsha256su1q_u32(MSG2A, MSG0A, MSG1A); + MSG2B = vsha256su1q_u32(MSG2B, MSG0B, MSG1B); + + // Transform 3: Rounds 29-32 + TMP = vld1q_u32(&K[28]); + TMP0A = vaddq_u32(MSG3A, TMP); + TMP0B = vaddq_u32(MSG3B, TMP); + TMP2A = STATE0A; + TMP2B = STATE0B; + MSG3A = vsha256su0q_u32(MSG3A, MSG0A); + MSG3B = vsha256su0q_u32(MSG3B, MSG0B); + STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A); + STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B); + STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A); + STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B); + MSG3A = vsha256su1q_u32(MSG3A, MSG1A, MSG2A); + MSG3B = vsha256su1q_u32(MSG3B, MSG1B, MSG2B); + + // Transform 3: Rounds 33-36 + TMP = vld1q_u32(&K[32]); + TMP0A = vaddq_u32(MSG0A, TMP); + TMP0B = vaddq_u32(MSG0B, TMP); + TMP2A = STATE0A; + TMP2B = STATE0B; + MSG0A = vsha256su0q_u32(MSG0A, MSG1A); + MSG0B = vsha256su0q_u32(MSG0B, MSG1B); + STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A); + STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B); + STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A); + STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B); + MSG0A = vsha256su1q_u32(MSG0A, MSG2A, MSG3A); + MSG0B = vsha256su1q_u32(MSG0B, MSG2B, MSG3B); + + // Transform 3: Rounds 37-40 + TMP = vld1q_u32(&K[36]); + TMP0A = vaddq_u32(MSG1A, TMP); + TMP0B = vaddq_u32(MSG1B, TMP); + TMP2A = STATE0A; + TMP2B = STATE0B; + MSG1A = vsha256su0q_u32(MSG1A, MSG2A); + MSG1B = vsha256su0q_u32(MSG1B, MSG2B); + STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A); + STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B); + STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A); + STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B); + MSG1A = vsha256su1q_u32(MSG1A, MSG3A, MSG0A); + MSG1B = vsha256su1q_u32(MSG1B, MSG3B, MSG0B); + + // Transform 3: Rounds 41-44 + TMP = vld1q_u32(&K[40]); + TMP0A = vaddq_u32(MSG2A, TMP); + TMP0B = vaddq_u32(MSG2B, TMP); + TMP2A = STATE0A; + TMP2B = STATE0B; + MSG2A = vsha256su0q_u32(MSG2A, MSG3A); + MSG2B = vsha256su0q_u32(MSG2B, MSG3B); + STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A); + STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B); + STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A); + STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B); + MSG2A = vsha256su1q_u32(MSG2A, MSG0A, MSG1A); + MSG2B = vsha256su1q_u32(MSG2B, MSG0B, MSG1B); + + // Transform 3: Rounds 45-48 + TMP = vld1q_u32(&K[44]); + TMP0A = vaddq_u32(MSG3A, TMP); + TMP0B = vaddq_u32(MSG3B, TMP); + TMP2A = STATE0A; + TMP2B = STATE0B; + MSG3A = vsha256su0q_u32(MSG3A, MSG0A); + MSG3B = vsha256su0q_u32(MSG3B, MSG0B); + STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A); + STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B); + STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A); + STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B); + MSG3A = vsha256su1q_u32(MSG3A, MSG1A, MSG2A); + MSG3B = vsha256su1q_u32(MSG3B, MSG1B, MSG2B); + + // Transform 3: Rounds 49-52 + TMP = vld1q_u32(&K[48]); + TMP0A = vaddq_u32(MSG0A, TMP); + TMP0B = vaddq_u32(MSG0B, TMP); + TMP2A = STATE0A; + TMP2B = STATE0B; + STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A); + STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B); + STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A); + STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B); + + // Transform 3: Rounds 53-56 + TMP = vld1q_u32(&K[52]); + TMP0A = vaddq_u32(MSG1A, TMP); + TMP0B = vaddq_u32(MSG1B, TMP); + TMP2A = STATE0A; + TMP2B = STATE0B; + STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A); + STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B); + STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A); + STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B); + + // Transform 3: Rounds 57-60 + TMP = vld1q_u32(&K[56]); + TMP0A = vaddq_u32(MSG2A, TMP); + TMP0B = vaddq_u32(MSG2B, TMP); + TMP2A = STATE0A; + TMP2B = STATE0B; + STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A); + STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B); + STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A); + STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B); + + // Transform 3: Rounds 61-64 + TMP = vld1q_u32(&K[60]); + TMP0A = vaddq_u32(MSG3A, TMP); + TMP0B = vaddq_u32(MSG3B, TMP); + TMP2A = STATE0A; + TMP2B = STATE0B; + STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A); + STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B); + STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A); + STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B); + + // Transform 3: Update state + TMP = vld1q_u32(&INIT[0]); + STATE0A = vaddq_u32(STATE0A, TMP); + STATE0B = vaddq_u32(STATE0B, TMP); + TMP = vld1q_u32(&INIT[4]); + STATE1A = vaddq_u32(STATE1A, TMP); + STATE1B = vaddq_u32(STATE1B, TMP); + + // Store result + vst1q_u8(output, vrev32q_u8(vreinterpretq_u8_u32(STATE0A))); + vst1q_u8(output + 16, vrev32q_u8(vreinterpretq_u8_u32(STATE1A))); + vst1q_u8(output + 32, vrev32q_u8(vreinterpretq_u8_u32(STATE0B))); + vst1q_u8(output + 48, vrev32q_u8(vreinterpretq_u8_u32(STATE1B))); +} +} + +#endif diff --git a/src/crypto/sha256_shani.cpp b/src/crypto/sha256_x86_shani.cpp index 4f4d5b5837..a82802199f 100644 --- a/src/crypto/sha256_shani.cpp +++ b/src/crypto/sha256_x86_shani.cpp @@ -6,7 +6,7 @@ // Written and placed in public domain by Jeffrey Walton. // Based on code from Intel, and by Sean Gulley for the miTLS project. -#ifdef ENABLE_SHANI +#ifdef ENABLE_X86_SHANI #include <stdint.h> #include <immintrin.h> @@ -74,7 +74,7 @@ void inline __attribute__((always_inline)) Save(unsigned char* out, __m128i s) } } -namespace sha256_shani { +namespace sha256_x86_shani { void Transform(uint32_t* s, const unsigned char* chunk, size_t blocks) { __m128i m0, m1, m2, m3, s0, s1, so0, so1; @@ -139,7 +139,7 @@ void Transform(uint32_t* s, const unsigned char* chunk, size_t blocks) } } -namespace sha256d64_shani { +namespace sha256d64_x86_shani { void Transform_2way(unsigned char* out, const unsigned char* in) { @@ -140,6 +140,28 @@ static inline path PathFromString(const std::string& string) return std::filesystem::path(string); #endif } + +/** + * Create directory (and if necessary its parents), unless the leaf directory + * already exists or is a symlink to an existing directory. + * This is a temporary workaround for an issue in libstdc++ that has been fixed + * upstream [PR101510]. + */ +static inline bool create_directories(const std::filesystem::path& p) +{ + if (std::filesystem::is_symlink(p) && std::filesystem::is_directory(p)) { + return false; + } + return std::filesystem::create_directories(p); +} + +/** + * This variant is not used. Delete it to prevent it from accidentally working + * around the workaround. If it is needed, add a workaround in the same pattern + * as above. + */ +bool create_directories(const std::filesystem::path& p, std::error_code& ec) = delete; + } // namespace fs /** Bridge operations to C stdio */ diff --git a/src/index/base.cpp b/src/index/base.cpp index 2e3d500cd1..8fe30f8960 100644 --- a/src/index/base.cpp +++ b/src/index/base.cpp @@ -211,6 +211,11 @@ bool BaseIndex::Commit() bool BaseIndex::CommitInternal(CDBBatch& batch) { LOCK(cs_main); + // Don't commit anything if we haven't indexed any block yet + // (this could happen if init is interrupted). + if (m_best_block_index == nullptr) { + return false; + } GetDB().WriteBestBlock(batch, m_chainstate->m_chain.GetLocator(m_best_block_index)); return true; } diff --git a/src/index/coinstatsindex.cpp b/src/index/coinstatsindex.cpp index ef247dc119..7d4860b20b 100644 --- a/src/index/coinstatsindex.cpp +++ b/src/index/coinstatsindex.cpp @@ -360,9 +360,9 @@ bool CoinStatsIndex::Init() if (pindex) { DBVal entry; if (!LookUpOne(*m_db, pindex, entry)) { - return false; + return error("%s: Cannot read current %s state; index may be corrupted", + __func__, GetName()); } - m_transaction_output_count = entry.transaction_output_count; m_bogo_size = entry.bogo_size; m_total_amount = entry.total_amount; diff --git a/src/init.cpp b/src/init.cpp index 330aab5184..6aef1f8149 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1150,7 +1150,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) LogPrintf("Using at most %i automatic connections (%i file descriptors available)\n", nMaxConnections, nFD); // Warn about relative -datadir path. - if (args.IsArgSet("-datadir") && !fs::PathFromString(args.GetArg("-datadir", "")).is_absolute()) { + if (args.IsArgSet("-datadir") && !args.GetPathArg("-datadir").is_absolute()) { LogPrintf("Warning: relative datadir option '%s' specified, which will be interpreted relative to the " /* Continued */ "current working directory '%s'. This is fragile, because if bitcoin is started in the future " "from a different location, it will be unable to locate the current data files. There could " diff --git a/src/node/blockstorage.cpp b/src/node/blockstorage.cpp index 7691c9a5ce..8a99130fd0 100644 --- a/src/node/blockstorage.cpp +++ b/src/node/blockstorage.cpp @@ -295,7 +295,7 @@ bool BlockManager::LoadBlockIndex( // them from the background chainstate's setBlockIndexCandidates set. This // does mean that some blocks which are not technically assumed-valid // (later blocks on a fork beginning before the first assumed-valid block) - // might not get added to the the background chainstate, but this is ok, + // might not get added to the background chainstate, but this is ok, // because they will still be attached to the active chainstate if they // actually contain more work. // diff --git a/src/qt/addressbookpage.cpp b/src/qt/addressbookpage.cpp index a180b03c08..d59a4345f3 100644 --- a/src/qt/addressbookpage.cpp +++ b/src/qt/addressbookpage.cpp @@ -189,7 +189,7 @@ void AddressBookPage::onEditAction() dlg->setModel(model); QModelIndex origIndex = proxyModel->mapToSource(indexes.at(0)); dlg->loadRow(origIndex.row()); - GUIUtil::ShowModalDialogAndDeleteOnClose(dlg); + GUIUtil::ShowModalDialogAsynchronously(dlg); } void AddressBookPage::on_newAddress_clicked() diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index 6a2781079c..eb31287c56 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -268,7 +268,11 @@ void BitcoinApplication::createWindow(const NetworkStyle *networkStyle) connect(window, &BitcoinGUI::quitRequested, this, &BitcoinApplication::requestShutdown); pollShutdownTimer = new QTimer(window); - connect(pollShutdownTimer, &QTimer::timeout, window, &BitcoinGUI::detectShutdown); + connect(pollShutdownTimer, &QTimer::timeout, [this]{ + if (!QApplication::activeModalWidget()) { + window->detectShutdown(); + } + }); } void BitcoinApplication::createSplashScreen(const NetworkStyle *networkStyle) diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 0baacfe58c..7c22880dd1 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -261,10 +261,6 @@ void BitcoinGUI::createActions() sendCoinsAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_2)); tabGroup->addAction(sendCoinsAction); - sendCoinsMenuAction = new QAction(sendCoinsAction->text(), this); - sendCoinsMenuAction->setStatusTip(sendCoinsAction->statusTip()); - sendCoinsMenuAction->setToolTip(sendCoinsMenuAction->statusTip()); - receiveCoinsAction = new QAction(platformStyle->SingleColorIcon(":/icons/receiving_addresses"), tr("&Receive"), this); receiveCoinsAction->setStatusTip(tr("Request payments (generates QR codes and bitcoin: URIs)")); receiveCoinsAction->setToolTip(receiveCoinsAction->statusTip()); @@ -272,10 +268,6 @@ void BitcoinGUI::createActions() receiveCoinsAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_3)); tabGroup->addAction(receiveCoinsAction); - receiveCoinsMenuAction = new QAction(receiveCoinsAction->text(), this); - receiveCoinsMenuAction->setStatusTip(receiveCoinsAction->statusTip()); - receiveCoinsMenuAction->setToolTip(receiveCoinsMenuAction->statusTip()); - historyAction = new QAction(platformStyle->SingleColorIcon(":/icons/history"), tr("&Transactions"), this); historyAction->setStatusTip(tr("Browse transaction history")); historyAction->setToolTip(historyAction->statusTip()); @@ -290,12 +282,8 @@ void BitcoinGUI::createActions() connect(overviewAction, &QAction::triggered, this, &BitcoinGUI::gotoOverviewPage); connect(sendCoinsAction, &QAction::triggered, [this]{ showNormalIfMinimized(); }); connect(sendCoinsAction, &QAction::triggered, [this]{ gotoSendCoinsPage(); }); - connect(sendCoinsMenuAction, &QAction::triggered, [this]{ showNormalIfMinimized(); }); - connect(sendCoinsMenuAction, &QAction::triggered, [this]{ gotoSendCoinsPage(); }); connect(receiveCoinsAction, &QAction::triggered, [this]{ showNormalIfMinimized(); }); connect(receiveCoinsAction, &QAction::triggered, this, &BitcoinGUI::gotoReceiveCoinsPage); - connect(receiveCoinsMenuAction, &QAction::triggered, [this]{ showNormalIfMinimized(); }); - connect(receiveCoinsMenuAction, &QAction::triggered, this, &BitcoinGUI::gotoReceiveCoinsPage); connect(historyAction, &QAction::triggered, [this]{ showNormalIfMinimized(); }); connect(historyAction, &QAction::triggered, this, &BitcoinGUI::gotoHistoryPage); #endif // ENABLE_WALLET @@ -315,8 +303,6 @@ void BitcoinGUI::createActions() optionsAction->setStatusTip(tr("Modify configuration options for %1").arg(PACKAGE_NAME)); optionsAction->setMenuRole(QAction::PreferencesRole); optionsAction->setEnabled(false); - toggleHideAction = new QAction(tr("&Show / Hide"), this); - toggleHideAction->setStatusTip(tr("Show or hide the main Window")); encryptWalletAction = new QAction(tr("&Encrypt Wallet…"), this); encryptWalletAction->setStatusTip(tr("Encrypt the private keys that belong to your wallet")); @@ -376,7 +362,6 @@ void BitcoinGUI::createActions() connect(aboutAction, &QAction::triggered, this, &BitcoinGUI::aboutClicked); connect(aboutQtAction, &QAction::triggered, qApp, QApplication::aboutQt); connect(optionsAction, &QAction::triggered, this, &BitcoinGUI::optionsClicked); - connect(toggleHideAction, &QAction::triggered, this, &BitcoinGUI::toggleHidden); connect(showHelpMessageAction, &QAction::triggered, this, &BitcoinGUI::showHelpMessageClicked); connect(openRPCConsoleAction, &QAction::triggered, this, &BitcoinGUI::showDebugWindow); // prevents an open debug window from becoming stuck/unusable on client shutdown @@ -627,8 +612,6 @@ void BitcoinGUI::setClientModel(ClientModel *_clientModel, interfaces::BlockAndH trayIcon->setVisible(optionsModel->getShowTrayIcon()); } } else { - // Disable possibility to show main window via action - toggleHideAction->setEnabled(false); if(trayIconMenu) { // Disable context menu on tray icon @@ -752,9 +735,7 @@ void BitcoinGUI::setWalletActionsEnabled(bool enabled) { overviewAction->setEnabled(enabled); sendCoinsAction->setEnabled(enabled); - sendCoinsMenuAction->setEnabled(enabled); receiveCoinsAction->setEnabled(enabled); - receiveCoinsMenuAction->setEnabled(enabled); historyAction->setEnabled(enabled); encryptWalletAction->setEnabled(enabled); backupWalletAction->setEnabled(enabled); @@ -784,57 +765,82 @@ void BitcoinGUI::createTrayIcon() void BitcoinGUI::createTrayIconMenu() { #ifndef Q_OS_MAC - // return if trayIcon is unset (only on non-macOSes) - if (!trayIcon) - return; - - trayIcon->setContextMenu(trayIconMenu.get()); - connect(trayIcon, &QSystemTrayIcon::activated, this, &BitcoinGUI::trayIconActivated); -#else - // Note: On macOS, the Dock icon is used to provide the tray's functionality. - MacDockIconHandler *dockIconHandler = MacDockIconHandler::instance(); - connect(dockIconHandler, &MacDockIconHandler::dockIconClicked, this, &BitcoinGUI::macosDockIconActivated); - trayIconMenu->setAsDockMenu(); -#endif + if (!trayIcon) return; +#endif // Q_OS_MAC - // Configuration of the tray icon (or Dock icon) menu + // Configuration of the tray icon (or Dock icon) menu. + QAction* show_hide_action{nullptr}; #ifndef Q_OS_MAC // Note: On macOS, the Dock icon's menu already has Show / Hide action. - trayIconMenu->addAction(toggleHideAction); + show_hide_action = trayIconMenu->addAction(QString(), this, &BitcoinGUI::toggleHidden); trayIconMenu->addSeparator(); -#endif +#endif // Q_OS_MAC + + QAction* send_action{nullptr}; + QAction* receive_action{nullptr}; + QAction* sign_action{nullptr}; + QAction* verify_action{nullptr}; if (enableWallet) { - trayIconMenu->addAction(sendCoinsMenuAction); - trayIconMenu->addAction(receiveCoinsMenuAction); + send_action = trayIconMenu->addAction(sendCoinsAction->text(), sendCoinsAction, &QAction::trigger); + receive_action = trayIconMenu->addAction(receiveCoinsAction->text(), receiveCoinsAction, &QAction::trigger); trayIconMenu->addSeparator(); - trayIconMenu->addAction(signMessageAction); - trayIconMenu->addAction(verifyMessageAction); + sign_action = trayIconMenu->addAction(signMessageAction->text(), signMessageAction, &QAction::trigger); + verify_action = trayIconMenu->addAction(verifyMessageAction->text(), verifyMessageAction, &QAction::trigger); trayIconMenu->addSeparator(); } - trayIconMenu->addAction(optionsAction); - trayIconMenu->addAction(openRPCConsoleAction); -#ifndef Q_OS_MAC // This is built-in on macOS + QAction* options_action = trayIconMenu->addAction(optionsAction->text(), optionsAction, &QAction::trigger); + options_action->setMenuRole(QAction::PreferencesRole); + QAction* node_window_action = trayIconMenu->addAction(openRPCConsoleAction->text(), openRPCConsoleAction, &QAction::trigger); + QAction* quit_action{nullptr}; +#ifndef Q_OS_MAC + // Note: On macOS, the Dock icon's menu already has Quit action. trayIconMenu->addSeparator(); - trayIconMenu->addAction(quitAction); -#endif -} + quit_action = trayIconMenu->addAction(quitAction->text(), quitAction, &QAction::trigger); -#ifndef Q_OS_MAC -void BitcoinGUI::trayIconActivated(QSystemTrayIcon::ActivationReason reason) -{ - if(reason == QSystemTrayIcon::Trigger) - { - // Click on system tray icon triggers show/hide of the main window - toggleHidden(); - } -} + trayIcon->setContextMenu(trayIconMenu.get()); + connect(trayIcon, &QSystemTrayIcon::activated, [this](QSystemTrayIcon::ActivationReason reason) { + if (reason == QSystemTrayIcon::Trigger) { + // Click on system tray icon triggers show/hide of the main window + toggleHidden(); + } + }); #else -void BitcoinGUI::macosDockIconActivated() -{ - show(); - activateWindow(); + // Note: On macOS, the Dock icon is used to provide the tray's functionality. + MacDockIconHandler* dockIconHandler = MacDockIconHandler::instance(); + connect(dockIconHandler, &MacDockIconHandler::dockIconClicked, [this] { + show(); + activateWindow(); + }); + trayIconMenu->setAsDockMenu(); +#endif // Q_OS_MAC + + connect( + // Using QSystemTrayIcon::Context is not reliable. + // See https://bugreports.qt.io/browse/QTBUG-91697 + trayIconMenu.get(), &QMenu::aboutToShow, + [this, show_hide_action, send_action, receive_action, sign_action, verify_action, options_action, node_window_action, quit_action] { + if (show_hide_action) show_hide_action->setText( + (!isHidden() && !isMinimized() && !GUIUtil::isObscured(this)) ? + tr("&Hide") : + tr("S&how")); + if (QApplication::activeModalWidget()) { + for (QAction* a : trayIconMenu.get()->actions()) { + a->setEnabled(false); + } + } else { + if (show_hide_action) show_hide_action->setEnabled(true); + if (enableWallet) { + send_action->setEnabled(sendCoinsAction->isEnabled()); + receive_action->setEnabled(receiveCoinsAction->isEnabled()); + sign_action->setEnabled(signMessageAction->isEnabled()); + verify_action->setEnabled(verifyMessageAction->isEnabled()); + } + options_action->setEnabled(optionsAction->isEnabled()); + node_window_action->setEnabled(openRPCConsoleAction->isEnabled()); + if (quit_action) quit_action->setEnabled(true); + } + }); } -#endif void BitcoinGUI::optionsClicked() { @@ -847,7 +853,7 @@ void BitcoinGUI::aboutClicked() return; auto dlg = new HelpMessageDialog(this, /* about */ true); - GUIUtil::ShowModalDialogAndDeleteOnClose(dlg); + GUIUtil::ShowModalDialogAsynchronously(dlg); } void BitcoinGUI::showDebugWindow() @@ -992,7 +998,7 @@ void BitcoinGUI::openOptionsDialogWithTab(OptionsDialog::Tab tab) connect(dlg, &OptionsDialog::quitOnReset, this, &BitcoinGUI::quitRequested); dlg->setCurrentTab(tab); dlg->setModel(clientModel->getOptionsModel()); - GUIUtil::ShowModalDialogAndDeleteOnClose(dlg); + GUIUtil::ShowModalDialogAsynchronously(dlg); } void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, bool header, SynchronizationState sync_state) diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index 658ab5a210..0ae5f7331e 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -137,7 +137,6 @@ private: QAction* historyAction = nullptr; QAction* quitAction = nullptr; QAction* sendCoinsAction = nullptr; - QAction* sendCoinsMenuAction = nullptr; QAction* usedSendingAddressesAction = nullptr; QAction* usedReceivingAddressesAction = nullptr; QAction* signMessageAction = nullptr; @@ -146,9 +145,7 @@ private: QAction* m_load_psbt_clipboard_action = nullptr; QAction* aboutAction = nullptr; QAction* receiveCoinsAction = nullptr; - QAction* receiveCoinsMenuAction = nullptr; QAction* optionsAction = nullptr; - QAction* toggleHideAction = nullptr; QAction* encryptWalletAction = nullptr; QAction* backupWalletAction = nullptr; QAction* changePassphraseAction = nullptr; @@ -302,13 +299,6 @@ public Q_SLOTS: void showDebugWindowActivateConsole(); /** Show help message dialog */ void showHelpMessageClicked(); -#ifndef Q_OS_MAC - /** Handle tray icon clicked */ - void trayIconActivated(QSystemTrayIcon::ActivationReason reason); -#else - /** Handle macOS Dock icon clicked */ - void macosDockIconActivated(); -#endif /** Show window if hidden, unminimize when minimized, rise when obscured or show if hidden and fToggleHidden is true */ void showNormalIfMinimized() { showNormalIfMinimized(false); } diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index dc73bcd911..9565fa508f 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -984,7 +984,7 @@ void PrintSlotException( PrintExceptionContinue(exception, description.c_str()); } -void ShowModalDialogAndDeleteOnClose(QDialog* dialog) +void ShowModalDialogAsynchronously(QDialog* dialog) { dialog->setAttribute(Qt::WA_DeleteOnClose); dialog->setWindowModality(Qt::ApplicationModal); diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h index 9b25b77325..0224b18b4e 100644 --- a/src/qt/guiutil.h +++ b/src/qt/guiutil.h @@ -426,7 +426,7 @@ namespace GUIUtil /** * Shows a QDialog instance asynchronously, and deletes it on close. */ - void ShowModalDialogAndDeleteOnClose(QDialog* dialog); + void ShowModalDialogAsynchronously(QDialog* dialog); inline bool IsEscapeOrBack(int key) { diff --git a/src/qt/qvalidatedlineedit.cpp b/src/qt/qvalidatedlineedit.cpp index aa936d6b7c..bd4df75d23 100644 --- a/src/qt/qvalidatedlineedit.cpp +++ b/src/qt/qvalidatedlineedit.cpp @@ -15,6 +15,12 @@ QValidatedLineEdit::QValidatedLineEdit(QWidget *parent) : connect(this, &QValidatedLineEdit::textChanged, this, &QValidatedLineEdit::markValid); } +void QValidatedLineEdit::setText(const QString& text) +{ + QLineEdit::setText(text); + checkValidity(); +} + void QValidatedLineEdit::setValid(bool _valid) { if(_valid == this->valid) @@ -28,7 +34,7 @@ void QValidatedLineEdit::setValid(bool _valid) } else { - setStyleSheet(STYLE_INVALID); + setStyleSheet("QValidatedLineEdit { " STYLE_INVALID "}"); } this->valid = _valid; } @@ -106,6 +112,7 @@ void QValidatedLineEdit::checkValidity() void QValidatedLineEdit::setCheckValidator(const QValidator *v) { checkValidator = v; + checkValidity(); } bool QValidatedLineEdit::isValid() diff --git a/src/qt/qvalidatedlineedit.h b/src/qt/qvalidatedlineedit.h index b32305f5e1..12d35aa264 100644 --- a/src/qt/qvalidatedlineedit.h +++ b/src/qt/qvalidatedlineedit.h @@ -29,6 +29,7 @@ private: const QValidator *checkValidator; public Q_SLOTS: + void setText(const QString&); void setValid(bool valid); void setEnabled(bool enabled); diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index e37168830e..579ef0c3fd 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -930,7 +930,7 @@ void SendCoinsDialog::coinControlButtonClicked() { auto dlg = new CoinControlDialog(*m_coin_control, model, platformStyle); connect(dlg, &QDialog::finished, this, &SendCoinsDialog::coinControlUpdateLabels); - GUIUtil::ShowModalDialogAndDeleteOnClose(dlg); + GUIUtil::ShowModalDialogAsynchronously(dlg); } // Coin Control: checkbox custom change address diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp index 1ab1333b72..778ef04b77 100644 --- a/src/qt/transactionview.cpp +++ b/src/qt/transactionview.cpp @@ -511,7 +511,7 @@ void TransactionView::editLabel() : EditAddressDialog::EditSendingAddress, this); dlg->setModel(addressBook); dlg->loadRow(idx); - GUIUtil::ShowModalDialogAndDeleteOnClose(dlg); + GUIUtil::ShowModalDialogAsynchronously(dlg); } else { @@ -520,7 +520,7 @@ void TransactionView::editLabel() this); dlg->setModel(addressBook); dlg->setAddress(address); - GUIUtil::ShowModalDialogAndDeleteOnClose(dlg); + GUIUtil::ShowModalDialogAsynchronously(dlg); } } } diff --git a/src/qt/walletframe.cpp b/src/qt/walletframe.cpp index 08190f0b9f..91ce420a33 100644 --- a/src/qt/walletframe.cpp +++ b/src/qt/walletframe.cpp @@ -226,7 +226,7 @@ void WalletFrame::gotoLoadPSBT(bool from_clipboard) auto dlg = new PSBTOperationsDialog(this, currentWalletModel(), clientModel); dlg->openWithPSBT(psbtx); - GUIUtil::ShowModalDialogAndDeleteOnClose(dlg); + GUIUtil::ShowModalDialogAsynchronously(dlg); } void WalletFrame::encryptWallet() diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp index 7954a66995..e7ec54721a 100644 --- a/src/qt/walletview.cpp +++ b/src/qt/walletview.cpp @@ -208,7 +208,7 @@ void WalletView::encryptWallet() auto dlg = new AskPassphraseDialog(AskPassphraseDialog::Encrypt, this); dlg->setModel(walletModel); connect(dlg, &QDialog::finished, this, &WalletView::encryptionStatusChanged); - GUIUtil::ShowModalDialogAndDeleteOnClose(dlg); + GUIUtil::ShowModalDialogAsynchronously(dlg); } void WalletView::backupWallet() @@ -235,16 +235,18 @@ void WalletView::changePassphrase() { auto dlg = new AskPassphraseDialog(AskPassphraseDialog::ChangePass, this); dlg->setModel(walletModel); - GUIUtil::ShowModalDialogAndDeleteOnClose(dlg); + GUIUtil::ShowModalDialogAsynchronously(dlg); } void WalletView::unlockWallet() { // Unlock wallet when requested by wallet model if (walletModel->getEncryptionStatus() == WalletModel::Locked) { - auto dlg = new AskPassphraseDialog(AskPassphraseDialog::Unlock, this); - dlg->setModel(walletModel); - GUIUtil::ShowModalDialogAndDeleteOnClose(dlg); + AskPassphraseDialog dlg(AskPassphraseDialog::Unlock, this); + dlg.setModel(walletModel); + // A modal dialog must be synchronous here as expected + // in the WalletModel::requestUnlock() function. + dlg.exec(); } } diff --git a/src/random.cpp b/src/random.cpp index 5dae80fe31..b862510524 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -32,10 +32,8 @@ #include <sys/syscall.h> #include <linux/random.h> #endif -#if defined(HAVE_GETENTROPY) || (defined(HAVE_GETENTROPY_RAND) && defined(MAC_OSX)) -#include <unistd.h> -#endif #if defined(HAVE_GETENTROPY_RAND) && defined(MAC_OSX) +#include <unistd.h> #include <sys/random.h> #endif #ifdef HAVE_SYSCTL_ARND @@ -305,16 +303,14 @@ void GetOSRand(unsigned char *ent32) RandFailure(); } } -#elif defined(HAVE_GETENTROPY) && defined(__OpenBSD__) - /* On OpenBSD this can return up to 256 bytes of entropy, will return an - * error if more are requested. - * The call cannot return less than the requested number of bytes. - getentropy is explicitly limited to openbsd here, as a similar (but not - the same) function may exist on other platforms via glibc. +#elif defined(__OpenBSD__) + /* OpenBSD. From the arc4random(3) man page: + "Use of these functions is encouraged for almost all random number + consumption because the other interfaces are deficient in either + quality, portability, standardization, or availability." + The function call is always successful. */ - if (getentropy(ent32, NUM_OS_RANDOM_BYTES) != 0) { - RandFailure(); - } + arc4random_buf(ent32, NUM_OS_RANDOM_BYTES); // Silence a compiler warning about unused function. (void)GetDevURandom; #elif defined(HAVE_GETENTROPY_RAND) && defined(MAC_OSX) diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 7cbe7e6159..69204e346a 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1430,7 +1430,7 @@ static RPCHelpMan verifychain() }; } -static void SoftForkDescPushBack(const CBlockIndex* active_chain_tip, UniValue& softforks, const Consensus::Params& params, Consensus::BuriedDeployment dep) +static void SoftForkDescPushBack(const CBlockIndex* blockindex, UniValue& softforks, const Consensus::Params& params, Consensus::BuriedDeployment dep) { // For buried deployments. @@ -1440,17 +1440,17 @@ static void SoftForkDescPushBack(const CBlockIndex* active_chain_tip, UniValue& rv.pushKV("type", "buried"); // getdeploymentinfo reports the softfork as active from when the chain height is // one below the activation height - rv.pushKV("active", DeploymentActiveAfter(active_chain_tip, params, dep)); + rv.pushKV("active", DeploymentActiveAfter(blockindex, params, dep)); rv.pushKV("height", params.DeploymentHeight(dep)); softforks.pushKV(DeploymentName(dep), rv); } -static void SoftForkDescPushBack(const CBlockIndex* active_chain_tip, UniValue& softforks, const Consensus::Params& consensusParams, Consensus::DeploymentPos id) +static void SoftForkDescPushBack(const CBlockIndex* blockindex, UniValue& softforks, const Consensus::Params& consensusParams, Consensus::DeploymentPos id) { // For BIP9 deployments. if (!DeploymentEnabled(consensusParams, id)) return; - if (active_chain_tip == nullptr) return; + if (blockindex == nullptr) return; auto get_state_name = [](const ThresholdState state) -> std::string { switch (state) { @@ -1465,8 +1465,8 @@ static void SoftForkDescPushBack(const CBlockIndex* active_chain_tip, UniValue& UniValue bip9(UniValue::VOBJ); - const ThresholdState next_state = g_versionbitscache.State(active_chain_tip, consensusParams, id); - const ThresholdState current_state = g_versionbitscache.State(active_chain_tip->pprev, consensusParams, id); + const ThresholdState next_state = g_versionbitscache.State(blockindex, consensusParams, id); + const ThresholdState current_state = g_versionbitscache.State(blockindex->pprev, consensusParams, id); const bool has_signal = (ThresholdState::STARTED == current_state || ThresholdState::LOCKED_IN == current_state); @@ -1480,14 +1480,14 @@ static void SoftForkDescPushBack(const CBlockIndex* active_chain_tip, UniValue& // BIP9 status bip9.pushKV("status", get_state_name(current_state)); - bip9.pushKV("since", g_versionbitscache.StateSinceHeight(active_chain_tip->pprev, consensusParams, id)); + bip9.pushKV("since", g_versionbitscache.StateSinceHeight(blockindex->pprev, consensusParams, id)); bip9.pushKV("status-next", get_state_name(next_state)); // BIP9 signalling status, if applicable if (has_signal) { UniValue statsUV(UniValue::VOBJ); std::vector<bool> signals; - BIP9Stats statsStruct = g_versionbitscache.Statistics(active_chain_tip, consensusParams, id, &signals); + BIP9Stats statsStruct = g_versionbitscache.Statistics(blockindex, consensusParams, id, &signals); statsUV.pushKV("period", statsStruct.period); statsUV.pushKV("elapsed", statsStruct.elapsed); statsUV.pushKV("count", statsStruct.count); @@ -1508,7 +1508,7 @@ static void SoftForkDescPushBack(const CBlockIndex* active_chain_tip, UniValue& UniValue rv(UniValue::VOBJ); rv.pushKV("type", "bip9"); if (ThresholdState::ACTIVE == next_state) { - rv.pushKV("height", g_versionbitscache.StateSinceHeight(active_chain_tip, consensusParams, id)); + rv.pushKV("height", g_versionbitscache.StateSinceHeight(blockindex, consensusParams, id)); } rv.pushKV("active", ThresholdState::ACTIVE == next_state); rv.pushKV("bip9", bip9); @@ -1517,7 +1517,7 @@ static void SoftForkDescPushBack(const CBlockIndex* active_chain_tip, UniValue& } namespace { -/* TODO: when -dprecatedrpc=softforks is removed, drop these */ +/* TODO: when -deprecatedrpc=softforks is removed, drop these */ UniValue DeploymentInfo(const CBlockIndex* tip, const Consensus::Params& consensusParams); extern const std::vector<RPCResult> RPCHelpForDeployment; } @@ -1621,9 +1621,9 @@ const std::vector<RPCResult> RPCHelpForDeployment{ {RPCResult::Type::NUM_TIME, "start_time", "the minimum median time past of a block at which the bit gains its meaning"}, {RPCResult::Type::NUM_TIME, "timeout", "the median time past of a block at which the deployment is considered failed if not yet locked in"}, {RPCResult::Type::NUM, "min_activation_height", "minimum height of blocks for which the rules may be enforced"}, - {RPCResult::Type::STR, "status", "bip9 status of specified block (one of \"defined\", \"started\", \"locked_in\", \"active\", \"failed\")"}, + {RPCResult::Type::STR, "status", "status of deployment at specified block (one of \"defined\", \"started\", \"locked_in\", \"active\", \"failed\")"}, {RPCResult::Type::NUM, "since", "height of the first block to which the status applies"}, - {RPCResult::Type::STR, "status-next", "bip9 status of next block"}, + {RPCResult::Type::STR, "status-next", "status of deployment at the next block"}, {RPCResult::Type::OBJ, "statistics", /*optional=*/true, "numeric statistics about signalling for a softfork (only for \"started\" and \"locked_in\" status)", { {RPCResult::Type::NUM, "period", "the length in blocks of the signalling period"}, @@ -1636,16 +1636,16 @@ const std::vector<RPCResult> RPCHelpForDeployment{ }}, }; -UniValue DeploymentInfo(const CBlockIndex* tip, const Consensus::Params& consensusParams) +UniValue DeploymentInfo(const CBlockIndex* blockindex, const Consensus::Params& consensusParams) { UniValue softforks(UniValue::VOBJ); - SoftForkDescPushBack(tip, softforks, consensusParams, Consensus::DEPLOYMENT_HEIGHTINCB); - SoftForkDescPushBack(tip, softforks, consensusParams, Consensus::DEPLOYMENT_DERSIG); - SoftForkDescPushBack(tip, softforks, consensusParams, Consensus::DEPLOYMENT_CLTV); - SoftForkDescPushBack(tip, softforks, consensusParams, Consensus::DEPLOYMENT_CSV); - SoftForkDescPushBack(tip, softforks, consensusParams, Consensus::DEPLOYMENT_SEGWIT); - SoftForkDescPushBack(tip, softforks, consensusParams, Consensus::DEPLOYMENT_TESTDUMMY); - SoftForkDescPushBack(tip, softforks, consensusParams, Consensus::DEPLOYMENT_TAPROOT); + SoftForkDescPushBack(blockindex, softforks, consensusParams, Consensus::DEPLOYMENT_HEIGHTINCB); + SoftForkDescPushBack(blockindex, softforks, consensusParams, Consensus::DEPLOYMENT_DERSIG); + SoftForkDescPushBack(blockindex, softforks, consensusParams, Consensus::DEPLOYMENT_CLTV); + SoftForkDescPushBack(blockindex, softforks, consensusParams, Consensus::DEPLOYMENT_CSV); + SoftForkDescPushBack(blockindex, softforks, consensusParams, Consensus::DEPLOYMENT_SEGWIT); + SoftForkDescPushBack(blockindex, softforks, consensusParams, Consensus::DEPLOYMENT_TESTDUMMY); + SoftForkDescPushBack(blockindex, softforks, consensusParams, Consensus::DEPLOYMENT_TAPROOT); return softforks; } } // anon namespace @@ -1653,9 +1653,9 @@ UniValue DeploymentInfo(const CBlockIndex* tip, const Consensus::Params& consens static RPCHelpMan getdeploymentinfo() { return RPCHelpMan{"getdeploymentinfo", - "Returns an object containing various state info regarding soft-forks.", + "Returns an object containing various state info regarding deployments of consensus changes.", { - {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Default{"chain tip"}, "The block hash at which to query fork state"}, + {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Default{"hash of current chain tip"}, "The block hash at which to query deployment state"}, }, RPCResult{ RPCResult::Type::OBJ, "", "", { @@ -1669,18 +1669,18 @@ static RPCHelpMan getdeploymentinfo() RPCExamples{ HelpExampleCli("getdeploymentinfo", "") + HelpExampleRpc("getdeploymentinfo", "") }, [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue { - ChainstateManager& chainman = EnsureAnyChainman(request.context); + const ChainstateManager& chainman = EnsureAnyChainman(request.context); LOCK(cs_main); - CChainState& active_chainstate = chainman.ActiveChainstate(); + const CChainState& active_chainstate = chainman.ActiveChainstate(); - const CBlockIndex* tip; + const CBlockIndex* blockindex; if (request.params[0].isNull()) { - tip = active_chainstate.m_chain.Tip(); - CHECK_NONFATAL(tip); + blockindex = active_chainstate.m_chain.Tip(); + CHECK_NONFATAL(blockindex); } else { - uint256 hash(ParseHashV(request.params[0], "blockhash")); - tip = chainman.m_blockman.LookupBlockIndex(hash); - if (!tip) { + const uint256 hash(ParseHashV(request.params[0], "blockhash")); + blockindex = chainman.m_blockman.LookupBlockIndex(hash); + if (!blockindex) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); } } @@ -1688,9 +1688,9 @@ static RPCHelpMan getdeploymentinfo() const Consensus::Params& consensusParams = Params().GetConsensus(); UniValue deploymentinfo(UniValue::VOBJ); - deploymentinfo.pushKV("hash", tip->GetBlockHash().ToString()); - deploymentinfo.pushKV("height", tip->nHeight); - deploymentinfo.pushKV("deployments", DeploymentInfo(tip, consensusParams)); + deploymentinfo.pushKV("hash", blockindex->GetBlockHash().ToString()); + deploymentinfo.pushKV("height", blockindex->nHeight); + deploymentinfo.pushKV("deployments", DeploymentInfo(blockindex, consensusParams)); return deploymentinfo; }, }; diff --git a/src/script/script.h b/src/script/script.h index 3425bf8102..8b7a7bb7b3 100644 --- a/src/script/script.h +++ b/src/script/script.h @@ -51,10 +51,10 @@ static const uint32_t LOCKTIME_MAX = 0xFFFFFFFFU; static constexpr unsigned int ANNEX_TAG = 0x50; // Validation weight per passing signature (Tapscript only, see BIP 342). -static constexpr uint64_t VALIDATION_WEIGHT_PER_SIGOP_PASSED = 50; +static constexpr int64_t VALIDATION_WEIGHT_PER_SIGOP_PASSED{50}; // How much weight budget is added to the witness size (Tapscript only, see BIP 342). -static constexpr uint64_t VALIDATION_WEIGHT_OFFSET = 50; +static constexpr int64_t VALIDATION_WEIGHT_OFFSET{50}; template <typename T> std::vector<unsigned char> ToByteVector(const T& in) diff --git a/src/streams.h b/src/streams.h index 2f26be6dd8..cf8b4eb96f 100644 --- a/src/streams.h +++ b/src/streams.h @@ -240,76 +240,9 @@ public: const_reference operator[](size_type pos) const { return vch[pos + nReadPos]; } reference operator[](size_type pos) { return vch[pos + nReadPos]; } void clear() { vch.clear(); nReadPos = 0; } - iterator insert(iterator it, const value_type x) { return vch.insert(it, x); } - void insert(iterator it, size_type n, const value_type x) { vch.insert(it, n, x); } value_type* data() { return vch.data() + nReadPos; } const value_type* data() const { return vch.data() + nReadPos; } - void insert(iterator it, std::vector<value_type>::const_iterator first, std::vector<value_type>::const_iterator last) - { - if (last == first) return; - assert(last - first > 0); - if (it == vch.begin() + nReadPos && (unsigned int)(last - first) <= nReadPos) - { - // special case for inserting at the front when there's room - nReadPos -= (last - first); - memcpy(&vch[nReadPos], &first[0], last - first); - } - else - vch.insert(it, first, last); - } - - void insert(iterator it, const value_type* first, const value_type* last) - { - if (last == first) return; - assert(last - first > 0); - if (it == vch.begin() + nReadPos && (unsigned int)(last - first) <= nReadPos) - { - // special case for inserting at the front when there's room - nReadPos -= (last - first); - memcpy(&vch[nReadPos], &first[0], last - first); - } - else - vch.insert(it, first, last); - } - - iterator erase(iterator it) - { - if (it == vch.begin() + nReadPos) - { - // special case for erasing from the front - if (++nReadPos >= vch.size()) - { - // whenever we reach the end, we take the opportunity to clear the buffer - nReadPos = 0; - return vch.erase(vch.begin(), vch.end()); - } - return vch.begin() + nReadPos; - } - else - return vch.erase(it); - } - - iterator erase(iterator first, iterator last) - { - if (first == vch.begin() + nReadPos) - { - // special case for erasing from the front - if (last == vch.end()) - { - nReadPos = 0; - return vch.erase(vch.begin(), vch.end()); - } - else - { - nReadPos = (last - vch.begin()); - return last; - } - } - else - return vch.erase(first, last); - } - inline void Compact() { vch.erase(vch.begin(), vch.begin() + nReadPos); diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp index 922fd8e513..82e4e1c90f 100644 --- a/src/test/coins_tests.cpp +++ b/src/test/coins_tests.cpp @@ -324,7 +324,7 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test) tx.vout.resize(1); tx.vout[0].nValue = i; //Keep txs unique unless intended to duplicate tx.vout[0].scriptPubKey.assign(InsecureRand32() & 0x3F, 0); // Random sizes so we can test memory usage accounting - unsigned int height = InsecureRand32(); + const int height{int(InsecureRand32() >> 1)}; Coin old_coin; // 2/20 times create a new coinbase @@ -393,11 +393,11 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test) // Update the expected result to know about the new output coins assert(tx.vout.size() == 1); const COutPoint outpoint(tx.GetHash(), 0); - result[outpoint] = Coin{tx.vout[0], int(height), CTransaction(tx).IsCoinBase()}; + result[outpoint] = Coin{tx.vout[0], height, CTransaction{tx}.IsCoinBase()}; // Call UpdateCoins on the top cache CTxUndo undo; - UpdateCoins(CTransaction(tx), *(stack.back()), undo, int(height)); + UpdateCoins(CTransaction{tx}, *(stack.back()), undo, height); // Update the utxo set for future spends utxoset.insert(outpoint); diff --git a/src/test/data/script_tests.json b/src/test/data/script_tests.json index 724789bbf9..ad05240369 100644 --- a/src/test/data/script_tests.json +++ b/src/test/data/script_tests.json @@ -1269,6 +1269,10 @@ [["51", 0.00000000 ], "", "0 0x206e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d", "P2SH,WITNESS", "WITNESS_PROGRAM_MISMATCH", "Witness script hash mismatch"], [["00", 0.00000000 ], "", "0 0x206e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d", "", "OK", "Invalid witness script without WITNESS"], [["51", 0.00000000 ], "", "0 0x206e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d", "", "OK", "Witness script hash mismatch without WITNESS"], +[["51", 0.00000000 ], "", "-1 0x021234", "P2SH,WITNESS", "WITNESS_UNEXPECTED", "OP_1NEGATE does not introduce a witness program"], +[["51", 0.00000000 ], "00", "1 0x021234", "P2SH,WITNESS", "WITNESS_MALLEATED", "OP_1 does introduce a witness program"], +[["51", 0.00000000 ], "00", "16 0x021234", "P2SH,WITNESS", "WITNESS_MALLEATED", "OP_16 does introduce a witness program"], +[["51", 0.00000000 ], "", "NOP 0x021234", "P2SH,WITNESS", "WITNESS_UNEXPECTED", "NOP does not introduce a witness program"], ["Automatically generated test cases"], [ diff --git a/src/test/dbwrapper_tests.cpp b/src/test/dbwrapper_tests.cpp index 2f95cc27a3..fc89fe1450 100644 --- a/src/test/dbwrapper_tests.cpp +++ b/src/test/dbwrapper_tests.cpp @@ -203,7 +203,7 @@ BOOST_AUTO_TEST_CASE(existing_data_no_obfuscate) { // We're going to share this fs::path between two wrappers fs::path ph = m_args.GetDataDirBase() / "existing_data_no_obfuscate"; - create_directories(ph); + fs::create_directories(ph); // Set up a non-obfuscated wrapper to write some initial data. std::unique_ptr<CDBWrapper> dbw = std::make_unique<CDBWrapper>(ph, (1 << 10), false, false, false); @@ -244,7 +244,7 @@ BOOST_AUTO_TEST_CASE(existing_data_reindex) { // We're going to share this fs::path between two wrappers fs::path ph = m_args.GetDataDirBase() / "existing_data_reindex"; - create_directories(ph); + fs::create_directories(ph); // Set up a non-obfuscated wrapper to write some initial data. std::unique_ptr<CDBWrapper> dbw = std::make_unique<CDBWrapper>(ph, (1 << 10), false, false, false); diff --git a/src/test/fs_tests.cpp b/src/test/fs_tests.cpp index 1256395849..313064b294 100644 --- a/src/test/fs_tests.cpp +++ b/src/test/fs_tests.cpp @@ -118,4 +118,62 @@ BOOST_AUTO_TEST_CASE(fsbridge_fstream) } } -BOOST_AUTO_TEST_SUITE_END()
\ No newline at end of file +BOOST_AUTO_TEST_CASE(rename) +{ + const fs::path tmpfolder{m_args.GetDataDirBase()}; + + const fs::path path1{GetUniquePath(tmpfolder)}; + const fs::path path2{GetUniquePath(tmpfolder)}; + + const std::string path1_contents{"1111"}; + const std::string path2_contents{"2222"}; + + { + std::ofstream file{path1}; + file << path1_contents; + } + + { + std::ofstream file{path2}; + file << path2_contents; + } + + // Rename path1 -> path2. + BOOST_CHECK(RenameOver(path1, path2)); + + BOOST_CHECK(!fs::exists(path1)); + + { + std::ifstream file{path2}; + std::string contents; + file >> contents; + BOOST_CHECK_EQUAL(contents, path1_contents); + } + fs::remove(path2); +} + +#ifndef WIN32 +BOOST_AUTO_TEST_CASE(create_directories) +{ + // Test fs::create_directories workaround. + const fs::path tmpfolder{m_args.GetDataDirBase()}; + + const fs::path dir{GetUniquePath(tmpfolder)}; + fs::create_directory(dir); + BOOST_CHECK(fs::exists(dir)); + BOOST_CHECK(fs::is_directory(dir)); + BOOST_CHECK(!fs::create_directories(dir)); + + const fs::path symlink{GetUniquePath(tmpfolder)}; + fs::create_directory_symlink(dir, symlink); + BOOST_CHECK(fs::exists(symlink)); + BOOST_CHECK(fs::is_symlink(symlink)); + BOOST_CHECK(fs::is_directory(symlink)); + BOOST_CHECK(!fs::create_directories(symlink)); + + fs::remove(symlink); + fs::remove(dir); +} +#endif // WIN32 + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/fuzz/coins_view.cpp b/src/test/fuzz/coins_view.cpp index 994b4b9e49..360dc00307 100644 --- a/src/test/fuzz/coins_view.cpp +++ b/src/test/fuzz/coins_view.cpp @@ -211,7 +211,7 @@ FUZZ_TARGET_INIT(coins_view, initialize_coins_view) return; } bool expected_code_path = false; - const int height = fuzzed_data_provider.ConsumeIntegral<int>(); + const int height{int(fuzzed_data_provider.ConsumeIntegral<uint32_t>() >> 1)}; const bool possible_overwrite = fuzzed_data_provider.ConsumeBool(); try { AddCoins(coins_view_cache, transaction, height, possible_overwrite); diff --git a/src/test/fuzz/script.cpp b/src/test/fuzz/script.cpp index 14a59912db..fdcd0da37d 100644 --- a/src/test/fuzz/script.cpp +++ b/src/test/fuzz/script.cpp @@ -167,12 +167,4 @@ FUZZ_TARGET_INIT(script, initialize_script) Assert(dest == GetScriptForDestination(tx_destination_2)); } } - - (void)FormatScript(script); - (void)ScriptToAsmStr(script, /*fAttemptSighashDecode=*/fuzzed_data_provider.ConsumeBool()); - - UniValue o1(UniValue::VOBJ); - ScriptPubKeyToUniv(script, o1, /*include_hex=*/fuzzed_data_provider.ConsumeBool()); - UniValue o3(UniValue::VOBJ); - ScriptToUniv(script, o3); } diff --git a/src/test/fuzz/script_format.cpp b/src/test/fuzz/script_format.cpp new file mode 100644 index 0000000000..2fa893f812 --- /dev/null +++ b/src/test/fuzz/script_format.cpp @@ -0,0 +1,30 @@ +// Copyright (c) 2019-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 <chainparams.h> +#include <core_io.h> +#include <script/script.h> +#include <test/fuzz/FuzzedDataProvider.h> +#include <test/fuzz/fuzz.h> +#include <test/fuzz/util.h> +#include <univalue.h> + +void initialize_script_format() +{ + SelectParams(CBaseChainParams::REGTEST); +} + +FUZZ_TARGET_INIT(script_format, initialize_script_format) +{ + FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); + const CScript script{ConsumeScript(fuzzed_data_provider)}; + + (void)FormatScript(script); + (void)ScriptToAsmStr(script, /*fAttemptSighashDecode=*/fuzzed_data_provider.ConsumeBool()); + + UniValue o1(UniValue::VOBJ); + ScriptPubKeyToUniv(script, o1, /*include_hex=*/fuzzed_data_provider.ConsumeBool()); + UniValue o3(UniValue::VOBJ); + ScriptToUniv(script, o3); +} diff --git a/src/test/fuzz/string.cpp b/src/test/fuzz/string.cpp index 8f071b71fe..ca57af25c4 100644 --- a/src/test/fuzz/string.cpp +++ b/src/test/fuzz/string.cpp @@ -145,7 +145,8 @@ FUZZ_TARGET(string) (void)CopyrightHolders(random_string_1); FeeEstimateMode fee_estimate_mode; (void)FeeModeFromString(random_string_1, fee_estimate_mode); - (void)FormatParagraph(random_string_1, fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 1000), fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 1000)); + const auto width{fuzzed_data_provider.ConsumeIntegralInRange<size_t>(1, 1000)}; + (void)FormatParagraph(random_string_1, width, fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, width)); (void)FormatSubVersion(random_string_1, fuzzed_data_provider.ConsumeIntegral<int>(), random_string_vector); (void)GetDescriptorChecksum(random_string_1); (void)HelpExampleCli(random_string_1, random_string_2); diff --git a/src/test/getarg_tests.cpp b/src/test/getarg_tests.cpp index d5142c8d74..597d774673 100644 --- a/src/test/getarg_tests.cpp +++ b/src/test/getarg_tests.cpp @@ -159,6 +159,98 @@ BOOST_AUTO_TEST_CASE(intarg) BOOST_CHECK_EQUAL(m_local_args.GetIntArg("-bar", 11), 0); } +BOOST_AUTO_TEST_CASE(patharg) +{ + const auto dir = std::make_pair("-dir", ArgsManager::ALLOW_ANY); + SetupArgs({dir}); + ResetArgs(""); + BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), fs::path{}); + + const fs::path root_path{"/"}; + ResetArgs("-dir=/"); + BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), root_path); + + ResetArgs("-dir=/."); + BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), root_path); + + ResetArgs("-dir=/./"); + BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), root_path); + + ResetArgs("-dir=/.//"); + BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), root_path); + +#ifdef WIN32 + const fs::path win_root_path{"C:\\"}; + ResetArgs("-dir=C:\\"); + BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), win_root_path); + + ResetArgs("-dir=C:/"); + BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), win_root_path); + + ResetArgs("-dir=C:\\\\"); + BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), win_root_path); + + ResetArgs("-dir=C:\\."); + BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), win_root_path); + + ResetArgs("-dir=C:\\.\\"); + BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), win_root_path); + + ResetArgs("-dir=C:\\.\\\\"); + BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), win_root_path); +#endif + + const fs::path absolute_path{"/home/user/.bitcoin"}; + ResetArgs("-dir=/home/user/.bitcoin"); + BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), absolute_path); + + ResetArgs("-dir=/root/../home/user/.bitcoin"); + BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), absolute_path); + + ResetArgs("-dir=/home/./user/.bitcoin"); + BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), absolute_path); + + ResetArgs("-dir=/home/user/.bitcoin/"); + BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), absolute_path); + + ResetArgs("-dir=/home/user/.bitcoin//"); + BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), absolute_path); + + ResetArgs("-dir=/home/user/.bitcoin/."); + BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), absolute_path); + + ResetArgs("-dir=/home/user/.bitcoin/./"); + BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), absolute_path); + + ResetArgs("-dir=/home/user/.bitcoin/.//"); + BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), absolute_path); + + const fs::path relative_path{"user/.bitcoin"}; + ResetArgs("-dir=user/.bitcoin"); + BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path); + + ResetArgs("-dir=somewhere/../user/.bitcoin"); + BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path); + + ResetArgs("-dir=user/./.bitcoin"); + BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path); + + ResetArgs("-dir=user/.bitcoin/"); + BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path); + + ResetArgs("-dir=user/.bitcoin//"); + BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path); + + ResetArgs("-dir=user/.bitcoin/."); + BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path); + + ResetArgs("-dir=user/.bitcoin/./"); + BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path); + + ResetArgs("-dir=user/.bitcoin/.//"); + BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path); +} + BOOST_AUTO_TEST_CASE(doubledash) { const auto foo = std::make_pair("-foo", ArgsManager::ALLOW_ANY); diff --git a/src/test/main.cpp b/src/test/main.cpp index 1ad8fcce3a..73bb331e21 100644 --- a/src/test/main.cpp +++ b/src/test/main.cpp @@ -3,11 +3,11 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. /** - * See https://www.boost.org/doc/libs/1_71_0/libs/test/doc/html/boost_test/utf_reference/link_references/link_boost_test_module_macro.html + * See https://www.boost.org/doc/libs/1_78_0/libs/test/doc/html/boost_test/adv_scenarios/single_header_customizations/multiple_translation_units.html */ #define BOOST_TEST_MODULE Bitcoin Core Test Suite -#include <boost/test/unit_test.hpp> +#include <boost/test/included/unit_test.hpp> #include <test/util/setup_common.h> diff --git a/src/test/serialize_tests.cpp b/src/test/serialize_tests.cpp index 8b8133b689..2441847f99 100644 --- a/src/test/serialize_tests.cpp +++ b/src/test/serialize_tests.cpp @@ -215,51 +215,6 @@ BOOST_AUTO_TEST_CASE(noncanonical) BOOST_CHECK_EXCEPTION(ReadCompactSize(ss), std::ios_base::failure, isCanonicalException); } -BOOST_AUTO_TEST_CASE(insert_delete) -{ - constexpr auto B2I{[](std::byte b) { return std::to_integer<uint8_t>(b); }}; - - // Test inserting/deleting bytes. - CDataStream ss(SER_DISK, 0); - BOOST_CHECK_EQUAL(ss.size(), 0U); - - ss.write(MakeByteSpan("\x00\x01\x02\xff").first(4)); - BOOST_CHECK_EQUAL(ss.size(), 4U); - - uint8_t c{11}; - - // Inserting at beginning/end/middle: - ss.insert(ss.begin(), std::byte{c}); - BOOST_CHECK_EQUAL(ss.size(), 5U); - BOOST_CHECK_EQUAL(B2I(ss[0]), c); - BOOST_CHECK_EQUAL(B2I(ss[1]), 0); - - ss.insert(ss.end(), std::byte{c}); - BOOST_CHECK_EQUAL(ss.size(), 6U); - BOOST_CHECK_EQUAL(B2I(ss[4]), 0xff); - BOOST_CHECK_EQUAL(B2I(ss[5]), c); - - ss.insert(ss.begin() + 2, std::byte{c}); - BOOST_CHECK_EQUAL(ss.size(), 7U); - BOOST_CHECK_EQUAL(B2I(ss[2]), c); - - // Delete at beginning/end/middle - ss.erase(ss.begin()); - BOOST_CHECK_EQUAL(ss.size(), 6U); - BOOST_CHECK_EQUAL(B2I(ss[0]), 0); - - ss.erase(ss.begin()+ss.size()-1); - BOOST_CHECK_EQUAL(ss.size(), 5U); - BOOST_CHECK_EQUAL(B2I(ss[4]), 0xff); - - ss.erase(ss.begin()+1); - BOOST_CHECK_EQUAL(ss.size(), 4U); - BOOST_CHECK_EQUAL(B2I(ss[0]), 0); - BOOST_CHECK_EQUAL(B2I(ss[1]), 1); - BOOST_CHECK_EQUAL(B2I(ss[2]), 2); - BOOST_CHECK_EQUAL(B2I(ss[3]), 0xff); -} - BOOST_AUTO_TEST_CASE(class_methods) { int intval(100); diff --git a/src/test/streams_tests.cpp b/src/test/streams_tests.cpp index 6a69fe9840..0925e2e9ee 100644 --- a/src/test/streams_tests.cpp +++ b/src/test/streams_tests.cpp @@ -8,6 +8,8 @@ #include <boost/test/unit_test.hpp> +using namespace std::string_literals; + BOOST_FIXTURE_TEST_SUITE(streams_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(streams_vector_writer) @@ -162,46 +164,35 @@ BOOST_AUTO_TEST_CASE(bitstream_reader_writer) BOOST_AUTO_TEST_CASE(streams_serializedata_xor) { std::vector<std::byte> in; - std::vector<char> expected_xor; - CDataStream ds(in, 0, 0); // Degenerate case - ds.Xor({0x00, 0x00}); - BOOST_CHECK_EQUAL( - std::string(expected_xor.begin(), expected_xor.end()), - ds.str()); + { + CDataStream ds{in, 0, 0}; + ds.Xor({0x00, 0x00}); + BOOST_CHECK_EQUAL(""s, ds.str()); + } in.push_back(std::byte{0x0f}); in.push_back(std::byte{0xf0}); - expected_xor.push_back('\xf0'); - expected_xor.push_back('\x0f'); // Single character key - - ds.clear(); - ds.insert(ds.begin(), in.begin(), in.end()); - - ds.Xor({0xff}); - BOOST_CHECK_EQUAL( - std::string(expected_xor.begin(), expected_xor.end()), - ds.str()); + { + CDataStream ds{in, 0, 0}; + ds.Xor({0xff}); + BOOST_CHECK_EQUAL("\xf0\x0f"s, ds.str()); + } // Multi character key in.clear(); - expected_xor.clear(); in.push_back(std::byte{0xf0}); in.push_back(std::byte{0x0f}); - expected_xor.push_back('\x0f'); - expected_xor.push_back('\x00'); - - ds.clear(); - ds.insert(ds.begin(), in.begin(), in.end()); - ds.Xor({0xff, 0x0f}); - BOOST_CHECK_EQUAL( - std::string(expected_xor.begin(), expected_xor.end()), - ds.str()); + { + CDataStream ds{in, 0, 0}; + ds.Xor({0xff, 0x0f}); + BOOST_CHECK_EQUAL("\x0f\x00"s, ds.str()); + } } BOOST_AUTO_TEST_CASE(streams_buffered_file) diff --git a/src/util/strencodings.cpp b/src/util/strencodings.cpp index a386f2b7b3..940fa90da2 100644 --- a/src/util/strencodings.cpp +++ b/src/util/strencodings.cpp @@ -113,7 +113,7 @@ void SplitHostPort(std::string in, uint16_t& portOut, std::string& hostOut) // if a : is found, and it either follows a [...], or no other : is in the string, treat it as port separator bool fHaveColon = colon != in.npos; bool fBracketed = fHaveColon && (in[0] == '[' && in[colon - 1] == ']'); // if there is a colon, and in[0]=='[', colon is not 0, so in[colon-1] is safe - bool fMultiColon = fHaveColon && (in.find_last_of(':', colon - 1) != in.npos); + bool fMultiColon{fHaveColon && colon != 0 && (in.find_last_of(':', colon - 1) != in.npos)}; if (fHaveColon && (colon == 0 || fBracketed || !fMultiColon)) { uint16_t n; if (ParseUInt16(in.substr(colon + 1), &n)) { @@ -328,6 +328,7 @@ bool ParseUInt64(const std::string& str, uint64_t* out) std::string FormatParagraph(const std::string& in, size_t width, size_t indent) { + assert(width >= indent); std::stringstream out; size_t ptr = 0; size_t indented = 0; diff --git a/src/util/syscall_sandbox.cpp b/src/util/syscall_sandbox.cpp index 4157be9d9f..f513dba598 100644 --- a/src/util/syscall_sandbox.cpp +++ b/src/util/syscall_sandbox.cpp @@ -600,6 +600,7 @@ public: allowed_syscalls.insert(__NR_statfs); // get filesystem statistics allowed_syscalls.insert(__NR_statx); // get file status (extended) allowed_syscalls.insert(__NR_unlink); // delete a name and possibly the file it refers to + allowed_syscalls.insert(__NR_unlinkat); // delete relative to a directory file descriptor } void AllowFutex() diff --git a/src/util/system.cpp b/src/util/system.cpp index 8d0cec249d..69811a751b 100644 --- a/src/util/system.cpp +++ b/src/util/system.cpp @@ -74,6 +74,7 @@ #include <memory> #include <optional> #include <string> +#include <system_error> #include <thread> #include <typeinfo> @@ -245,19 +246,6 @@ static std::optional<util::SettingsValue> InterpretValue(const KeyInfo& key, con return value; } -namespace { -fs::path StripRedundantLastElementsOfPath(const fs::path& path) -{ - auto result = path; - while (result.filename().empty() || fs::PathToString(result.filename()) == ".") { - result = result.parent_path(); - } - - assert(fs::equivalent(result, path.lexically_normal())); - return result; -} -} // namespace - // Define default constructor and destructor that are not inline, so code instantiating this class doesn't need to // #include class definitions for all members. // For example, m_settings has an internal dependency on univalue. @@ -399,6 +387,13 @@ std::optional<unsigned int> ArgsManager::GetArgFlags(const std::string& name) co return std::nullopt; } +fs::path ArgsManager::GetPathArg(std::string pathlike_arg) const +{ + auto result = fs::PathFromString(GetArg(pathlike_arg, "")).lexically_normal(); + // Remove trailing slash, if present. + return result.has_filename() ? result : result.parent_path(); +} + const fs::path& ArgsManager::GetBlocksDirPath() const { LOCK(cs_args); @@ -409,7 +404,7 @@ const fs::path& ArgsManager::GetBlocksDirPath() const if (!path.empty()) return path; if (IsArgSet("-blocksdir")) { - path = fs::absolute(fs::PathFromString(GetArg("-blocksdir", ""))); + path = fs::absolute(GetPathArg("-blocksdir")); if (!fs::is_directory(path)) { path = ""; return path; @@ -433,9 +428,9 @@ const fs::path& ArgsManager::GetDataDir(bool net_specific) const // this function if (!path.empty()) return path; - std::string datadir = GetArg("-datadir", ""); + const fs::path datadir{GetPathArg("-datadir")}; if (!datadir.empty()) { - path = fs::absolute(StripRedundantLastElementsOfPath(fs::PathFromString(datadir))); + path = fs::absolute(datadir); if (!fs::is_directory(path)) { path = ""; return path; @@ -443,15 +438,18 @@ const fs::path& ArgsManager::GetDataDir(bool net_specific) const } else { path = GetDefaultDataDir(); } - if (net_specific) - path /= fs::PathFromString(BaseParams().DataDir()); - if (fs::create_directories(path)) { - // This is the first run, create wallets subdirectory too + if (!fs::exists(path)) { fs::create_directories(path / "wallets"); } - path = StripRedundantLastElementsOfPath(path); + if (net_specific && !BaseParams().DataDir().empty()) { + path /= fs::PathFromString(BaseParams().DataDir()); + if (!fs::exists(path)) { + fs::create_directories(path / "wallets"); + } + } + return path; } @@ -812,8 +810,8 @@ fs::path GetDefaultDataDir() bool CheckDataDirOption() { - std::string datadir = gArgs.GetArg("-datadir", ""); - return datadir.empty() || fs::is_directory(fs::absolute(fs::PathFromString(datadir))); + const fs::path datadir{gArgs.GetPathArg("-datadir")}; + return datadir.empty() || fs::is_directory(fs::absolute(datadir)); } fs::path GetConfigFile(const std::string& confPath) @@ -1064,13 +1062,20 @@ void ArgsManager::LogArgs() const bool RenameOver(fs::path src, fs::path dest) { -#ifdef WIN32 +#ifdef __MINGW64__ + // This is a workaround for a bug in libstdc++ which + // implements std::filesystem::rename with _wrename function. + // This bug has been fixed in upstream: + // - GCC 10.3: 8dd1c1085587c9f8a21bb5e588dfe1e8cdbba79e + // - GCC 11.1: 1dfd95f0a0ca1d9e6cbc00e6cbfd1fa20a98f312 + // For more details see the commits mentioned above. return MoveFileExW(src.wstring().c_str(), dest.wstring().c_str(), MOVEFILE_REPLACE_EXISTING) != 0; #else - int rc = std::rename(src.c_str(), dest.c_str()); - return (rc == 0); -#endif /* WIN32 */ + std::error_code error; + fs::rename(src, dest, error); + return !error; +#endif } /** diff --git a/src/util/system.h b/src/util/system.h index a8fd21fcaa..a72ba3f3ed 100644 --- a/src/util/system.h +++ b/src/util/system.h @@ -69,7 +69,13 @@ void DirectoryCommit(const fs::path &dirname); bool TruncateFile(FILE *file, unsigned int length); int RaiseFileDescriptorLimit(int nMinFD); void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length); + +/** + * Rename src to dest. + * @return true if the rename was successful. + */ [[nodiscard]] bool RenameOver(fs::path src, fs::path dest); + bool LockDirectory(const fs::path& directory, const std::string lockfile_name, bool probe_only=false); void UnlockDirectory(const fs::path& directory, const std::string& lockfile_name); bool DirIsWritable(const fs::path& directory); @@ -265,6 +271,16 @@ protected: std::optional<const Command> GetCommand() const; /** + * Get a normalized path from a specified pathlike argument + * + * It is guaranteed that the returned path has no trailing slashes. + * + * @param pathlike_arg Pathlike argument to get a path from (e.g., "-datadir", "-blocksdir" or "-walletdir") + * @return Normalized path which is get from a specified pathlike argument + */ + fs::path GetPathArg(std::string pathlike_arg) const; + + /** * Get blocks directory path * * @return Blocks path which is network specific diff --git a/src/validation.cpp b/src/validation.cpp index c12dc9e8b6..5b52638fc5 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -286,8 +286,10 @@ bool CheckSequenceLocks(CBlockIndex* tip, static unsigned int GetBlockScriptFlags(const CBlockIndex* pindex, const Consensus::Params& chainparams); static void LimitMempoolSize(CTxMemPool& pool, CCoinsViewCache& coins_cache, size_t limit, std::chrono::seconds age) - EXCLUSIVE_LOCKS_REQUIRED(pool.cs, ::cs_main) + EXCLUSIVE_LOCKS_REQUIRED(::cs_main, pool.cs) { + AssertLockHeld(::cs_main); + AssertLockHeld(pool.cs); int expired = pool.Expire(GetTime<std::chrono::seconds>() - age); if (expired != 0) { LogPrint(BCLog::MEMPOOL, "Expired %i transactions from the memory pool\n", expired); @@ -628,8 +630,10 @@ private: EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_pool.cs); // Compare a package's feerate against minimum allowed. - bool CheckFeeRate(size_t package_size, CAmount package_fee, TxValidationState& state) EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_pool.cs) + bool CheckFeeRate(size_t package_size, CAmount package_fee, TxValidationState& state) EXCLUSIVE_LOCKS_REQUIRED(::cs_main, m_pool.cs) { + AssertLockHeld(::cs_main); + AssertLockHeld(m_pool.cs); CAmount mempoolRejectFee = m_pool.GetMinFee(gArgs.GetIntArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000).GetFee(package_size); if (mempoolRejectFee > 0 && package_fee < mempoolRejectFee) { return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "mempool min fee not met", strprintf("%d < %d", package_fee, mempoolRejectFee)); @@ -663,6 +667,8 @@ private: bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws) { + AssertLockHeld(cs_main); + AssertLockHeld(m_pool.cs); const CTransactionRef& ptx = ws.m_ptx; const CTransaction& tx = *ws.m_ptx; const uint256& hash = ws.m_hash; @@ -963,6 +969,8 @@ bool MemPoolAccept::PackageMempoolChecks(const std::vector<CTransactionRef>& txn bool MemPoolAccept::PolicyScriptChecks(const ATMPArgs& args, Workspace& ws) { + AssertLockHeld(cs_main); + AssertLockHeld(m_pool.cs); const CTransaction& tx = *ws.m_ptx; TxValidationState& state = ws.m_state; @@ -989,6 +997,8 @@ bool MemPoolAccept::PolicyScriptChecks(const ATMPArgs& args, Workspace& ws) bool MemPoolAccept::ConsensusScriptChecks(const ATMPArgs& args, Workspace& ws) { + AssertLockHeld(cs_main); + AssertLockHeld(m_pool.cs); const CTransaction& tx = *ws.m_ptx; const uint256& hash = ws.m_hash; TxValidationState& state = ws.m_state; @@ -1021,6 +1031,8 @@ bool MemPoolAccept::ConsensusScriptChecks(const ATMPArgs& args, Workspace& ws) bool MemPoolAccept::Finalize(const ATMPArgs& args, Workspace& ws) { + AssertLockHeld(cs_main); + AssertLockHeld(m_pool.cs); const CTransaction& tx = *ws.m_ptx; const uint256& hash = ws.m_hash; TxValidationState& state = ws.m_state; @@ -1342,8 +1354,9 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptPackage(const Package& package, MempoolAcceptResult AcceptToMemoryPool(CChainState& active_chainstate, const CTransactionRef& tx, int64_t accept_time, bool bypass_limits, bool test_accept) - EXCLUSIVE_LOCKS_REQUIRED(cs_main) + EXCLUSIVE_LOCKS_REQUIRED(::cs_main) { + AssertLockHeld(::cs_main); const CChainParams& chainparams{active_chainstate.m_params}; assert(active_chainstate.GetMempool() != nullptr); CTxMemPool& pool{*active_chainstate.GetMempool()}; @@ -1421,6 +1434,7 @@ CoinsViews::CoinsViews( void CoinsViews::InitCache() { + AssertLockHeld(::cs_main); m_cacheview = std::make_unique<CCoinsViewCache>(&m_catcherview); } @@ -1451,6 +1465,7 @@ void CChainState::InitCoinsDB( void CChainState::InitCoinsCache(size_t cache_size_bytes) { + AssertLockHeld(::cs_main); assert(m_coins_views != nullptr); m_coinstip_cache_size_bytes = cache_size_bytes; m_coins_views->InitCache(); @@ -1524,6 +1539,7 @@ void CChainState::CheckForkWarningConditions() // Called both upon regular invalid block discovery *and* InvalidateBlock void CChainState::InvalidChainFound(CBlockIndex* pindexNew) { + AssertLockHeld(cs_main); if (!m_chainman.m_best_invalid || pindexNew->nChainWork > m_chainman.m_best_invalid->nChainWork) { m_chainman.m_best_invalid = pindexNew; } @@ -1546,6 +1562,7 @@ void CChainState::InvalidChainFound(CBlockIndex* pindexNew) // which does its own setBlockIndexCandidates management. void CChainState::InvalidBlockFound(CBlockIndex* pindex, const BlockValidationState& state) { + AssertLockHeld(cs_main); if (state.GetResult() != BlockValidationResult::BLOCK_MUTATED) { pindex->nStatus |= BLOCK_FAILED_VALID; m_chainman.m_failed_blocks.insert(pindex); @@ -1787,8 +1804,9 @@ DisconnectResult CChainState::DisconnectBlock(const CBlock& block, const CBlockI error("DisconnectBlock(): transaction and undo data inconsistent"); return DISCONNECT_FAILED; } - for (unsigned int j = tx.vin.size(); j-- > 0;) { - const COutPoint &out = tx.vin[j].prevout; + for (unsigned int j = tx.vin.size(); j > 0;) { + --j; + const COutPoint& out = tx.vin[j].prevout; int res = ApplyTxInUndo(std::move(txundo.vprevout[j]), view, out); if (res == DISCONNECT_FAILED) return DISCONNECT_FAILED; fClean = fClean && res != DISCONNECT_UNCLEAN; @@ -1905,7 +1923,10 @@ bool CChainState::ConnectBlock(const CBlock& block, BlockValidationState& state, { AssertLockHeld(cs_main); assert(pindex); - assert(*pindex->phashBlock == block.GetHash()); + + uint256 block_hash{block.GetHash()}; + assert(*pindex->phashBlock == block_hash); + int64_t nTimeStart = GetTimeMicros(); // Check it again in case a previous version let a bad block in @@ -1939,7 +1960,7 @@ bool CChainState::ConnectBlock(const CBlock& block, BlockValidationState& state, // Special case for the genesis block, skipping connection of its transactions // (its coinbase is unspendable) - if (block.GetHash() == m_params.GetConsensus().hashGenesisBlock) { + if (block_hash == m_params.GetConsensus().hashGenesisBlock) { if (!fJustCheck) view.SetBestBlock(pindex->GetBlockHash()); return true; @@ -2196,12 +2217,12 @@ bool CChainState::ConnectBlock(const CBlock& block, BlockValidationState& state, LogPrint(BCLog::BENCH, " - Index writing: %.2fms [%.2fs (%.2fms/blk)]\n", MILLI * (nTime5 - nTime4), nTimeIndex * MICRO, nTimeIndex * MILLI / nBlocksTotal); TRACE6(validation, block_connected, - block.GetHash().data(), + block_hash.data(), pindex->nHeight, block.vtx.size(), nInputs, nSigOpsCost, - GetTimeMicros() - nTimeStart // in microseconds (µs) + nTime5 - nTimeStart // in microseconds (µs) ); return true; @@ -2209,6 +2230,7 @@ bool CChainState::ConnectBlock(const CBlock& block, BlockValidationState& state, CoinsCacheSizeState CChainState::GetCoinsCacheSizeState() { + AssertLockHeld(::cs_main); return this->GetCoinsCacheSizeState( m_coinstip_cache_size_bytes, gArgs.GetIntArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000); @@ -2218,6 +2240,7 @@ CoinsCacheSizeState CChainState::GetCoinsCacheSizeState( size_t max_coins_cache_size_bytes, size_t max_mempool_size_bytes) { + AssertLockHeld(::cs_main); const int64_t nMempoolUsage = m_mempool ? m_mempool->DynamicMemoryUsage() : 0; int64_t cacheSize = CoinsTip().DynamicMemoryUsage(); int64_t nTotalSpace = @@ -2426,6 +2449,7 @@ static void UpdateTipLog( void CChainState::UpdateTip(const CBlockIndex* pindexNew) { + AssertLockHeld(::cs_main); const auto& coins_tip = this->CoinsTip(); // The remainder of the function isn't relevant if we are not acting on @@ -2649,7 +2673,9 @@ bool CChainState::ConnectTip(BlockValidationState& state, CBlockIndex* pindexNew * Return the tip of the chain with the most work in it, that isn't * known to be invalid (it's however far from certain to be valid). */ -CBlockIndex* CChainState::FindMostWorkChain() { +CBlockIndex* CChainState::FindMostWorkChain() +{ + AssertLockHeld(::cs_main); do { CBlockIndex *pindexNew = nullptr; @@ -2853,7 +2879,7 @@ bool CChainState::ActivateBestChain(BlockValidationState& state, std::shared_ptr // far from a guarantee. Things in the P2P/RPC will often end up calling // us in the middle of ProcessNewBlock - do not assume pblock is set // sanely for performance or correctness! - AssertLockNotHeld(cs_main); + AssertLockNotHeld(::cs_main); // ABC maintains a fair degree of expensive-to-calculate internal state // because this function periodically releases cs_main so that it does not lock up other threads for too long @@ -2949,6 +2975,8 @@ bool CChainState::ActivateBestChain(BlockValidationState& state, std::shared_ptr bool CChainState::PreciousBlock(BlockValidationState& state, CBlockIndex* pindex) { + AssertLockNotHeld(m_chainstate_mutex); + AssertLockNotHeld(::cs_main); { LOCK(cs_main); if (pindex->nChainWork < m_chain.Tip()->nChainWork) { @@ -2979,6 +3007,7 @@ bool CChainState::PreciousBlock(BlockValidationState& state, CBlockIndex* pindex bool CChainState::InvalidateBlock(BlockValidationState& state, CBlockIndex* pindex) { AssertLockNotHeld(m_chainstate_mutex); + AssertLockNotHeld(::cs_main); // Genesis block can't be invalidated assert(pindex); @@ -3157,6 +3186,7 @@ void CChainState::ResetBlockFailureFlags(CBlockIndex *pindex) { /** Mark a block as having its data received and checked (up to BLOCK_VALID_TRANSACTIONS). */ void CChainState::ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pindexNew, const FlatFilePos& pos) { + AssertLockHeld(cs_main); pindexNew->nTx = block.vtx.size(); pindexNew->nChainTx = 0; pindexNew->nFile = pos.nFile; @@ -3329,8 +3359,9 @@ std::vector<unsigned char> GenerateCoinbaseCommitment(CBlock& block, const CBloc * in ConnectBlock(). * Note that -reindex-chainstate skips the validation that happens here! */ -static bool ContextualCheckBlockHeader(const CBlockHeader& block, BlockValidationState& state, BlockManager& blockman, const CChainParams& params, const CBlockIndex* pindexPrev, int64_t nAdjustedTime) EXCLUSIVE_LOCKS_REQUIRED(cs_main) +static bool ContextualCheckBlockHeader(const CBlockHeader& block, BlockValidationState& state, BlockManager& blockman, const CChainParams& params, const CBlockIndex* pindexPrev, int64_t nAdjustedTime) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) { + AssertLockHeld(::cs_main); assert(pindexPrev != nullptr); const int nHeight = pindexPrev->nHeight + 1; @@ -3701,6 +3732,7 @@ bool ChainstateManager::ProcessNewBlock(const CChainParams& chainparams, const s MempoolAcceptResult ChainstateManager::ProcessTransaction(const CTransactionRef& tx, bool test_accept) { + AssertLockHeld(cs_main); CChainState& active_chainstate = ActiveChainstate(); if (!active_chainstate.GetMempool()) { TxValidationState state; @@ -3914,6 +3946,7 @@ bool CVerifyDB::VerifyDB( /** Apply the effects of a block on the utxo cache, ignoring that it may already have been applied. */ bool CChainState::RollforwardBlock(const CBlockIndex* pindex, CCoinsViewCache& inputs) { + AssertLockHeld(cs_main); // TODO: merge with ConnectBlock CBlock block; if (!ReadBlockFromDisk(block, pindex, m_params.GetConsensus())) { @@ -4017,7 +4050,9 @@ bool CChainState::NeedsRedownload() const return false; } -void CChainState::UnloadBlockIndex() { +void CChainState::UnloadBlockIndex() +{ + AssertLockHeld(::cs_main); nBlockSequenceId = 1; setBlockIndexCandidates.clear(); } @@ -4089,6 +4124,7 @@ bool CChainState::LoadGenesisBlock() void CChainState::LoadExternalBlockFile(FILE* fileIn, FlatFilePos* dbp) { + AssertLockNotHeld(m_chainstate_mutex); // Map of disk positions for blocks with unknown parent (only used for reindex) static std::multimap<uint256, FlatFilePos> mapBlocksUnknownParent; int64_t nStart = GetTimeMillis(); @@ -4429,6 +4465,7 @@ void CChainState::CheckBlockIndex() std::string CChainState::ToString() { + AssertLockHeld(::cs_main); CBlockIndex* tip = m_chain.Tip(); return strprintf("Chainstate [%s] @ height %d (%s)", m_from_snapshot_blockhash ? "snapshot" : "ibd", @@ -4437,6 +4474,7 @@ std::string CChainState::ToString() bool CChainState::ResizeCoinsCaches(size_t coinstip_size, size_t coinsdb_size) { + AssertLockHeld(::cs_main); if (coinstip_size == m_coinstip_cache_size_bytes && coinsdb_size == m_coinsdb_cache_size_bytes) { // Cache sizes are unchanged, no need to continue. @@ -4493,7 +4531,8 @@ bool LoadMempool(CTxMemPool& pool, CChainState& active_chainstate, FopenFn mocka } uint64_t num; file >> num; - while (num--) { + while (num) { + --num; CTransactionRef tx; int64_t nTime; int64_t nFeeDelta; @@ -4660,6 +4699,7 @@ std::vector<CChainState*> ChainstateManager::GetAll() CChainState& ChainstateManager::InitializeChainstate( CTxMemPool* mempool, const std::optional<uint256>& snapshot_blockhash) { + AssertLockHeld(::cs_main); bool is_snapshot = snapshot_blockhash.has_value(); std::unique_ptr<CChainState>& to_modify = is_snapshot ? m_snapshot_chainstate : m_ibd_chainstate; @@ -4997,6 +5037,7 @@ bool ChainstateManager::IsSnapshotActive() const void ChainstateManager::Unload() { + AssertLockHeld(::cs_main); for (CChainState* chainstate : this->GetAll()) { chainstate->m_chain.SetTip(nullptr); chainstate->UnloadBlockIndex(); @@ -5018,6 +5059,7 @@ void ChainstateManager::Reset() void ChainstateManager::MaybeRebalanceCaches() { + AssertLockHeld(::cs_main); if (m_ibd_chainstate && !m_snapshot_chainstate) { LogPrintf("[snapshot] allocating all cache to the IBD chainstate\n"); // Allocate everything to the IBD chainstate. diff --git a/src/validation.h b/src/validation.h index fb258005f1..968f62aa9a 100644 --- a/src/validation.h +++ b/src/validation.h @@ -529,7 +529,9 @@ public: //! @returns whether or not the CoinsViews object has been fully initialized and we can //! safely flush this object to disk. - bool CanFlushToDisk() const EXCLUSIVE_LOCKS_REQUIRED(cs_main) { + bool CanFlushToDisk() const EXCLUSIVE_LOCKS_REQUIRED(::cs_main) + { + AssertLockHeld(::cs_main); return m_coins_views && m_coins_views->m_cacheview; } @@ -557,15 +559,17 @@ public: std::set<CBlockIndex*, node::CBlockIndexWorkComparator> setBlockIndexCandidates; //! @returns A reference to the in-memory cache of the UTXO set. - CCoinsViewCache& CoinsTip() EXCLUSIVE_LOCKS_REQUIRED(cs_main) + CCoinsViewCache& CoinsTip() EXCLUSIVE_LOCKS_REQUIRED(::cs_main) { + AssertLockHeld(::cs_main); assert(m_coins_views->m_cacheview); return *m_coins_views->m_cacheview.get(); } //! @returns A reference to the on-disk UTXO set database. - CCoinsViewDB& CoinsDB() EXCLUSIVE_LOCKS_REQUIRED(cs_main) + CCoinsViewDB& CoinsDB() EXCLUSIVE_LOCKS_REQUIRED(::cs_main) { + AssertLockHeld(::cs_main); return m_coins_views->m_dbview; } @@ -577,8 +581,9 @@ public: //! @returns A reference to a wrapped view of the in-memory UTXO set that //! handles disk read errors gracefully. - CCoinsViewErrorCatcher& CoinsErrorCatcher() EXCLUSIVE_LOCKS_REQUIRED(cs_main) + CCoinsViewErrorCatcher& CoinsErrorCatcher() EXCLUSIVE_LOCKS_REQUIRED(::cs_main) { + AssertLockHeld(::cs_main); return m_coins_views->m_catcherview; } @@ -597,7 +602,8 @@ public: EXCLUSIVE_LOCKS_REQUIRED(::cs_main); /** Import blocks from an external file */ - void LoadExternalBlockFile(FILE* fileIn, FlatFilePos* dbp = nullptr); + void LoadExternalBlockFile(FILE* fileIn, FlatFilePos* dbp = nullptr) + EXCLUSIVE_LOCKS_REQUIRED(!m_chainstate_mutex); /** * Update the on-disk chain state. @@ -639,7 +645,9 @@ public: */ bool ActivateBestChain( BlockValidationState& state, - std::shared_ptr<const CBlock> pblock = nullptr) LOCKS_EXCLUDED(m_chainstate_mutex, cs_main); + std::shared_ptr<const CBlock> pblock = nullptr) + EXCLUSIVE_LOCKS_REQUIRED(!m_chainstate_mutex) + LOCKS_EXCLUDED(::cs_main); bool AcceptBlock(const std::shared_ptr<const CBlock>& pblock, BlockValidationState& state, CBlockIndex** ppindex, bool fRequested, const FlatFilePos* dbp, bool* fNewBlock) EXCLUSIVE_LOCKS_REQUIRED(cs_main); @@ -657,9 +665,15 @@ public: * * May not be called in a validationinterface callback. */ - bool PreciousBlock(BlockValidationState& state, CBlockIndex* pindex) LOCKS_EXCLUDED(cs_main); + bool PreciousBlock(BlockValidationState& state, CBlockIndex* pindex) + EXCLUSIVE_LOCKS_REQUIRED(!m_chainstate_mutex) + LOCKS_EXCLUDED(::cs_main); + /** Mark a block as invalid. */ - bool InvalidateBlock(BlockValidationState& state, CBlockIndex* pindex) LOCKS_EXCLUDED(m_chainstate_mutex, cs_main); + bool InvalidateBlock(BlockValidationState& state, CBlockIndex* pindex) + EXCLUSIVE_LOCKS_REQUIRED(!m_chainstate_mutex) + LOCKS_EXCLUDED(::cs_main); + /** Remove invalidity status from a block and its descendants. */ void ResetBlockFailureFlags(CBlockIndex* pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main); @@ -915,6 +929,7 @@ public: node::BlockMap& BlockIndex() EXCLUSIVE_LOCKS_REQUIRED(::cs_main) { + AssertLockHeld(::cs_main); return m_blockman.m_block_index; } diff --git a/src/versionbits.cpp b/src/versionbits.cpp index 36815fba17..7a297c2bbb 100644 --- a/src/versionbits.cpp +++ b/src/versionbits.cpp @@ -107,7 +107,7 @@ BIP9Stats AbstractThresholdConditionChecker::GetStateStatisticsFor(const CBlockI if (pindex == nullptr) return stats; - // Find beginning of period + // Find how many blocks are in the current period int blocks_in_period = 1 + (pindex->nHeight % stats.period); // Reset signalling_blocks diff --git a/src/wallet/load.cpp b/src/wallet/load.cpp index 6a74f2eb84..633d8c5450 100644 --- a/src/wallet/load.cpp +++ b/src/wallet/load.cpp @@ -28,7 +28,7 @@ bool VerifyWallets(WalletContext& context) ArgsManager& args = *Assert(context.args); if (args.IsArgSet("-walletdir")) { - fs::path wallet_dir = fs::PathFromString(args.GetArg("-walletdir", "")); + const fs::path wallet_dir{args.GetPathArg("-walletdir")}; std::error_code error; // The canonical path cleans the path, preventing >1 Berkeley environment instances for the same directory // It also lets the fs::exists and fs::is_directory checks below pass on windows, since they return false diff --git a/src/wallet/rpc/wallet.cpp b/src/wallet/rpc/wallet.cpp index 33ec715b51..883a3c102b 100644 --- a/src/wallet/rpc/wallet.cpp +++ b/src/wallet/rpc/wallet.cpp @@ -57,6 +57,7 @@ static RPCHelpMan getwalletinfo() {RPCResult::Type::NUM, "progress", "scanning progress percentage [0.0, 1.0]"}, }}, {RPCResult::Type::BOOL, "descriptors", "whether this wallet uses descriptors for scriptPubKey management"}, + {RPCResult::Type::BOOL, "external_signer", "whether this wallet is configured to use an external signer such as a hardware wallet"}, }}, }, RPCExamples{ @@ -117,6 +118,7 @@ static RPCHelpMan getwalletinfo() obj.pushKV("scanning", false); } obj.pushKV("descriptors", pwallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)); + obj.pushKV("external_signer", pwallet->IsWalletFlagSet(WALLET_FLAG_EXTERNAL_SIGNER)); return obj; }, }; diff --git a/src/wallet/test/init_tests.cpp b/src/wallet/test/init_tests.cpp index c1cae5c5f6..7fdecc5642 100644 --- a/src/wallet/test/init_tests.cpp +++ b/src/wallet/test/init_tests.cpp @@ -18,7 +18,7 @@ BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_default) SetWalletDir(m_walletdir_path_cases["default"]); bool result = m_wallet_loader->verify(); BOOST_CHECK(result == true); - fs::path walletdir = fs::PathFromString(gArgs.GetArg("-walletdir", "")); + fs::path walletdir = gArgs.GetPathArg("-walletdir"); fs::path expected_path = fs::canonical(m_walletdir_path_cases["default"]); BOOST_CHECK_EQUAL(walletdir, expected_path); } @@ -28,7 +28,7 @@ BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_custom) SetWalletDir(m_walletdir_path_cases["custom"]); bool result = m_wallet_loader->verify(); BOOST_CHECK(result == true); - fs::path walletdir = fs::PathFromString(gArgs.GetArg("-walletdir", "")); + fs::path walletdir = gArgs.GetPathArg("-walletdir"); fs::path expected_path = fs::canonical(m_walletdir_path_cases["custom"]); BOOST_CHECK_EQUAL(walletdir, expected_path); } @@ -68,7 +68,7 @@ BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_no_trailing) SetWalletDir(m_walletdir_path_cases["trailing"]); bool result = m_wallet_loader->verify(); BOOST_CHECK(result == true); - fs::path walletdir = fs::PathFromString(gArgs.GetArg("-walletdir", "")); + fs::path walletdir = gArgs.GetPathArg("-walletdir"); fs::path expected_path = fs::canonical(m_walletdir_path_cases["default"]); BOOST_CHECK_EQUAL(walletdir, expected_path); } @@ -78,7 +78,7 @@ BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_no_trailing2) SetWalletDir(m_walletdir_path_cases["trailing2"]); bool result = m_wallet_loader->verify(); BOOST_CHECK(result == true); - fs::path walletdir = fs::PathFromString(gArgs.GetArg("-walletdir", "")); + fs::path walletdir = gArgs.GetPathArg("-walletdir"); fs::path expected_path = fs::canonical(m_walletdir_path_cases["default"]); BOOST_CHECK_EQUAL(walletdir, expected_path); } diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp index 8ef0d46c4f..7693c9c0e8 100644 --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -426,7 +426,7 @@ BOOST_AUTO_TEST_CASE(LoadReceiveRequests) // Test some watch-only LegacyScriptPubKeyMan methods by the procedure of loading (LoadWatchOnly), // checking (HaveWatchOnly), getting (GetWatchPubKey) and removing (RemoveWatchOnly) a -// given PubKey, resp. its corresponding P2PK Script. Results of the the impact on +// given PubKey, resp. its corresponding P2PK Script. Results of the impact on // the address -> PubKey map is dependent on whether the PubKey is a point on the curve static void TestWatchOnlyPubKey(LegacyScriptPubKeyMan* spk_man, const CPubKey& add_pubkey) { diff --git a/src/wallet/walletutil.cpp b/src/wallet/walletutil.cpp index ce276451c3..df1b10a634 100644 --- a/src/wallet/walletutil.cpp +++ b/src/wallet/walletutil.cpp @@ -13,7 +13,7 @@ fs::path GetWalletDir() fs::path path; if (gArgs.IsArgSet("-walletdir")) { - path = fs::PathFromString(gArgs.GetArg("-walletdir", "")); + path = gArgs.GetPathArg("-walletdir"); if (!fs::is_directory(path)) { // If the path specified doesn't exist, we return the deliberately // invalid empty string. diff --git a/test/functional/feature_dirsymlinks.py b/test/functional/feature_dirsymlinks.py new file mode 100755 index 0000000000..85c8e27600 --- /dev/null +++ b/test/functional/feature_dirsymlinks.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +# 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. +"""Test successful startup with symlinked directories. +""" + +import os +import sys + +from test_framework.test_framework import BitcoinTestFramework, SkipTest + + +def rename_and_link(*, from_name, to_name): + os.rename(from_name, to_name) + os.symlink(to_name, from_name) + assert os.path.islink(from_name) and os.path.isdir(from_name) + +class SymlinkTest(BitcoinTestFramework): + def skip_test_if_missing_module(self): + if sys.platform == 'win32': + raise SkipTest("Symlinks test skipped on Windows") + + def set_test_params(self): + self.num_nodes = 1 + + def run_test(self): + self.stop_node(0) + + rename_and_link(from_name=os.path.join(self.nodes[0].datadir, self.chain, "blocks"), + to_name=os.path.join(self.nodes[0].datadir, self.chain, "newblocks")) + rename_and_link(from_name=os.path.join(self.nodes[0].datadir, self.chain, "chainstate"), + to_name=os.path.join(self.nodes[0].datadir, self.chain, "newchainstate")) + + self.start_node(0) + + +if __name__ == '__main__': + SymlinkTest().main() diff --git a/test/functional/feature_init.py b/test/functional/feature_init.py index dbd71a8b2d..d0cb1e10e2 100755 --- a/test/functional/feature_init.py +++ b/test/functional/feature_init.py @@ -64,6 +64,8 @@ class InitStressTest(BitcoinTestFramework): 'addcon thread start', 'loadblk thread start', 'txindex thread start', + 'block filter index thread start', + 'coinstatsindex thread start', 'msghand thread start', 'net thread start', 'addcon thread start', @@ -74,7 +76,7 @@ class InitStressTest(BitcoinTestFramework): for terminate_line in lines_to_terminate_after: self.log.info(f"Starting node and will exit after line '{terminate_line}'") with node.wait_for_debug_log([terminate_line], ignore_case=True): - node.start(extra_args=['-txindex=1']) + node.start(extra_args=['-txindex=1', '-blockfilterindex=1', '-coinstatsindex=1']) self.log.debug("Terminating node after terminate line was found") sigterm_node() @@ -109,7 +111,7 @@ class InitStressTest(BitcoinTestFramework): # investigate doing this later. node.assert_start_raises_init_error( - extra_args=['-txindex=1'], + extra_args=['-txindex=1', '-blockfilterindex=1', '-coinstatsindex=1'], expected_msg=err_fragment, match=ErrorMatch.PARTIAL_REGEX, ) diff --git a/test/functional/feature_syscall_sandbox.py b/test/functional/feature_syscall_sandbox.py index caf7f1e7fc..e430542845 100755 --- a/test/functional/feature_syscall_sandbox.py +++ b/test/functional/feature_syscall_sandbox.py @@ -14,7 +14,7 @@ class SyscallSandboxTest(BitcoinTestFramework): def skip_test_if_missing_module(self): if not self.is_syscall_sandbox_compiled(): raise SkipTest("bitcoind has not been built with syscall sandbox enabled.") - if self.options.nosandbox: + if self.disable_syscall_sandbox: raise SkipTest("--nosandbox passed to test runner.") def run_test(self): diff --git a/test/functional/test_framework/address.py b/test/functional/test_framework/address.py index 013522a5e1..c7fbf679b6 100644 --- a/test/functional/test_framework/address.py +++ b/test/functional/test_framework/address.py @@ -55,17 +55,15 @@ def create_deterministic_address_bcrt1_p2tr_op_true(): def byte_to_base58(b, version): result = '' - str = b.hex() - str = chr(version).encode('latin-1').hex() + str - checksum = hash256(bytes.fromhex(str)).hex() - str += checksum[:8] - value = int('0x' + str, 0) + b = bytes([version]) + b # prepend version + b += hash256(b)[:4] # append checksum + value = int.from_bytes(b, 'big') while value > 0: result = chars[value % 58] + result value //= 58 - while (str[:2] == '00'): + while b[0] == 0: result = chars[0] + result - str = str[2:] + b = b[1:] return result diff --git a/test/functional/test_framework/netutil.py b/test/functional/test_framework/netutil.py index 174dc44a2a..b64f66e69b 100644 --- a/test/functional/test_framework/netutil.py +++ b/test/functional/test_framework/netutil.py @@ -144,7 +144,6 @@ def test_ipv6_local(): ''' Check for (local) IPv6 support. ''' - import socket # By using SOCK_DGRAM this will not actually make a connection, but it will # fail if there is no route to IPv6 localhost. have_ipv6 = True diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py index dabde13bf1..210025104e 100644 --- a/test/functional/test_framework/util.py +++ b/test/functional/test_framework/util.py @@ -36,6 +36,7 @@ def assert_approx(v, vexp, vspan=0.00001): def assert_fee_amount(fee, tx_size, feerate_BTC_kvB): """Assert the fee is in range.""" + assert isinstance(tx_size, int) target_fee = get_fee(tx_size, feerate_BTC_kvB) if fee < target_fee: raise AssertionError("Fee of %s BTC too low! (Should be %s BTC)" % (str(fee), str(target_fee))) @@ -219,7 +220,13 @@ def str_to_b64str(string): def ceildiv(a, b): - """Divide 2 ints and round up to next int rather than round down""" + """ + Divide 2 ints and round up to next int rather than round down + Implementation requires python integers, which have a // operator that does floor division. + Other types like decimal.Decimal whose // operator truncates towards 0 will not work. + """ + assert isinstance(a, int) + assert isinstance(b, int) return -(-a // b) @@ -227,7 +234,7 @@ def get_fee(tx_size, feerate_btc_kvb): """Calculate the fee in BTC given a feerate is BTC/kvB. Reflects CFeeRate::GetFee""" feerate_sat_kvb = int(feerate_btc_kvb * Decimal(1e8)) # Fee in sat/kvb as an int to avoid float precision errors target_fee_sat = ceildiv(feerate_sat_kvb * tx_size, 1000) # Round calculated fee up to nearest sat - return satoshi_round(target_fee_sat / Decimal(1e8)) # Truncate BTC result to nearest sat + return target_fee_sat / Decimal(1e8) # Return result in BTC def satoshi_round(amount): diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index e833128063..516e8be638 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -321,6 +321,7 @@ BASE_SCRIPTS = [ 'rpc_getdescriptorinfo.py', 'rpc_mempool_entry_fee_fields_deprecation.py', 'rpc_help.py', + 'feature_dirsymlinks.py', 'feature_help.py', 'feature_shutdown.py', 'p2p_ibd_txrelay.py', @@ -532,8 +533,11 @@ def run_tests(*, test_list, src_dir, build_dir, tmpdir, jobs=1, enable_coverage= max_len_name = len(max(test_list, key=len)) test_count = len(test_list) + all_passed = True i = 0 while i < test_count: + if failfast and not all_passed: + break for test_result, testdir, stdout, stderr in job_queue.get_next(): test_results.append(test_result) i += 1 @@ -543,6 +547,7 @@ def run_tests(*, test_list, src_dir, build_dir, tmpdir, jobs=1, enable_coverage= elif test_result.status == "Skipped": logging.debug("%s skipped" % (done_str)) else: + all_passed = False print("%s failed, Duration: %s s\n" % (done_str, test_result.time)) print(BOLD[1] + 'stdout:\n' + BOLD[0] + stdout + '\n') print(BOLD[1] + 'stderr:\n' + BOLD[0] + stderr + '\n') @@ -576,7 +581,7 @@ def run_tests(*, test_list, src_dir, build_dir, tmpdir, jobs=1, enable_coverage= if not os.listdir(tmpdir): os.rmdir(tmpdir) - all_passed = all(map(lambda test_result: test_result.was_successful, test_results)) and coverage_passed + all_passed = all_passed and coverage_passed # Clean up dangling processes if any. This may only happen with --failfast option. # Killing the process group will also terminate the current process but that is diff --git a/test/functional/wallet_send.py b/test/functional/wallet_send.py index 843a9f52b7..86e36be8f7 100755 --- a/test/functional/wallet_send.py +++ b/test/functional/wallet_send.py @@ -16,6 +16,7 @@ from test_framework.util import ( assert_fee_amount, assert_greater_than, assert_raises_rpc_error, + count_bytes, ) from test_framework.wallet_util import bytes_to_wif @@ -320,20 +321,20 @@ class WalletSendTest(BitcoinTestFramework): res = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, fee_rate=7, add_to_wallet=False) fee = self.nodes[1].decodepsbt(res["psbt"])["fee"] - assert_fee_amount(fee, Decimal(len(res["hex"]) / 2), Decimal("0.00007")) + assert_fee_amount(fee, count_bytes(res["hex"]), Decimal("0.00007")) # "unset" and None are treated the same for estimate_mode res = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, fee_rate=2, estimate_mode="unset", add_to_wallet=False) fee = self.nodes[1].decodepsbt(res["psbt"])["fee"] - assert_fee_amount(fee, Decimal(len(res["hex"]) / 2), Decimal("0.00002")) + assert_fee_amount(fee, count_bytes(res["hex"]), Decimal("0.00002")) res = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, arg_fee_rate=4.531, add_to_wallet=False) fee = self.nodes[1].decodepsbt(res["psbt"])["fee"] - assert_fee_amount(fee, Decimal(len(res["hex"]) / 2), Decimal("0.00004531")) + assert_fee_amount(fee, count_bytes(res["hex"]), Decimal("0.00004531")) res = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, arg_fee_rate=3, add_to_wallet=False) fee = self.nodes[1].decodepsbt(res["psbt"])["fee"] - assert_fee_amount(fee, Decimal(len(res["hex"]) / 2), Decimal("0.00003")) + assert_fee_amount(fee, count_bytes(res["hex"]), Decimal("0.00003")) # Test that passing fee_rate as both an argument and an option raises. self.test_send(from_wallet=w0, to_wallet=w1, amount=1, arg_fee_rate=1, fee_rate=1, add_to_wallet=False, diff --git a/test/functional/wallet_signer.py b/test/functional/wallet_signer.py index 9e2db517b6..423cfecdc0 100755 --- a/test/functional/wallet_signer.py +++ b/test/functional/wallet_signer.py @@ -72,10 +72,12 @@ class WalletSignerTest(BitcoinTestFramework): self.nodes[1].createwallet(wallet_name='hww', disable_private_keys=True, descriptors=True, external_signer=True) hww = self.nodes[1].get_wallet_rpc('hww') + assert_equal(hww.getwalletinfo()["external_signer"], True) # Flag can't be set afterwards (could be added later for non-blank descriptor based watch-only wallets) self.nodes[1].createwallet(wallet_name='not_hww', disable_private_keys=True, descriptors=True, external_signer=False) not_hww = self.nodes[1].get_wallet_rpc('not_hww') + assert_equal(not_hww.getwalletinfo()["external_signer"], False) assert_raises_rpc_error(-8, "Wallet flag is immutable: external_signer", not_hww.setwalletflag, "external_signer", True) # assert_raises_rpc_error(-4, "Multiple signers found, please specify which to use", wallet_name='not_hww', disable_private_keys=True, descriptors=True, external_signer=True) diff --git a/test/lint/lint-includes.sh b/test/lint/lint-includes.sh index ba80c8edfa..9e72831ee9 100755 --- a/test/lint/lint-includes.sh +++ b/test/lint/lint-includes.sh @@ -62,6 +62,7 @@ EXPECTED_BOOST_INCLUDES=( boost/signals2/connection.hpp boost/signals2/optional_last_value.hpp boost/signals2/signal.hpp + boost/test/included/unit_test.hpp boost/test/unit_test.hpp ) diff --git a/test/sanitizer_suppressions/tsan b/test/sanitizer_suppressions/tsan index 3c5a15a0c7..ed8c75d617 100644 --- a/test/sanitizer_suppressions/tsan +++ b/test/sanitizer_suppressions/tsan @@ -30,6 +30,9 @@ race:validation_chainstatemanager_tests deadlock:libdb race:libzmq +# Race in headers only Boost Test +race:std::__1::ios_base::flags + # Intermittent issues # ------------------- # diff --git a/test/sanitizer_suppressions/ubsan b/test/sanitizer_suppressions/ubsan index ec13acb689..bdaee5d191 100644 --- a/test/sanitizer_suppressions/ubsan +++ b/test/sanitizer_suppressions/ubsan @@ -43,12 +43,10 @@ shift-base:test/fuzz/crypto_diff_fuzz_chacha20.cpp # contains files in which we expect unsigned integer overflows to occur. The # list is used to suppress -fsanitize=integer warnings when running our CI UBSan # job. -unsigned-integer-overflow:addrman.cpp unsigned-integer-overflow:arith_uint256.h unsigned-integer-overflow:common/bloom.cpp unsigned-integer-overflow:coins.cpp unsigned-integer-overflow:compressor.cpp -unsigned-integer-overflow:core_write.cpp unsigned-integer-overflow:crypto/ unsigned-integer-overflow:hash.cpp unsigned-integer-overflow:policy/fees.cpp @@ -57,10 +55,7 @@ unsigned-integer-overflow:pubkey.h unsigned-integer-overflow:script/interpreter.cpp unsigned-integer-overflow:txmempool.cpp unsigned-integer-overflow:util/strencodings.cpp -unsigned-integer-overflow:validation.cpp -implicit-integer-sign-change:addrman.h implicit-integer-sign-change:bech32.cpp -implicit-integer-sign-change:coins.h implicit-integer-sign-change:compat/stdin.cpp implicit-integer-sign-change:compressor.h implicit-integer-sign-change:crypto/ @@ -72,7 +67,6 @@ implicit-integer-sign-change:script/interpreter.cpp implicit-integer-sign-change:serialize.h implicit-integer-sign-change:txmempool.cpp implicit-signed-integer-truncation:addrman.cpp -implicit-signed-integer-truncation:addrman.h implicit-signed-integer-truncation:crypto/ implicit-unsigned-integer-truncation:crypto/ shift-base:arith_uint256.cpp |