diff options
283 files changed, 3069 insertions, 3987 deletions
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index bf094e8325..fb91208954 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,6 +1,6 @@ --- name: Bug report -about: Create a report to help us improve +about: Create a report to help us improve (use this for suspected bugs only, if not sure, open a regular issue below) title: '' labels: Bug assignees: '' diff --git a/.travis.yml b/.travis.yml index f59c7fc7e8..3ddafda6d2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -34,6 +34,11 @@ cache: - $TRAVIS_BUILD_DIR/depends/built - $TRAVIS_BUILD_DIR/depends/sdk-sources - $TRAVIS_BUILD_DIR/ci/scratch/.ccache + # macOS + - $HOME/Library/Caches/Homebrew + - /usr/local/Homebrew +before_cache: + - if [ "${TRAVIS_OS_NAME}" = "osx" ]; then brew cleanup; fi stages: - lint - test @@ -88,28 +93,6 @@ jobs: script: - set -o errexit; source ./ci/extended_lint/06_script.sh - - stage: extended-lint - name: 'lint macOS 10.12 (compat)' - os: osx - # Use the earliest macOS that can build our lint dependencies: - # Xcode 8.3.3, macOS 10.12, JDK 1.8.0_112-b16 - # https://docs.travis-ci.com/user/reference/osx/#OS-X-Version - osx_image: xcode8.3 - # TODO: if you're updating osx_image, try using "rvm:" to supply the - # version of ruby required by homebrew. Despite this "rvm:" declaration, - # brew update installs ruby 2.3.7 as its first action. - language: ruby - rvm: - - 2.3.7 - env: - cache: false - install: - - set -o errexit; source ./ci/lint/04_install.sh - before_script: - - set -o errexit; source ./ci/lint/05_before_script.sh - script: - - set -o errexit; source ./ci/lint/06_script.sh - - stage: test name: 'ARM [GOAL: install] [unit tests, no functional tests]' env: >- @@ -121,7 +104,7 @@ jobs: FILE_ENV="./ci/test/00_setup_env_win64.sh" - stage: test - name: '32-bit + dash [GOAL: install] [GUI: BIP70 enabled]' + name: '32-bit + dash [GOAL: install] [gui]' env: >- FILE_ENV="./ci/test/00_setup_env_i686.sh" @@ -160,3 +143,13 @@ jobs: name: 'macOS 10.10 [GOAL: deploy] [no functional tests]' env: >- FILE_ENV="./ci/test/00_setup_env_mac.sh" + + - stage: test + name: 'macOS 10.14 native [GOAL: install] [GUI] [no depends]' + os: osx + # Use the most recent version: + # Xcode 11, macOS 10.14, JDK 12.0.1 + # https://docs.travis-ci.com/user/reference/osx/#macos-version + osx_image: xcode11 + env: >- + FILE_ENV="./ci/test/00_setup_env_mac_host.sh" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1f4a2c081e..ecb5704a8f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -46,7 +46,7 @@ facilitates social contribution, easy testing and peer review. To contribute a patch, the workflow is as follows: - 1. Fork repository + 1. Fork repository ([only the first time](https://help.github.com/en/articles/fork-a-repo)). 1. Create topic branch 1. Commit patches diff --git a/Makefile.am b/Makefile.am index 49a20b7614..deae2c1b57 100644 --- a/Makefile.am +++ b/Makefile.am @@ -43,13 +43,19 @@ OSX_INSTALLER_ICONS=$(top_srcdir)/src/qt/res/icons/bitcoin.icns OSX_PLIST=$(top_builddir)/share/qt/Info.plist #not installed OSX_QT_TRANSLATIONS = da,de,es,hu,ru,uk,zh_CN,zh_TW -DIST_DOCS = $(wildcard doc/*.md) $(wildcard doc/release-notes/*.md) +DIST_DOCS = \ + README.md \ + $(wildcard doc/*.md) \ + $(wildcard doc/release-notes/*.md) DIST_CONTRIB = $(top_srcdir)/contrib/bitcoin-cli.bash-completion \ $(top_srcdir)/contrib/bitcoin-tx.bash-completion \ $(top_srcdir)/contrib/bitcoind.bash-completion \ $(top_srcdir)/contrib/debian/copyright \ $(top_srcdir)/contrib/init \ - $(top_srcdir)/contrib/install_db4.sh + $(top_srcdir)/contrib/install_db4.sh \ + $(top_srcdir)/contrib/linearize/linearize-data.py \ + $(top_srcdir)/contrib/linearize/linearize-hashes.py + DIST_SHARE = \ $(top_srcdir)/share/genbuild.sh \ $(top_srcdir)/share/rpcauth diff --git a/build_msvc/bitcoin_config.h b/build_msvc/bitcoin_config.h index 2fe489239d..e892765fde 100644 --- a/build_msvc/bitcoin_config.h +++ b/build_msvc/bitcoin_config.h @@ -98,10 +98,6 @@ */ #define HAVE_DECL_DAEMON 0 -/* Define to 1 if you have the declaration of `EVP_MD_CTX_new', and to 0 if - you don't. */ -//#define HAVE_DECL_EVP_MD_CTX_NEW 1 - /* Define to 1 if you have the declaration of `htobe16', and to 0 if you don't. */ #define HAVE_DECL_HTOBE16 0 diff --git a/build_msvc/test_bitcoin/test_bitcoin.vcxproj b/build_msvc/test_bitcoin/test_bitcoin.vcxproj index 47e87b59e4..703f616f8e 100644 --- a/build_msvc/test_bitcoin/test_bitcoin.vcxproj +++ b/build_msvc/test_bitcoin/test_bitcoin.vcxproj @@ -13,6 +13,7 @@ <ClCompile Include="..\..\src\test\*_properties.cpp" /> <ClCompile Include="..\..\src\test\gen\*_gen.cpp" /> <ClCompile Include="..\..\src\wallet\test\*_tests.cpp" /> + <ClCompile Include="..\..\src\test\lib\*.cpp" /> <ClCompile Include="..\..\src\test\setup_common.cpp" /> <ClCompile Include="..\..\src\test\main.cpp" /> <ClCompile Include="..\..\src\wallet\test\*_fixture.cpp" /> diff --git a/ci/lint/04_install.sh b/ci/lint/04_install.sh index 9f7e1b310d..12c3bfce45 100755 --- a/ci/lint/04_install.sh +++ b/ci/lint/04_install.sh @@ -6,22 +6,9 @@ export LC_ALL=C -if [ "$TRAVIS_OS_NAME" == "osx" ]; then - # update first to install required ruby dependency - travis_retry brew update - travis_retry brew reinstall git -- --with-pcre2 # for --perl-regexp - travis_retry brew install grep # gnu grep for --perl-regexp support - PATH="$(brew --prefix grep)/libexec/gnubin:$PATH" - travis_retry brew install shellcheck - travis_retry brew upgrade python - PATH="$(brew --prefix python)/bin:$PATH" - export PATH -else - SHELLCHECK_VERSION=v0.6.0 - travis_retry curl --silent "https://storage.googleapis.com/shellcheck/shellcheck-${SHELLCHECK_VERSION}.linux.x86_64.tar.xz" | tar --xz -xf - --directory /tmp/ - PATH="/tmp/shellcheck-${SHELLCHECK_VERSION}:${PATH}" - export PATH -fi - travis_retry pip3 install codespell==1.15.0 travis_retry pip3 install flake8==3.7.8 + +SHELLCHECK_VERSION=v0.6.0 +curl -s "https://storage.googleapis.com/shellcheck/shellcheck-${SHELLCHECK_VERSION}.linux.x86_64.tar.xz" | tar --xz -xf - --directory /tmp/ +export PATH="/tmp/shellcheck-${SHELLCHECK_VERSION}:${PATH}" diff --git a/ci/test/00_setup_env_i686.sh b/ci/test/00_setup_env_i686.sh index 63068dc95d..6df65dd4a0 100644 --- a/ci/test/00_setup_env_i686.sh +++ b/ci/test/00_setup_env_i686.sh @@ -7,8 +7,7 @@ export LC_ALL=C.UTF-8 export HOST=i686-pc-linux-gnu -export DEP_OPTS="PROTOBUF=1" export PACKAGES="g++-multilib python3-zmq" export GOAL="install" -export BITCOIN_CONFIG="--enable-zmq --with-gui=qt5 --enable-bip70 --enable-glibc-back-compat --enable-reduce-exports LDFLAGS=-static-libstdc++" +export BITCOIN_CONFIG="--enable-zmq --with-gui=qt5 --enable-glibc-back-compat --enable-reduce-exports LDFLAGS=-static-libstdc++" export CONFIG_SHELL="/bin/dash" diff --git a/ci/test/00_setup_env_mac_host.sh b/ci/test/00_setup_env_mac_host.sh new file mode 100644 index 0000000000..aa68a5700e --- /dev/null +++ b/ci/test/00_setup_env_mac_host.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash +# +# Copyright (c) 2019 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +export LC_ALL=C.UTF-8 + +export HOST=x86_64-apple-darwin14 +export BREW_PACKAGES="automake berkeley-db4 libtool boost miniupnpc pkg-config qt qrencode python3 ccache zeromq" +export PIP_PACKAGES="zmq" +export RUN_CI_ON_HOST=true +export RUN_UNIT_TESTS=true +export RUN_FUNCTIONAL_TESTS=false +export GOAL="install" +export BITCOIN_CONFIG="--enable-gui --enable-reduce-exports --enable-werror" +# Run without depends +export NO_DEPENDS=1 +export OSX_SDK="" diff --git a/ci/test/04_install.sh b/ci/test/04_install.sh index 409e87ce04..d0831a4c13 100755 --- a/ci/test/04_install.sh +++ b/ci/test/04_install.sh @@ -6,6 +6,32 @@ export LC_ALL=C.UTF-8 +if [ "$TRAVIS_OS_NAME" == "osx" ]; then + set +o errexit + pushd /usr/local/Homebrew || exit 1 + git reset --hard origin/master + popd || exit 1 + set -o errexit + ${CI_RETRY_EXE} brew update + # brew upgrade returns an error if any of the packages is already up to date + # Failure is safe to ignore, unless we really need an update. + brew upgrade $BREW_PACKAGES || true + + # install new packages (brew install returns an error if already installed) + for i in $BREW_PACKAGES; do + if ! brew list | grep -q $i; then + ${CI_RETRY_EXE} brew install $i + fi + done + + export PATH="/usr/local/opt/ccache/libexec:$PATH" + OPENSSL_PKG_CONFIG_PATH="/usr/local/opt/openssl@1.1/lib/pkgconfig" + export PKG_CONFIG_PATH=$OPENSSL_PKG_CONFIG_PATH:$PKG_CONFIG_PATH + + ${CI_RETRY_EXE} pip3 install $PIP_PACKAGES + +fi + mkdir -p "${BASE_SCRATCH_DIR}" ccache echo "Creating ccache dir if it didn't already exist" @@ -15,7 +41,7 @@ fi export DIR_FUZZ_IN=${DIR_QA_ASSETS}/fuzz_seed_corpus/ mkdir -p "${BASE_BUILD_DIR}/sanitizer-output/" -export ASAN_OPTIONS="" +export ASAN_OPTIONS="detect_stack_use_after_return=1" export LSAN_OPTIONS="suppressions=${BASE_BUILD_DIR}/test/sanitizer_suppressions/lsan" export TSAN_OPTIONS="suppressions=${BASE_BUILD_DIR}/test/sanitizer_suppressions/tsan:log_path=${BASE_BUILD_DIR}/sanitizer-output/tsan" export UBSAN_OPTIONS="suppressions=${BASE_BUILD_DIR}/test/sanitizer_suppressions/ubsan:print_stacktrace=1:halt_on_error=1" @@ -42,11 +68,19 @@ else } fi -DOCKER_EXEC free -m -h -DOCKER_EXEC echo "Number of CPUs \(nproc\):" \$\(nproc\) +if [ "$TRAVIS_OS_NAME" == "osx" ]; then + top -l 1 -s 0 | awk ' /PhysMem/ {print}' + echo "Number of CPUs: $(sysctl -n hw.logicalcpu)" +else + DOCKER_EXEC free -m -h + DOCKER_EXEC echo "Number of CPUs \(nproc\):" \$\(nproc\) +fi -${CI_RETRY_EXE} DOCKER_EXEC apt-get update -${CI_RETRY_EXE} DOCKER_EXEC apt-get install --no-install-recommends --no-upgrade -y $PACKAGES $DOCKER_PACKAGES + +if [ "$TRAVIS_OS_NAME" != "osx" ]; then + ${CI_RETRY_EXE} DOCKER_EXEC apt-get update + ${CI_RETRY_EXE} DOCKER_EXEC apt-get install --no-install-recommends --no-upgrade -y $PACKAGES $DOCKER_PACKAGES +fi if [ "$USE_BUSY_BOX" = "true" ]; then echo "Setup to use BusyBox utils" diff --git a/ci/test/05_before_script.sh b/ci/test/05_before_script.sh index 516d3fc042..a0488f0807 100755 --- a/ci/test/05_before_script.sh +++ b/ci/test/05_before_script.sh @@ -6,7 +6,12 @@ export LC_ALL=C.UTF-8 -DOCKER_EXEC echo \> \$HOME/.bitcoin # Make sure default datadir does not exist and is never read by creating a dummy file +# Make sure default datadir does not exist and is never read by creating a dummy file +if [ "$TRAVIS_OS_NAME" == "osx" ]; then + echo > $HOME/Library/Application\ Support/Bitcoin +else + DOCKER_EXEC echo \> \$HOME/.bitcoin +fi mkdir -p depends/SDKs depends/sdk-sources diff --git a/ci/test/06_script_a.sh b/ci/test/06_script_a.sh index eb6ade7919..c4dc22bdd8 100755 --- a/ci/test/06_script_a.sh +++ b/ci/test/06_script_a.sh @@ -20,7 +20,11 @@ fi END_FOLD mkdir -p build + +# Temporarily disable errexit, because Travis macOS fails without error message +set +o errexit cd build || (echo "could not enter build directory"; exit 1) +set -o errexit BEGIN_FOLD configure DOCKER_EXEC ../configure --cache-file=config.cache $BITCOIN_CONFIG_ALL $BITCOIN_CONFIG || ( cat config.log && false) @@ -30,7 +34,9 @@ BEGIN_FOLD distdir DOCKER_EXEC make distdir VERSION=$HOST END_FOLD +set +o errexit cd "bitcoin-$HOST" || (echo "could not enter distdir bitcoin-$HOST"; exit 1) +set -o errexit BEGIN_FOLD configure DOCKER_EXEC ./configure --cache-file=../config.cache $BITCOIN_CONFIG_ALL $BITCOIN_CONFIG || ( cat config.log && false) @@ -43,4 +49,6 @@ BEGIN_FOLD build DOCKER_EXEC make $MAKEJOBS $GOAL || ( echo "Build failure. Verbose build follows." && DOCKER_EXEC make $GOAL V=1 ; false ) END_FOLD +set +o errexit cd ${BASE_BUILD_DIR} || (echo "could not enter travis build dir $BASE_BUILD_DIR"; exit 1) +set -o errexit diff --git a/ci/test/06_script_b.sh b/ci/test/06_script_b.sh index 1a5217277a..048fe06c84 100755 --- a/ci/test/06_script_b.sh +++ b/ci/test/06_script_b.sh @@ -6,7 +6,10 @@ export LC_ALL=C.UTF-8 +# Temporarily disable errexit, because Travis macOS fails without error message +set +o errexit cd "build/bitcoin-$HOST" || (echo "could not enter distdir build/bitcoin-$HOST"; exit 1) +set -o errexit if [ -n "$QEMU_USER_CMD" ]; then BEGIN_FOLD wrap-qemu @@ -46,4 +49,6 @@ if [ "$RUN_FUZZ_TESTS" = "true" ]; then END_FOLD fi +set +o errexit cd ${BASE_BUILD_DIR} || (echo "could not enter travis build dir $BASE_BUILD_DIR"; exit 1) +set -o errexit diff --git a/configure.ac b/configure.ac index d25e0f4496..9f2942dc9f 100644 --- a/configure.ac +++ b/configure.ac @@ -226,13 +226,16 @@ AC_ARG_ENABLE([zmq], [disable ZMQ notifications])], [use_zmq=$enableval], [use_zmq=yes]) + AC_ARG_ENABLE([bip70], [AS_HELP_STRING([--enable-bip70], - [enable BIP70 (payment protocol) support in the GUI (default is to disable)])], + [BIP70 (payment protocol) support in the GUI (no longer supported)])], [enable_bip70=$enableval], [enable_bip70=no]) -AC_ARG_WITH([protoc-bindir],[AS_HELP_STRING([--with-protoc-bindir=BIN_DIR],[specify protoc bin path])], [protoc_bin_path=$withval], []) +if test x$enable_bip70 != xno; then + AC_MSG_ERROR([BIP70 is no longer supported!]) +fi AC_ARG_ENABLE(man, [AS_HELP_STRING([--disable-man], @@ -753,12 +756,17 @@ if test x$use_hardening != xno; then AX_CHECK_COMPILE_FLAG([-Wstack-protector],[HARDENED_CXXFLAGS="$HARDENED_CXXFLAGS -Wstack-protector"]) AX_CHECK_COMPILE_FLAG([-fstack-protector-all],[HARDENED_CXXFLAGS="$HARDENED_CXXFLAGS -fstack-protector-all"]) - AX_CHECK_PREPROC_FLAG([-D_FORTIFY_SOURCE=2],[ - AX_CHECK_PREPROC_FLAG([-U_FORTIFY_SOURCE],[ - HARDENED_CPPFLAGS="$HARDENED_CPPFLAGS -U_FORTIFY_SOURCE" + # When enable_debug is yes, all optimizations are disabled. + # However, FORTIFY_SOURCE requires that there is some level of optimization, otherwise it does nothing and just creates a compiler warning. + # Since FORTIFY_SOURCE is a no-op without optimizations, do not enable it when enable_debug is yes. + if test x$enable_debug != xyes; then + AX_CHECK_PREPROC_FLAG([-D_FORTIFY_SOURCE=2],[ + AX_CHECK_PREPROC_FLAG([-U_FORTIFY_SOURCE],[ + HARDENED_CPPFLAGS="$HARDENED_CPPFLAGS -U_FORTIFY_SOURCE" + ]) + HARDENED_CPPFLAGS="$HARDENED_CPPFLAGS -D_FORTIFY_SOURCE=2" ]) - HARDENED_CPPFLAGS="$HARDENED_CPPFLAGS -D_FORTIFY_SOURCE=2" - ]) + fi AX_CHECK_LINK_FLAG([[-Wl,--dynamicbase]], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,--dynamicbase"]) AX_CHECK_LINK_FLAG([[-Wl,--nxcompat]], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,--nxcompat"]) @@ -1232,11 +1240,7 @@ if test x$use_pkgconfig = xyes; then m4_ifdef( [PKG_CHECK_MODULES], [ - PKG_CHECK_MODULES([SSL], [libssl],, [AC_MSG_ERROR(openssl not found.)]) PKG_CHECK_MODULES([CRYPTO], [libcrypto],,[AC_MSG_ERROR(libcrypto not found.)]) - if test x$enable_bip70 != xno; then - BITCOIN_QT_CHECK([PKG_CHECK_MODULES([PROTOBUF], [protobuf], [have_protobuf=yes], [have_protobuf=no])]) - fi if test x$use_qr != xno; then BITCOIN_QT_CHECK([PKG_CHECK_MODULES([QR], [libqrencode], [have_qrencode=yes], [have_qrencode=no])]) fi @@ -1262,9 +1266,6 @@ else AC_CHECK_HEADER([openssl/crypto.h],,AC_MSG_ERROR(libcrypto headers missing)) AC_CHECK_LIB([crypto], [main],CRYPTO_LIBS=-lcrypto, AC_MSG_ERROR(libcrypto missing)) - AC_CHECK_HEADER([openssl/ssl.h],, AC_MSG_ERROR(libssl headers missing),) - AC_CHECK_LIB([ssl], [main],SSL_LIBS=-lssl, AC_MSG_ERROR(libssl missing)) - if test x$build_bitcoin_cli$build_bitcoind$bitcoin_enable_qt$use_tests != xnononono; then AC_CHECK_HEADER([event2/event.h],, AC_MSG_ERROR(libevent headers missing),) AC_CHECK_LIB([event],[main],EVENT_LIBS=-levent,AC_MSG_ERROR(libevent missing)) @@ -1296,22 +1297,12 @@ else esac fi - if test x$enable_bip70 != xno; then - BITCOIN_QT_CHECK(AC_CHECK_LIB([protobuf] ,[main],[PROTOBUF_LIBS=-lprotobuf], [have_protobuf=no])) - fi if test x$use_qr != xno; then BITCOIN_QT_CHECK([AC_CHECK_LIB([qrencode], [main],[QR_LIBS=-lqrencode], [have_qrencode=no])]) BITCOIN_QT_CHECK([AC_CHECK_HEADER([qrencode.h],, have_qrencode=no)]) fi fi -save_CXXFLAGS="${CXXFLAGS}" -CXXFLAGS="${CXXFLAGS} ${CRYPTO_CFLAGS} ${SSL_CFLAGS}" -AC_CHECK_DECLS([EVP_MD_CTX_new],,,[AC_INCLUDES_DEFAULT -#include <openssl/x509_vfy.h> -]) -CXXFLAGS="${save_CXXFLAGS}" - dnl RapidCheck property-based testing enable_property_tests=no @@ -1376,12 +1367,6 @@ AM_CONDITIONAL([EMBEDDED_UNIVALUE],[test x$need_bundled_univalue = xyes]) AC_SUBST(UNIVALUE_CFLAGS) AC_SUBST(UNIVALUE_LIBS) - -if test x$have_protobuf != xno && - test x$enable_bip70 != xno; then - BITCOIN_QT_PATH_PROGS([PROTOC], [protoc],$protoc_bin_path) -fi - AC_MSG_CHECKING([whether to build bitcoind]) AM_CONDITIONAL([BUILD_BITCOIND], [test x$build_bitcoind = xyes]) AC_MSG_RESULT($build_bitcoind) @@ -1503,23 +1488,6 @@ if test x$bitcoin_enable_qt != xno; then else AC_MSG_RESULT([no]) fi - - AC_MSG_CHECKING([whether to build BIP70 support]) - if test x$have_protobuf = xno; then - if test x$enable_bip70 = xyes; then - AC_MSG_ERROR(protobuf missing) - fi - enable_bip70=no - AC_MSG_RESULT(no) - else - if test x$enable_bip70 != xno; then - AC_DEFINE([ENABLE_BIP70],[1],[Define if BIP70 support should be compiled in]) - enable_bip70=yes - AC_MSG_RESULT([yes]) - else - AC_MSG_RESULT([no]) - fi - fi fi AM_CONDITIONAL([ENABLE_ZMQ], [test "x$use_zmq" = "xyes"]) @@ -1552,7 +1520,6 @@ AM_CONDITIONAL([ENABLE_TESTS],[test x$BUILD_TEST = xyes]) AM_CONDITIONAL([ENABLE_FUZZ],[test x$enable_fuzz = xyes]) AM_CONDITIONAL([ENABLE_QT],[test x$bitcoin_enable_qt = xyes]) AM_CONDITIONAL([ENABLE_QT_TESTS],[test x$BUILD_TEST_QT = xyes]) -AM_CONDITIONAL([ENABLE_BIP70],[test x$enable_bip70 = xyes]) AM_CONDITIONAL([ENABLE_BENCH],[test x$use_bench = xyes]) AM_CONDITIONAL([USE_QRCODE], [test x$use_qr = xyes]) AM_CONDITIONAL([USE_LCOV],[test x$use_lcov = xyes]) @@ -1618,11 +1585,9 @@ AC_SUBST(LEVELDB_TARGET_FLAGS) AC_SUBST(MINIUPNPC_CPPFLAGS) AC_SUBST(MINIUPNPC_LIBS) AC_SUBST(CRYPTO_LIBS) -AC_SUBST(SSL_LIBS) AC_SUBST(EVENT_LIBS) AC_SUBST(EVENT_PTHREADS_LIBS) AC_SUBST(ZMQ_LIBS) -AC_SUBST(PROTOBUF_LIBS) AC_SUBST(QR_LIBS) AC_CONFIG_FILES([Makefile src/Makefile doc/man/Makefile share/setup.nsi share/qt/Info.plist test/config.ini]) AC_CONFIG_FILES([contrib/devtools/split-debug.sh],[chmod +x contrib/devtools/split-debug.sh]) @@ -1677,7 +1642,6 @@ echo "Options used to compile and link:" echo " with wallet = $enable_wallet" echo " with gui / qt = $bitcoin_enable_qt" if test x$bitcoin_enable_qt != xno; then - echo " with bip70 = $enable_bip70" echo " with qr = $use_qr" fi echo " with zmq = $use_zmq" diff --git a/contrib/bitcoind.bash-completion b/contrib/bitcoind.bash-completion index cccd4bde0d..da869fa2c3 100644 --- a/contrib/bitcoind.bash-completion +++ b/contrib/bitcoind.bash-completion @@ -15,7 +15,7 @@ _bitcoind() { _get_comp_words_by_ref -n = cur prev words cword case "$cur" in - -conf=*|-pid=*|-loadblock=*|-rootcertificates=*|-rpccookiefile=*|-wallet=*) + -conf=*|-pid=*|-loadblock=*|-rpccookiefile=*|-wallet=*) cur="${cur#*=}" _filedir return 0 diff --git a/contrib/gitian-descriptors/gitian-win.yml b/contrib/gitian-descriptors/gitian-win.yml index d5f2c1ad35..d600af84fb 100644 --- a/contrib/gitian-descriptors/gitian-win.yml +++ b/contrib/gitian-descriptors/gitian-win.yml @@ -72,18 +72,10 @@ script: | done } - function create_per-host_linker_wrapper { - # This is only needed for trusty, as the mingw linker leaks a few bytes of - # heap, causing non-determinism. See discussion in https://github.com/bitcoin/bitcoin/pull/6900 + function create_per-host_compiler_wrapper { + # -posix variant is required for c++11 threading. for i in $HOSTS; do mkdir -p ${WRAP_DIR}/${i} - for prog in collect2; do - echo '#!/usr/bin/env bash' > ${WRAP_DIR}/${i}/${prog} - REAL=$(${i}-gcc -print-prog-name=${prog}) - echo "export MALLOC_PERTURB_=255" >> ${WRAP_DIR}/${i}/${prog} - echo "${REAL} \$@" >> $WRAP_DIR/${i}/${prog} - chmod +x ${WRAP_DIR}/${i}/${prog} - done for prog in gcc g++; do echo '#!/usr/bin/env bash' > ${WRAP_DIR}/${i}-${prog} echo "REAL=\`which -a ${i}-${prog}-posix | grep -v ${WRAP_DIR}/${i}-${prog} | head -1\`" >> ${WRAP_DIR}/${i}-${prog} @@ -100,7 +92,7 @@ script: | export PATH_orig=${PATH} create_global_faketime_wrappers "2000-01-01 12:00:00" create_per-host_faketime_wrappers "2000-01-01 12:00:00" - create_per-host_linker_wrapper "2000-01-01 12:00:00" + create_per-host_compiler_wrapper "2000-01-01 12:00:00" export PATH=${WRAP_DIR}:${PATH} cd bitcoin @@ -114,7 +106,7 @@ script: | export PATH=${PATH_orig} create_global_faketime_wrappers "${REFERENCE_DATETIME}" create_per-host_faketime_wrappers "${REFERENCE_DATETIME}" - create_per-host_linker_wrapper "${REFERENCE_DATETIME}" + create_per-host_compiler_wrapper "${REFERENCE_DATETIME}" export PATH=${WRAP_DIR}:${PATH} # Create the release tarball using (arbitrarily) the first host diff --git a/contrib/macdeploy/README.md b/contrib/macdeploy/README.md index e90120ea79..29b49ebff4 100644 --- a/contrib/macdeploy/README.md +++ b/contrib/macdeploy/README.md @@ -11,5 +11,5 @@ This script should not be run manually, instead, after building as usual: During the process, the disk image window will pop up briefly where the fancy settings are applied. This is normal, please do not interfere. -When finished, it will produce `Bitcoin-Core.dmg`. +When finished, it will produce `Bitcoin-Qt.dmg`. diff --git a/depends/Makefile b/depends/Makefile index 25ff135ea6..80df0e46f8 100644 --- a/depends/Makefile +++ b/depends/Makefile @@ -9,7 +9,6 @@ WORK_PATH = $(BASEDIR)/work BASE_CACHE ?= $(BASEDIR)/built SDK_PATH ?= $(BASEDIR)/SDKs NO_QT ?= -PROTOBUF ?= RAPIDCHECK ?= NO_WALLET ?= NO_ZMQ ?= @@ -101,17 +100,11 @@ wallet_packages_$(NO_WALLET) = $(wallet_packages) upnp_packages_$(NO_UPNP) = $(upnp_packages) zmq_packages_$(NO_ZMQ) = $(zmq_packages) -protobuf_packages_$(PROTOBUF) = $(protobuf_packages) rapidcheck_packages_$(RAPIDCHECK) = $(rapidcheck_packages) packages += $($(host_arch)_$(host_os)_packages) $($(host_os)_packages) $(qt_packages_) $(wallet_packages_) $(upnp_packages_) native_packages += $($(host_arch)_$(host_os)_native_packages) $($(host_os)_native_packages) -ifeq ($(protobuf_packages_),) -native_packages += $(protobuf_native_packages) -packages += $(protobuf_packages) -endif - ifneq ($(zmq_packages_),) packages += $(zmq_packages) endif @@ -157,7 +150,6 @@ $(host_prefix)/share/config.site : config.site.in $(host_prefix)/.stamp_$(final_ -e 's|@allow_host_packages@|$(ALLOW_HOST_PACKAGES)|' \ -e 's|@no_qt@|$(NO_QT)|' \ -e 's|@no_zmq@|$(NO_ZMQ)|' \ - -e 's|@enable_bip70@|$(PROTOBUF)|' \ -e 's|@no_wallet@|$(NO_WALLET)|' \ -e 's|@no_upnp@|$(NO_UPNP)|' \ -e 's|@debug@|$(DEBUG)|' \ diff --git a/depends/README.md b/depends/README.md index cfb9bbfeb0..ca542be13f 100644 --- a/depends/README.md +++ b/depends/README.md @@ -77,7 +77,6 @@ The following can be set when running make: make FOO=bar NO_UPNP: Don't download/build/cache packages needed for enabling upnp DEBUG: disable some optimizations and enable more runtime checking RAPIDCHECK: build rapidcheck (experimental, requires cmake) - PROTOBUF: build protobuf (used for deprecated BIP70 support) HOST_ID_SALT: Optional salt to use when generating host package ids BUILD_ID_SALT: Optional salt to use when generating build package ids diff --git a/depends/builders/darwin.mk b/depends/builders/darwin.mk index c7671c1548..eb587fca89 100644 --- a/depends/builders/darwin.mk +++ b/depends/builders/darwin.mk @@ -10,8 +10,8 @@ build_darwin_SHA256SUM=shasum -a 256 build_darwin_DOWNLOAD=curl --location --fail --connect-timeout $(DOWNLOAD_CONNECT_TIMEOUT) --retry $(DOWNLOAD_RETRIES) -o #darwin host on darwin builder. overrides darwin host preferences. -darwin_CC=$(shell xcrun -f clang) -mmacosx-version-min=$(OSX_MIN_VERSION) -darwin_CXX:=$(shell xcrun -f clang++) -mmacosx-version-min=$(OSX_MIN_VERSION) -stdlib=libc++ +darwin_CC=$(shell xcrun -f clang) -mmacosx-version-min=$(OSX_MIN_VERSION) --sysroot $(shell xcrun --show-sdk-path) +darwin_CXX:=$(shell xcrun -f clang++) -mmacosx-version-min=$(OSX_MIN_VERSION) -stdlib=libc++ --sysroot $(shell xcrun --show-sdk-path) darwin_AR:=$(shell xcrun -f ar) darwin_RANLIB:=$(shell xcrun -f ranlib) darwin_STRIP:=$(shell xcrun -f strip) diff --git a/depends/config.guess b/depends/config.guess index 2b79f6d837..7f9ebbe310 100755 --- a/depends/config.guess +++ b/depends/config.guess @@ -1,8 +1,8 @@ #! /bin/sh # Attempt to guess a canonical system name. -# Copyright 1992-2018 Free Software Foundation, Inc. +# Copyright 1992-2019 Free Software Foundation, Inc. -timestamp='2018-07-06' +timestamp='2019-09-10' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -50,7 +50,7 @@ version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. -Copyright 1992-2018 Free Software Foundation, Inc. +Copyright 1992-2019 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -84,8 +84,6 @@ if test $# != 0; then exit 1 fi -trap 'exit 1' 1 2 15 - # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a @@ -96,34 +94,38 @@ trap 'exit 1' 1 2 15 # Portable tmp directory creation inspired by the Autoconf team. -set_cc_for_build=' -trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; -trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; -: ${TMPDIR=/tmp} ; - { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || - { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp 2>/dev/null) ; } || - { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } || - { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; -dummy=$tmp/dummy ; -tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; -case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in - ,,) echo "int x;" > "$dummy.c" ; - for c in cc gcc c89 c99 ; do - if ($c -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then - CC_FOR_BUILD="$c"; break ; - fi ; - done ; - if test x"$CC_FOR_BUILD" = x ; then - CC_FOR_BUILD=no_compiler_found ; - fi - ;; - ,,*) CC_FOR_BUILD=$CC ;; - ,*,*) CC_FOR_BUILD=$HOST_CC ;; -esac ; set_cc_for_build= ;' +tmp= +# shellcheck disable=SC2172 +trap 'test -z "$tmp" || rm -fr "$tmp"' 0 1 2 13 15 + +set_cc_for_build() { + : "${TMPDIR=/tmp}" + # shellcheck disable=SC2039 + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir "$tmp" 2>/dev/null) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir "$tmp" 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } + dummy=$tmp/dummy + case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in + ,,) echo "int x;" > "$dummy.c" + for driver in cc gcc c89 c99 ; do + if ($driver -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then + CC_FOR_BUILD="$driver" + break + fi + done + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; + esac +} # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) -if (test -f /.attbin/uname) >/dev/null 2>&1 ; then +if test -f /.attbin/uname ; then PATH=$PATH:/.attbin ; export PATH fi @@ -138,7 +140,7 @@ Linux|GNU|GNU/*) # We could probably try harder. LIBC=gnu - eval "$set_cc_for_build" + set_cc_for_build cat <<-EOF > "$dummy.c" #include <features.h> #if defined(__UCLIBC__) @@ -199,7 +201,7 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in os=netbsdelf ;; arm*|i386|m68k|ns32k|sh3*|sparc|vax) - eval "$set_cc_for_build" + set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ then @@ -260,6 +262,9 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in *:SolidBSD:*:*) echo "$UNAME_MACHINE"-unknown-solidbsd"$UNAME_RELEASE" exit ;; + *:OS108:*:*) + echo "$UNAME_MACHINE"-unknown-os108_"$UNAME_RELEASE" + exit ;; macppc:MirBSD:*:*) echo powerpc-unknown-mirbsd"$UNAME_RELEASE" exit ;; @@ -269,12 +274,15 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in *:Sortix:*:*) echo "$UNAME_MACHINE"-unknown-sortix exit ;; + *:Twizzler:*:*) + echo "$UNAME_MACHINE"-unknown-twizzler + exit ;; *:Redox:*:*) echo "$UNAME_MACHINE"-unknown-redox exit ;; mips:OSF1:*.*) - echo mips-dec-osf1 - exit ;; + echo mips-dec-osf1 + exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) @@ -389,7 +397,7 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in echo i386-pc-auroraux"$UNAME_RELEASE" exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) - eval "$set_cc_for_build" + set_cc_for_build SUN_ARCH=i386 # If there is a compiler, see if it is configured for 64-bit objects. # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. @@ -482,7 +490,7 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in echo clipper-intergraph-clix"$UNAME_RELEASE" exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) - eval "$set_cc_for_build" + set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #ifdef __cplusplus #include <stdio.h> /* for printf() prototype */ @@ -579,7 +587,7 @@ EOF exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then - eval "$set_cc_for_build" + set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #include <sys/systemcfg.h> @@ -660,7 +668,7 @@ EOF esac fi if [ "$HP_ARCH" = "" ]; then - eval "$set_cc_for_build" + set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #define _HPUX_SOURCE @@ -700,7 +708,7 @@ EOF esac if [ "$HP_ARCH" = hppa2.0w ] then - eval "$set_cc_for_build" + set_cc_for_build # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler @@ -726,7 +734,7 @@ EOF echo ia64-hp-hpux"$HPUX_REV" exit ;; 3050*:HI-UX:*:*) - eval "$set_cc_for_build" + set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #include <unistd.h> int @@ -840,6 +848,17 @@ EOF *:BSD/OS:*:*) echo "$UNAME_MACHINE"-unknown-bsdi"$UNAME_RELEASE" exit ;; + arm:FreeBSD:*:*) + UNAME_PROCESSOR=`uname -p` + set_cc_for_build + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo "${UNAME_PROCESSOR}"-unknown-freebsd"`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`"-gnueabi + else + echo "${UNAME_PROCESSOR}"-unknown-freebsd"`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`"-gnueabihf + fi + exit ;; *:FreeBSD:*:*) UNAME_PROCESSOR=`/usr/bin/uname -p` case "$UNAME_PROCESSOR" in @@ -881,7 +900,7 @@ EOF echo "$UNAME_MACHINE"-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) - echo x86_64-unknown-cygwin + echo x86_64-pc-cygwin exit ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" @@ -922,7 +941,7 @@ EOF echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; arm*:Linux:*:*) - eval "$set_cc_for_build" + set_cc_for_build if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then @@ -971,23 +990,51 @@ EOF echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; mips:Linux:*:* | mips64:Linux:*:*) - eval "$set_cc_for_build" + set_cc_for_build + IS_GLIBC=0 + test x"${LIBC}" = xgnu && IS_GLIBC=1 sed 's/^ //' << EOF > "$dummy.c" #undef CPU - #undef ${UNAME_MACHINE} - #undef ${UNAME_MACHINE}el + #undef mips + #undef mipsel + #undef mips64 + #undef mips64el + #if ${IS_GLIBC} && defined(_ABI64) + LIBCABI=gnuabi64 + #else + #if ${IS_GLIBC} && defined(_ABIN32) + LIBCABI=gnuabin32 + #else + LIBCABI=${LIBC} + #endif + #endif + + #if ${IS_GLIBC} && defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6 + CPU=mipsisa64r6 + #else + #if ${IS_GLIBC} && !defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6 + CPU=mipsisa32r6 + #else + #if defined(__mips64) + CPU=mips64 + #else + CPU=mips + #endif + #endif + #endif + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) - CPU=${UNAME_MACHINE}el + MIPS_ENDIAN=el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) - CPU=${UNAME_MACHINE} + MIPS_ENDIAN= #else - CPU= + MIPS_ENDIAN= #endif #endif EOF - eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU'`" - test "x$CPU" != x && { echo "$CPU-unknown-linux-$LIBC"; exit; } + eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU\|^MIPS_ENDIAN\|^LIBCABI'`" + test "x$CPU" != x && { echo "$CPU${MIPS_ENDIAN}-unknown-linux-$LIBCABI"; exit; } ;; mips64el:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" @@ -1100,7 +1147,7 @@ EOF *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac - echo "$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}{$UNAME_VERSION}" + echo "$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}" exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then @@ -1284,38 +1331,39 @@ EOF echo "$UNAME_MACHINE"-apple-rhapsody"$UNAME_RELEASE" exit ;; *:Darwin:*:*) - UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown - eval "$set_cc_for_build" - if test "$UNAME_PROCESSOR" = unknown ; then - UNAME_PROCESSOR=powerpc + UNAME_PROCESSOR=`uname -p` + case $UNAME_PROCESSOR in + unknown) UNAME_PROCESSOR=powerpc ;; + esac + if command -v xcode-select > /dev/null 2> /dev/null && \ + ! xcode-select --print-path > /dev/null 2> /dev/null ; then + # Avoid executing cc if there is no toolchain installed as + # cc will be a stub that puts up a graphical alert + # prompting the user to install developer tools. + CC_FOR_BUILD=no_compiler_found + else + set_cc_for_build fi - if test "`echo "$UNAME_RELEASE" | sed -e 's/\..*//'`" -le 10 ; then - if [ "$CC_FOR_BUILD" != no_compiler_found ]; then - if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null - then - case $UNAME_PROCESSOR in - i386) UNAME_PROCESSOR=x86_64 ;; - powerpc) UNAME_PROCESSOR=powerpc64 ;; - esac - fi - # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc - if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \ - (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_PPC >/dev/null - then - UNAME_PROCESSOR=powerpc - fi + if [ "$CC_FOR_BUILD" != no_compiler_found ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + case $UNAME_PROCESSOR in + i386) UNAME_PROCESSOR=x86_64 ;; + powerpc) UNAME_PROCESSOR=powerpc64 ;; + esac + fi + # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc + if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_PPC >/dev/null + then + UNAME_PROCESSOR=powerpc fi elif test "$UNAME_PROCESSOR" = i386 ; then - # Avoid executing cc on OS X 10.9, as it ships with a stub - # that puts up a graphical alert prompting to install - # developer tools. Any system running Mac OS X 10.7 or - # later (Darwin 11 and later) is required to have a 64-bit - # processor. This is not true of the ARM version of Darwin - # that Apple uses in portable devices. - UNAME_PROCESSOR=x86_64 + # uname -m returns i386 or x86_64 + UNAME_PROCESSOR=$UNAME_MACHINE fi echo "$UNAME_PROCESSOR"-apple-darwin"$UNAME_RELEASE" exit ;; @@ -1358,6 +1406,7 @@ EOF # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. + # shellcheck disable=SC2154 if test "$cputype" = 386; then UNAME_MACHINE=i386 else @@ -1414,8 +1463,148 @@ EOF amd64:Isilon\ OneFS:*:*) echo x86_64-unknown-onefs exit ;; + *:Unleashed:*:*) + echo "$UNAME_MACHINE"-unknown-unleashed"$UNAME_RELEASE" + exit ;; esac +# No uname command or uname output not recognized. +set_cc_for_build +cat > "$dummy.c" <<EOF +#ifdef _SEQUENT_ +#include <sys/types.h> +#include <sys/utsname.h> +#endif +#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__) +#if defined (vax) || defined (__vax) || defined (__vax__) || defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__) +#include <signal.h> +#if defined(_SIZE_T_) || defined(SIGLOST) +#include <sys/utsname.h> +#endif +#endif +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include <sys/param.h> + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); +#endif + +#if defined (vax) +#if !defined (ultrix) +#include <sys/param.h> +#if defined (BSD) +#if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +#else +#if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +#else + printf ("vax-dec-bsd\n"); exit (0); +#endif +#endif +#else + printf ("vax-dec-bsd\n"); exit (0); +#endif +#else +#if defined(_SIZE_T_) || defined(SIGLOST) + struct utsname un; + uname (&un); + printf ("vax-dec-ultrix%s\n", un.release); exit (0); +#else + printf ("vax-dec-ultrix\n"); exit (0); +#endif +#endif +#endif +#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__) +#if defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__) +#if defined(_SIZE_T_) || defined(SIGLOST) + struct utsname *un; + uname (&un); + printf ("mips-dec-ultrix%s\n", un.release); exit (0); +#else + printf ("mips-dec-ultrix\n"); exit (0); +#endif +#endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. +test -d /usr/apollo && { echo "$ISP-apollo-$SYSTYPE"; exit; } + echo "$0: unable to guess system type" >&2 case "$UNAME_MACHINE:$UNAME_SYSTEM" in diff --git a/depends/config.site.in b/depends/config.site.in index d0d36641c4..dee568bc25 100644 --- a/depends/config.site.in +++ b/depends/config.site.in @@ -16,10 +16,6 @@ fi if test -z $with_qt_bindir && test -z "@no_qt@"; then with_qt_bindir=$depends_prefix/native/bin fi -if test -z $with_protoc_bindir && test -z "@no_qt@"; then - with_protoc_bindir=$depends_prefix/native/bin -fi - if test -z $enable_wallet && test -n "@no_wallet@"; then enable_wallet=no @@ -37,10 +33,6 @@ if test -z $enable_zmq && test -n "@no_zmq@"; then enable_zmq=no fi -if test -n $enable_bip70 && test -n "@enable_bip70@"; then - enable_bip70=yes -fi - if test x@host_os@ = xdarwin; then BREW=no PORT=no diff --git a/depends/config.sub b/depends/config.sub index c95acc681d..a318a46868 100755 --- a/depends/config.sub +++ b/depends/config.sub @@ -1,8 +1,8 @@ #! /bin/sh # Configuration validation subroutine script. -# Copyright 1992-2018 Free Software Foundation, Inc. +# Copyright 1992-2019 Free Software Foundation, Inc. -timestamp='2018-07-03' +timestamp='2019-06-30' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -67,7 +67,7 @@ Report bugs and patches to <config-patches@gnu.org>." version="\ GNU config.sub ($timestamp) -Copyright 1992-2018 Free Software Foundation, Inc. +Copyright 1992-2019 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -89,7 +89,7 @@ while test $# -gt 0 ; do - ) # Use stdin as input. break ;; -* ) - echo "$me: invalid option $1$help" + echo "$me: invalid option $1$help" >&2 exit 1 ;; *local*) @@ -111,7 +111,8 @@ case $# in esac # Split fields of configuration type -IFS="-" read -r field1 field2 field3 field4 <<EOF +# shellcheck disable=SC2162 +IFS="-" read field1 field2 field3 field4 <<EOF $1 EOF @@ -149,29 +150,39 @@ case $1 in esac ;; *-*) - # Second component is usually, but not always the OS - case $field2 in - # Prevent following clause from handling this valid os - sun*os*) - basic_machine=$field1 - os=$field2 - ;; - # Manufacturers - dec* | mips* | sequent* | encore* | pc532* | sgi* | sony* \ - | att* | 7300* | 3300* | delta* | motorola* | sun[234]* \ - | unicom* | ibm* | next | hp | isi* | apollo | altos* \ - | convergent* | ncr* | news | 32* | 3600* | 3100* | hitachi* \ - | c[123]* | convex* | sun | crds | omron* | dg | ultra | tti* \ - | harris | dolphin | highlevel | gould | cbm | ns | masscomp \ - | apple | axis | knuth | cray | microblaze* \ - | sim | cisco | oki | wec | wrs | winbond) - basic_machine=$field1-$field2 + # A lone config we happen to match not fitting any pattern + case $field1-$field2 in + decstation-3100) + basic_machine=mips-dec os= ;; - *) - basic_machine=$field1 - os=$field2 - ;; + *-*) + # Second component is usually, but not always the OS + case $field2 in + # Prevent following clause from handling this valid os + sun*os*) + basic_machine=$field1 + os=$field2 + ;; + # Manufacturers + dec* | mips* | sequent* | encore* | pc533* | sgi* | sony* \ + | att* | 7300* | 3300* | delta* | motorola* | sun[234]* \ + | unicom* | ibm* | next | hp | isi* | apollo | altos* \ + | convergent* | ncr* | news | 32* | 3600* | 3100* \ + | hitachi* | c[123]* | convex* | sun | crds | omron* | dg \ + | ultra | tti* | harris | dolphin | highlevel | gould \ + | cbm | ns | masscomp | apple | axis | knuth | cray \ + | microblaze* | sim | cisco \ + | oki | wec | wrs | winbond) + basic_machine=$field1-$field2 + os= + ;; + *) + basic_machine=$field1 + os=$field2 + ;; + esac + ;; esac ;; *) @@ -190,6 +201,14 @@ case $1 in basic_machine=m68010-adobe os=scout ;; + alliant) + basic_machine=fx80-alliant + os= + ;; + altos | altos3068) + basic_machine=m68k-altos + os= + ;; am29k) basic_machine=a29k-none os=bsd @@ -198,6 +217,10 @@ case $1 in basic_machine=580-amdahl os=sysv ;; + amiga) + basic_machine=m68k-unknown + os= + ;; amigaos | amigados) basic_machine=m68k-unknown os=amigaos @@ -234,13 +257,41 @@ case $1 in basic_machine=arm-unknown os=cegcc ;; + convex-c1) + basic_machine=c1-convex + os=bsd + ;; + convex-c2) + basic_machine=c2-convex + os=bsd + ;; + convex-c32) + basic_machine=c32-convex + os=bsd + ;; + convex-c34) + basic_machine=c34-convex + os=bsd + ;; + convex-c38) + basic_machine=c38-convex + os=bsd + ;; cray) basic_machine=j90-cray os=unicos ;; - craynv) - basic_machine=craynv-cray - os=unicosmp + crds | unos) + basic_machine=m68k-crds + os= + ;; + da30) + basic_machine=m68k-da30 + os= + ;; + decstation | pmax | pmin | dec3100 | decstatn) + basic_machine=mips-dec + os= ;; delta88) basic_machine=m88k-motorola @@ -286,13 +337,13 @@ case $1 in basic_machine=m88k-harris os=sysv3 ;; - hp300bsd) + hp300 | hp300hpux) basic_machine=m68k-hp - os=bsd + os=hpux ;; - hp300hpux) + hp300bsd) basic_machine=m68k-hp - os=hpux + os=bsd ;; hppaosf) basic_machine=hppa1.1-hp @@ -306,10 +357,6 @@ case $1 in basic_machine=i386-mach os=mach ;; - vsta) - basic_machine=i386-unknown - os=vsta - ;; isi68 | isi) basic_machine=m68k-isi os=sysv @@ -371,7 +418,7 @@ case $1 in os=sysv4 ;; netbsd386) - basic_machine=i386-unknown + basic_machine=i386-pc os=netbsd ;; netwinder) @@ -454,14 +501,26 @@ case $1 in basic_machine=mips-sei os=seiux ;; + sequent) + basic_machine=i386-sequent + os= + ;; sps7) basic_machine=m68k-bull os=sysv2 ;; + st2000) + basic_machine=m68k-tandem + os= + ;; stratus) basic_machine=i860-stratus os=sysv4 ;; + sun2) + basic_machine=m68000-sun + os= + ;; sun2os3) basic_machine=m68000-sun os=sunos3 @@ -470,6 +529,10 @@ case $1 in basic_machine=m68000-sun os=sunos4 ;; + sun3) + basic_machine=m68k-sun + os= + ;; sun3os3) basic_machine=m68k-sun os=sunos3 @@ -478,6 +541,10 @@ case $1 in basic_machine=m68k-sun os=sunos4 ;; + sun4) + basic_machine=sparc-sun + os= + ;; sun4os3) basic_machine=sparc-sun os=sunos3 @@ -490,6 +557,10 @@ case $1 in basic_machine=sparc-sun os=solaris2 ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + os= + ;; sv1) basic_machine=sv1-cray os=unicos @@ -534,6 +605,10 @@ case $1 in basic_machine=vax-dec os=vms ;; + vsta) + basic_machine=i386-pc + os=vsta + ;; vxworks960) basic_machine=i960-wrs os=vxworks @@ -562,417 +637,162 @@ case $1 in ;; esac -# Decode aliases for certain CPU-COMPANY combinations. +# Decode 1-component or ad-hoc basic machines case $basic_machine in - # Recognize the basic CPU types without company name. - # Some are omitted here because they have special meanings below. - 1750a | 580 \ - | a29k \ - | aarch64 | aarch64_be \ - | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ - | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ - | am33_2.0 \ - | arc | arceb \ - | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv6m | armv[78][arm] \ - | avr | avr32 \ - | ba \ - | be32 | be64 \ - | bfin \ - | c4x | c8051 | clipper | csky \ - | d10v | d30v | dlx | dsp16xx \ - | e2k | epiphany \ - | fido | fr30 | frv | ft32 \ - | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ - | hexagon \ - | i370 | i860 | i960 | ia16 | ia64 \ - | ip2k | iq2000 \ - | k1om \ - | le32 | le64 \ - | lm32 \ - | m32c | m32r | m32rle | m68000 | m68k | m88k \ - | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ - | mips | mipsbe | mipseb | mipsel | mipsle \ - | mips16 \ - | mips64 | mips64el \ - | mips64octeon | mips64octeonel \ - | mips64orion | mips64orionel \ - | mips64r5900 | mips64r5900el \ - | mips64vr | mips64vrel \ - | mips64vr4100 | mips64vr4100el \ - | mips64vr4300 | mips64vr4300el \ - | mips64vr5000 | mips64vr5000el \ - | mips64vr5900 | mips64vr5900el \ - | mipsisa32 | mipsisa32el \ - | mipsisa32r2 | mipsisa32r2el \ - | mipsisa32r6 | mipsisa32r6el \ - | mipsisa64 | mipsisa64el \ - | mipsisa64r2 | mipsisa64r2el \ - | mipsisa64r6 | mipsisa64r6el \ - | mipsisa64sb1 | mipsisa64sb1el \ - | mipsisa64sr71k | mipsisa64sr71kel \ - | mipsr5900 | mipsr5900el \ - | mipstx39 | mipstx39el \ - | mn10200 | mn10300 \ - | moxie \ - | mt \ - | msp430 \ - | nds32 | nds32le | nds32be \ - | nfp \ - | nios | nios2 | nios2eb | nios2el \ - | ns16k | ns32k \ - | open8 | or1k | or1knd | or32 \ - | pdp10 | pj | pjl \ - | powerpc | powerpc64 | powerpc64le | powerpcle \ - | pru \ - | pyramid \ - | riscv | riscv32 | riscv64 \ - | rl78 | rx \ - | score \ - | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ - | sh64 | sh64le \ - | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ - | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ - | spu \ - | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ - | ubicom32 \ - | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ - | visium \ - | wasm32 \ - | x86 | xc16x | xstormy16 | xtensa \ - | z8k | z80) - basic_machine=$basic_machine-unknown - ;; - c54x) - basic_machine=tic54x-unknown - ;; - c55x) - basic_machine=tic55x-unknown - ;; - c6x) - basic_machine=tic6x-unknown - ;; - leon|leon[3-9]) - basic_machine=sparc-$basic_machine - ;; - m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) - basic_machine=$basic_machine-unknown - os=${os:-none} - ;; - m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65) + # Here we handle the default manufacturer of certain CPU types. It is in + # some cases the only manufacturer, in others, it is the most popular. + w89k) + cpu=hppa1.1 + vendor=winbond ;; - m9s12z | m68hcs12z | hcs12z | s12z) - basic_machine=s12z-unknown - os=${os:-none} + op50n) + cpu=hppa1.1 + vendor=oki ;; - ms1) - basic_machine=mt-unknown + op60c) + cpu=hppa1.1 + vendor=oki ;; - strongarm | thumb | xscale) - basic_machine=arm-unknown + ibm*) + cpu=i370 + vendor=ibm ;; - xgate) - basic_machine=$basic_machine-unknown - os=${os:-none} + orion105) + cpu=clipper + vendor=highlevel ;; - xscaleeb) - basic_machine=armeb-unknown + mac | mpw | mac-mpw) + cpu=m68k + vendor=apple ;; - - xscaleel) - basic_machine=armel-unknown + pmac | pmac-mpw) + cpu=powerpc + vendor=apple ;; - # We use `pc' rather than `unknown' - # because (1) that's what they normally are, and - # (2) the word "unknown" tends to confuse beginning users. - i*86 | x86_64) - basic_machine=$basic_machine-pc - ;; - # Recognize the basic CPU types with company name. - 580-* \ - | a29k-* \ - | aarch64-* | aarch64_be-* \ - | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ - | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ - | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ - | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ - | avr-* | avr32-* \ - | ba-* \ - | be32-* | be64-* \ - | bfin-* | bs2000-* \ - | c[123]* | c30-* | [cjt]90-* | c4x-* \ - | c8051-* | clipper-* | craynv-* | csky-* | cydra-* \ - | d10v-* | d30v-* | dlx-* \ - | e2k-* | elxsi-* \ - | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ - | h8300-* | h8500-* \ - | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ - | hexagon-* \ - | i*86-* | i860-* | i960-* | ia16-* | ia64-* \ - | ip2k-* | iq2000-* \ - | k1om-* \ - | le32-* | le64-* \ - | lm32-* \ - | m32c-* | m32r-* | m32rle-* \ - | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ - | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ - | microblaze-* | microblazeel-* \ - | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ - | mips16-* \ - | mips64-* | mips64el-* \ - | mips64octeon-* | mips64octeonel-* \ - | mips64orion-* | mips64orionel-* \ - | mips64r5900-* | mips64r5900el-* \ - | mips64vr-* | mips64vrel-* \ - | mips64vr4100-* | mips64vr4100el-* \ - | mips64vr4300-* | mips64vr4300el-* \ - | mips64vr5000-* | mips64vr5000el-* \ - | mips64vr5900-* | mips64vr5900el-* \ - | mipsisa32-* | mipsisa32el-* \ - | mipsisa32r2-* | mipsisa32r2el-* \ - | mipsisa32r6-* | mipsisa32r6el-* \ - | mipsisa64-* | mipsisa64el-* \ - | mipsisa64r2-* | mipsisa64r2el-* \ - | mipsisa64r6-* | mipsisa64r6el-* \ - | mipsisa64sb1-* | mipsisa64sb1el-* \ - | mipsisa64sr71k-* | mipsisa64sr71kel-* \ - | mipsr5900-* | mipsr5900el-* \ - | mipstx39-* | mipstx39el-* \ - | mmix-* \ - | mt-* \ - | msp430-* \ - | nds32-* | nds32le-* | nds32be-* \ - | nfp-* \ - | nios-* | nios2-* | nios2eb-* | nios2el-* \ - | none-* | np1-* | ns16k-* | ns32k-* \ - | open8-* \ - | or1k*-* \ - | orion-* \ - | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ - | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ - | pru-* \ - | pyramid-* \ - | riscv-* | riscv32-* | riscv64-* \ - | rl78-* | romp-* | rs6000-* | rx-* \ - | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ - | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ - | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ - | sparclite-* \ - | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \ - | tahoe-* \ - | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ - | tile*-* \ - | tron-* \ - | ubicom32-* \ - | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ - | vax-* \ - | visium-* \ - | wasm32-* \ - | we32k-* \ - | x86-* | x86_64-* | xc16x-* | xps100-* \ - | xstormy16-* | xtensa*-* \ - | ymp-* \ - | z8k-* | z80-*) - ;; - # Recognize the basic CPU types without company name, with glob match. - xtensa*) - basic_machine=$basic_machine-unknown - ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) - basic_machine=m68000-att + cpu=m68000 + vendor=att ;; 3b*) - basic_machine=we32k-att - ;; - abacus) - basic_machine=abacus-unknown - ;; - alliant | fx80) - basic_machine=fx80-alliant - ;; - altos | altos3068) - basic_machine=m68k-altos - ;; - amd64) - basic_machine=x86_64-pc - ;; - amd64-*) - basic_machine=x86_64-`echo "$basic_machine" | sed 's/^[^-]*-//'` - ;; - amiga | amiga-*) - basic_machine=m68k-unknown - ;; - asmjs) - basic_machine=asmjs-unknown - ;; - blackfin-*) - basic_machine=bfin-`echo "$basic_machine" | sed 's/^[^-]*-//'` - os=linux + cpu=we32k + vendor=att ;; bluegene*) - basic_machine=powerpc-ibm + cpu=powerpc + vendor=ibm os=cnk ;; - c54x-*) - basic_machine=tic54x-`echo "$basic_machine" | sed 's/^[^-]*-//'` - ;; - c55x-*) - basic_machine=tic55x-`echo "$basic_machine" | sed 's/^[^-]*-//'` - ;; - c6x-*) - basic_machine=tic6x-`echo "$basic_machine" | sed 's/^[^-]*-//'` - ;; - c90) - basic_machine=c90-cray - os=${os:-unicos} - ;; - convex-c1) - basic_machine=c1-convex - os=bsd - ;; - convex-c2) - basic_machine=c2-convex - os=bsd - ;; - convex-c32) - basic_machine=c32-convex - os=bsd - ;; - convex-c34) - basic_machine=c34-convex - os=bsd - ;; - convex-c38) - basic_machine=c38-convex - os=bsd - ;; - cr16 | cr16-*) - basic_machine=cr16-unknown - os=${os:-elf} - ;; - crds | unos) - basic_machine=m68k-crds - ;; - crisv32 | crisv32-* | etraxfs*) - basic_machine=crisv32-axis - ;; - cris | cris-* | etrax*) - basic_machine=cris-axis - ;; - crx) - basic_machine=crx-unknown - os=${os:-elf} - ;; - da30 | da30-*) - basic_machine=m68k-da30 - ;; - decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) - basic_machine=mips-dec - ;; decsystem10* | dec10*) - basic_machine=pdp10-dec + cpu=pdp10 + vendor=dec os=tops10 ;; decsystem20* | dec20*) - basic_machine=pdp10-dec + cpu=pdp10 + vendor=dec os=tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) - basic_machine=m68k-motorola - ;; - dpx20 | dpx20-*) - basic_machine=rs6000-bull - os=${os:-bosx} + cpu=m68k + vendor=motorola ;; dpx2*) - basic_machine=m68k-bull + cpu=m68k + vendor=bull os=sysv3 ;; - e500v[12]) - basic_machine=powerpc-unknown - os=$os"spe" - ;; - e500v[12]-*) - basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'` - os=$os"spe" - ;; encore | umax | mmax) - basic_machine=ns32k-encore + cpu=ns32k + vendor=encore ;; elxsi) - basic_machine=elxsi-elxsi + cpu=elxsi + vendor=elxsi os=${os:-bsd} ;; fx2800) - basic_machine=i860-alliant + cpu=i860 + vendor=alliant ;; genix) - basic_machine=ns32k-ns + cpu=ns32k + vendor=ns ;; h3050r* | hiux*) - basic_machine=hppa1.1-hitachi + cpu=hppa1.1 + vendor=hitachi os=hiuxwe2 ;; - hp300-*) - basic_machine=m68k-hp - ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) - basic_machine=hppa1.0-hp + cpu=hppa1.0 + vendor=hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) - basic_machine=m68000-hp + cpu=m68000 + vendor=hp ;; hp9k3[2-9][0-9]) - basic_machine=m68k-hp + cpu=m68k + vendor=hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) - basic_machine=hppa1.0-hp + cpu=hppa1.0 + vendor=hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) - basic_machine=hppa1.1-hp + cpu=hppa1.1 + vendor=hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp + cpu=hppa1.1 + vendor=hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp + cpu=hppa1.1 + vendor=hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) - basic_machine=hppa1.1-hp + cpu=hppa1.1 + vendor=hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - i370-ibm* | ibm*) - basic_machine=i370-ibm + cpu=hppa1.0 + vendor=hp ;; i*86v32) - basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` + cpu=`echo "$1" | sed -e 's/86.*/86/'` + vendor=pc os=sysv32 ;; i*86v4*) - basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` + cpu=`echo "$1" | sed -e 's/86.*/86/'` + vendor=pc os=sysv4 ;; i*86v) - basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` + cpu=`echo "$1" | sed -e 's/86.*/86/'` + vendor=pc os=sysv ;; i*86sol2) - basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` + cpu=`echo "$1" | sed -e 's/86.*/86/'` + vendor=pc os=solaris2 ;; j90 | j90-cray) - basic_machine=j90-cray + cpu=j90 + vendor=cray os=${os:-unicos} ;; iris | iris4d) - basic_machine=mips-sgi + cpu=mips + vendor=sgi case $os in irix*) ;; @@ -981,40 +801,27 @@ case $basic_machine in ;; esac ;; - leon-*|leon[3-9]-*) - basic_machine=sparc-`echo "$basic_machine" | sed 's/-.*//'` - ;; - m68knommu-*) - basic_machine=m68k-`echo "$basic_machine" | sed 's/^[^-]*-//'` - os=linux - ;; - microblaze*) - basic_machine=microblaze-xilinx - ;; miniframe) - basic_machine=m68000-convergent + cpu=m68000 + vendor=convergent ;; *mint | mint[0-9]* | *MiNT | *MiNT[0-9]*) - basic_machine=m68k-atari + cpu=m68k + vendor=atari os=mint ;; - mips3*-*) - basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'` - ;; - mips3*) - basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'`-unknown - ;; - ms1-*) - basic_machine=`echo "$basic_machine" | sed -e 's/ms1-/mt-/'` - ;; news-3600 | risc-news) - basic_machine=mips-sony + cpu=mips + vendor=sony os=newsos ;; next | m*-next) - basic_machine=m68k-next + cpu=m68k + vendor=next case $os in - nextstep* ) + openstep*) + ;; + nextstep*) ;; ns2*) os=nextstep2 @@ -1025,260 +832,442 @@ case $basic_machine in esac ;; np1) - basic_machine=np1-gould + cpu=np1 + vendor=gould ;; - neo-tandem) - basic_machine=neo-tandem + op50n-* | op60c-*) + cpu=hppa1.1 + vendor=oki + os=proelf ;; - nse-tandem) - basic_machine=nse-tandem + pa-hitachi) + cpu=hppa1.1 + vendor=hitachi + os=hiuxwe2 ;; - nsr-tandem) - basic_machine=nsr-tandem + pbd) + cpu=sparc + vendor=tti ;; - nsv-tandem) - basic_machine=nsv-tandem + pbb) + cpu=m68k + vendor=tti ;; - nsx-tandem) - basic_machine=nsx-tandem + pc532) + cpu=ns32k + vendor=pc532 ;; - op50n-* | op60c-*) - basic_machine=hppa1.1-oki - os=proelf + pn) + cpu=pn + vendor=gould ;; - openrisc | openrisc-*) - basic_machine=or32-unknown + power) + cpu=power + vendor=ibm ;; - pa-hitachi) - basic_machine=hppa1.1-hitachi - os=hiuxwe2 + ps2) + cpu=i386 + vendor=ibm ;; - parisc-*) - basic_machine=hppa-`echo "$basic_machine" | sed 's/^[^-]*-//'` - os=linux + rm[46]00) + cpu=mips + vendor=siemens ;; - pbd) - basic_machine=sparc-tti + rtpc | rtpc-*) + cpu=romp + vendor=ibm ;; - pbb) - basic_machine=m68k-tti + sde) + cpu=mipsisa32 + vendor=sde + os=${os:-elf} ;; - pc532 | pc532-*) - basic_machine=ns32k-pc532 + simso-wrs) + cpu=sparclite + vendor=wrs + os=vxworks ;; - pc98) - basic_machine=i386-pc + tower | tower-32) + cpu=m68k + vendor=ncr ;; - pc98-*) - basic_machine=i386-`echo "$basic_machine" | sed 's/^[^-]*-//'` + vpp*|vx|vx-*) + cpu=f301 + vendor=fujitsu ;; - pentium | p5 | k5 | k6 | nexgen | viac3) - basic_machine=i586-pc + w65) + cpu=w65 + vendor=wdc ;; - pentiumpro | p6 | 6x86 | athlon | athlon_*) - basic_machine=i686-pc + w89k-*) + cpu=hppa1.1 + vendor=winbond + os=proelf ;; - pentiumii | pentium2 | pentiumiii | pentium3) - basic_machine=i686-pc + none) + cpu=none + vendor=none ;; - pentium4) - basic_machine=i786-pc + leon|leon[3-9]) + cpu=sparc + vendor=$basic_machine ;; - pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) - basic_machine=i586-`echo "$basic_machine" | sed 's/^[^-]*-//'` + leon-*|leon[3-9]-*) + cpu=sparc + vendor=`echo "$basic_machine" | sed 's/-.*//'` ;; - pentiumpro-* | p6-* | 6x86-* | athlon-*) - basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'` + + *-*) + # shellcheck disable=SC2162 + IFS="-" read cpu vendor <<EOF +$basic_machine +EOF ;; - pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) - basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'` + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + cpu=$basic_machine + vendor=pc ;; - pentium4-*) - basic_machine=i786-`echo "$basic_machine" | sed 's/^[^-]*-//'` + # These rules are duplicated from below for sake of the special case above; + # i.e. things that normalized to x86 arches should also default to "pc" + pc98) + cpu=i386 + vendor=pc ;; - pn) - basic_machine=pn-gould + x64 | amd64) + cpu=x86_64 + vendor=pc + ;; + # Recognize the basic CPU types without company name. + *) + cpu=$basic_machine + vendor=unknown + ;; +esac + +unset -v basic_machine + +# Decode basic machines in the full and proper CPU-Company form. +case $cpu-$vendor in + # Here we handle the default manufacturer of certain CPU types in canonical form. It is in + # some cases the only manufacturer, in others, it is the most popular. + craynv-unknown) + vendor=cray + os=${os:-unicosmp} + ;; + c90-unknown | c90-cray) + vendor=cray + os=${os:-unicos} ;; - power) basic_machine=power-ibm + fx80-unknown) + vendor=alliant ;; - ppc | ppcbe) basic_machine=powerpc-unknown + romp-unknown) + vendor=ibm ;; - ppc-* | ppcbe-*) - basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'` + mmix-unknown) + vendor=knuth ;; - ppcle | powerpclittle) - basic_machine=powerpcle-unknown + microblaze-unknown | microblazeel-unknown) + vendor=xilinx ;; - ppcle-* | powerpclittle-*) - basic_machine=powerpcle-`echo "$basic_machine" | sed 's/^[^-]*-//'` + rs6000-unknown) + vendor=ibm ;; - ppc64) basic_machine=powerpc64-unknown + vax-unknown) + vendor=dec ;; - ppc64-*) basic_machine=powerpc64-`echo "$basic_machine" | sed 's/^[^-]*-//'` + pdp11-unknown) + vendor=dec ;; - ppc64le | powerpc64little) - basic_machine=powerpc64le-unknown + we32k-unknown) + vendor=att ;; - ppc64le-* | powerpc64little-*) - basic_machine=powerpc64le-`echo "$basic_machine" | sed 's/^[^-]*-//'` + cydra-unknown) + vendor=cydrome ;; - ps2) - basic_machine=i386-ibm + i370-ibm*) + vendor=ibm ;; - rm[46]00) - basic_machine=mips-siemens + orion-unknown) + vendor=highlevel ;; - rtpc | rtpc-*) - basic_machine=romp-ibm + xps-unknown | xps100-unknown) + cpu=xps100 + vendor=honeywell ;; - s390 | s390-*) - basic_machine=s390-ibm + + # Here we normalize CPU types with a missing or matching vendor + dpx20-unknown | dpx20-bull) + cpu=rs6000 + vendor=bull + os=${os:-bosx} ;; - s390x | s390x-*) - basic_machine=s390x-ibm + + # Here we normalize CPU types irrespective of the vendor + amd64-*) + cpu=x86_64 ;; - sb1) - basic_machine=mipsisa64sb1-unknown + blackfin-*) + cpu=bfin + os=linux ;; - sb1el) - basic_machine=mipsisa64sb1el-unknown + c54x-*) + cpu=tic54x ;; - sde) - basic_machine=mipsisa32-sde - os=${os:-elf} + c55x-*) + cpu=tic55x ;; - sequent) - basic_machine=i386-sequent + c6x-*) + cpu=tic6x ;; - sh5el) - basic_machine=sh5le-unknown + e500v[12]-*) + cpu=powerpc + os=$os"spe" ;; - simso-wrs) - basic_machine=sparclite-wrs - os=vxworks + mips3*-*) + cpu=mips64 ;; - spur) - basic_machine=spur-unknown + ms1-*) + cpu=mt ;; - st2000) - basic_machine=m68k-tandem + m68knommu-*) + cpu=m68k + os=linux ;; - strongarm-* | thumb-*) - basic_machine=arm-`echo "$basic_machine" | sed 's/^[^-]*-//'` + m9s12z-* | m68hcs12z-* | hcs12z-* | s12z-*) + cpu=s12z ;; - sun2) - basic_machine=m68000-sun + openrisc-*) + cpu=or32 ;; - sun3 | sun3-*) - basic_machine=m68k-sun + parisc-*) + cpu=hppa + os=linux ;; - sun4) - basic_machine=sparc-sun + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + cpu=i586 ;; - sun386 | sun386i | roadrunner) - basic_machine=i386-sun + pentiumpro-* | p6-* | 6x86-* | athlon-* | athalon_*-*) + cpu=i686 ;; - tile*) - basic_machine=$basic_machine-unknown - os=linux-gnu + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + cpu=i686 ;; - tx39) - basic_machine=mipstx39-unknown + pentium4-*) + cpu=i786 ;; - tx39el) - basic_machine=mipstx39el-unknown + pc98-*) + cpu=i386 ;; - tower | tower-32) - basic_machine=m68k-ncr + ppc-* | ppcbe-*) + cpu=powerpc ;; - vpp*|vx|vx-*) - basic_machine=f301-fujitsu + ppcle-* | powerpclittle-*) + cpu=powerpcle ;; - w65*) - basic_machine=w65-wdc - os=none + ppc64-*) + cpu=powerpc64 ;; - w89k-*) - basic_machine=hppa1.1-winbond - os=proelf + ppc64le-* | powerpc64little-*) + cpu=powerpc64le ;; - x64) - basic_machine=x86_64-pc + sb1-*) + cpu=mipsisa64sb1 ;; - xps | xps100) - basic_machine=xps100-honeywell + sb1el-*) + cpu=mipsisa64sb1el ;; - xscale-* | xscalee[bl]-*) - basic_machine=`echo "$basic_machine" | sed 's/^xscale/arm/'` + sh5e[lb]-*) + cpu=`echo "$cpu" | sed 's/^\(sh.\)e\(.\)$/\1\2e/'` ;; - none) - basic_machine=none-none - os=${os:-none} + spur-*) + cpu=spur ;; - -# Here we handle the default manufacturer of certain CPU types. It is in -# some cases the only manufacturer, in others, it is the most popular. - w89k) - basic_machine=hppa1.1-winbond + strongarm-* | thumb-*) + cpu=arm ;; - op50n) - basic_machine=hppa1.1-oki + tx39-*) + cpu=mipstx39 ;; - op60c) - basic_machine=hppa1.1-oki + tx39el-*) + cpu=mipstx39el ;; - romp) - basic_machine=romp-ibm + x64-*) + cpu=x86_64 ;; - mmix) - basic_machine=mmix-knuth + xscale-* | xscalee[bl]-*) + cpu=`echo "$cpu" | sed 's/^xscale/arm/'` ;; - rs6000) - basic_machine=rs6000-ibm + + # Recognize the canonical CPU Types that limit and/or modify the + # company names they are paired with. + cr16-*) + os=${os:-elf} ;; - vax) - basic_machine=vax-dec + crisv32-* | etraxfs*-*) + cpu=crisv32 + vendor=axis ;; - pdp11) - basic_machine=pdp11-dec + cris-* | etrax*-*) + cpu=cris + vendor=axis ;; - we32k) - basic_machine=we32k-att + crx-*) + os=${os:-elf} ;; - sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) - basic_machine=sh-unknown + neo-tandem) + cpu=neo + vendor=tandem ;; - cydra) - basic_machine=cydra-cydrome + nse-tandem) + cpu=nse + vendor=tandem ;; - orion) - basic_machine=orion-highlevel + nsr-tandem) + cpu=nsr + vendor=tandem ;; - orion105) - basic_machine=clipper-highlevel + nsv-tandem) + cpu=nsv + vendor=tandem ;; - mac | mpw | mac-mpw) - basic_machine=m68k-apple + nsx-tandem) + cpu=nsx + vendor=tandem ;; - pmac | pmac-mpw) - basic_machine=powerpc-apple + s390-*) + cpu=s390 + vendor=ibm ;; - *-unknown) - # Make sure to match an already-canonicalized machine name. + s390x-*) + cpu=s390x + vendor=ibm ;; + tile*-*) + os=${os:-linux-gnu} + ;; + *) - echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2 - exit 1 + # Recognize the canonical CPU types that are allowed with any + # company name. + case $cpu in + 1750a | 580 \ + | a29k \ + | aarch64 | aarch64_be \ + | abacus \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] \ + | alphapca5[67] | alpha64pca5[67] \ + | am33_2.0 \ + | amdgcn \ + | arc | arceb \ + | arm | arm[lb]e | arme[lb] | armv* \ + | avr | avr32 \ + | asmjs \ + | ba \ + | be32 | be64 \ + | bfin | bpf | bs2000 \ + | c[123]* | c30 | [cjt]90 | c4x \ + | c8051 | clipper | craynv | csky | cydra \ + | d10v | d30v | dlx | dsp16xx \ + | e2k | elxsi | epiphany \ + | f30[01] | f700 | fido | fr30 | frv | ft32 | fx80 \ + | h8300 | h8500 \ + | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | hexagon \ + | i370 | i*86 | i860 | i960 | ia16 | ia64 \ + | ip2k | iq2000 \ + | k1om \ + | le32 | le64 \ + | lm32 \ + | m32c | m32r | m32rle \ + | m5200 | m68000 | m680[012346]0 | m68360 | m683?2 | m68k \ + | m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x \ + | m88110 | m88k | maxq | mb | mcore | mep | metag \ + | microblaze | microblazeel \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64eb | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa32r6 | mipsisa32r6el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64r6 | mipsisa64r6el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipsr5900 | mipsr5900el \ + | mipstx39 | mipstx39el \ + | mmix \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nfp \ + | nios | nios2 | nios2eb | nios2el \ + | none | np1 | ns16k | ns32k | nvptx \ + | open8 \ + | or1k* \ + | or32 \ + | orion \ + | picochip \ + | pdp10 | pdp11 | pj | pjl | pn | power \ + | powerpc | powerpc64 | powerpc64le | powerpcle | powerpcspe \ + | pru \ + | pyramid \ + | riscv | riscv32 | riscv64 \ + | rl78 | romp | rs6000 | rx \ + | score \ + | sh | shl \ + | sh[1234] | sh[24]a | sh[24]ae[lb] | sh[23]e | she[lb] | sh[lb]e \ + | sh[1234]e[lb] | sh[12345][lb]e | sh[23]ele | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet \ + | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v | sv1 | sx* \ + | spu \ + | tahoe \ + | tic30 | tic4x | tic54x | tic55x | tic6x | tic80 \ + | tron \ + | ubicom32 \ + | v70 | v850 | v850e | v850e1 | v850es | v850e2 | v850e2v3 \ + | vax \ + | visium \ + | w65 \ + | wasm32 | wasm64 \ + | we32k \ + | x86 | x86_64 | xc16x | xgate | xps100 \ + | xstormy16 | xtensa* \ + | ymp \ + | z8k | z80) + ;; + + *) + echo Invalid configuration \`"$1"\': machine \`"$cpu-$vendor"\' not recognized 1>&2 + exit 1 + ;; + esac ;; esac # Here we canonicalize certain aliases for manufacturers. -case $basic_machine in - *-digital*) - basic_machine=`echo "$basic_machine" | sed 's/digital.*/dec/'` +case $vendor in + digital*) + vendor=dec ;; - *-commodore*) - basic_machine=`echo "$basic_machine" | sed 's/commodore.*/cbm/'` + commodore*) + vendor=cbm ;; *) ;; @@ -1356,9 +1345,9 @@ case $os in | amigaos* | amigados* | msdos* | newsos* | unicos* | aof* \ | aos* | aros* | cloudabi* | sortix* \ | nindy* | vxsim* | vxworks* | ebmon* | hms* | mvs* \ - | clix* | riscos* | uniplus* | iris* | rtu* | xenix* \ + | clix* | riscos* | uniplus* | iris* | isc* | rtu* | xenix* \ | knetbsd* | mirbsd* | netbsd* \ - | bitrig* | openbsd* | solidbsd* | libertybsd* \ + | bitrig* | openbsd* | solidbsd* | libertybsd* | os108* \ | ekkobsd* | kfreebsd* | freebsd* | riscix* | lynxos* \ | bosx* | nextstep* | cxux* | aout* | elf* | oabi* \ | ptx* | coff* | ecoff* | winnt* | domain* | vsta* \ @@ -1376,12 +1365,13 @@ case $os in | powermax* | dnix* | nx6 | nx7 | sei* | dragonfly* \ | skyos* | haiku* | rdos* | toppers* | drops* | es* \ | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \ - | midnightbsd*) + | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \ + | nsk* | powerunix) # Remember, each alternative MUST END IN *, to match a version number. ;; qnx*) - case $basic_machine in - x86-* | i*86-*) + case $cpu in + x86 | i*86) ;; *) os=nto-$os @@ -1460,9 +1450,6 @@ case $os in ns2) os=nextstep2 ;; - nsk*) - os=nsk - ;; # Preserve the version number of sinix5. sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` @@ -1507,7 +1494,7 @@ case $os in # Until real need of OS specific support for # particular features comes up, bare metal # configurations are quite functional. - case $basic_machine in + case $cpu in arm*) os=eabi ;; @@ -1541,7 +1528,7 @@ else # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. -case $basic_machine in +case $cpu-$vendor in score-*) os=elf ;; @@ -1722,9 +1709,8 @@ fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. -vendor=unknown -case $basic_machine in - *-unknown) +case $vendor in + unknown) case $os in riscix*) vendor=acorn @@ -1793,11 +1779,10 @@ case $basic_machine in vendor=stratus ;; esac - basic_machine=`echo "$basic_machine" | sed "s/unknown/$vendor/"` ;; esac -echo "$basic_machine-$os" +echo "$cpu-$vendor-$os" exit # Local variables: diff --git a/depends/funcs.mk b/depends/funcs.mk index 8f03c5f37a..a4434b5167 100644 --- a/depends/funcs.mk +++ b/depends/funcs.mk @@ -133,7 +133,7 @@ $(1)_config_env+=PKG_CONFIG_PATH=$($($(1)_type)_prefix)/share/pkgconfig $(1)_config_env+=PATH=$(build_prefix)/bin:$(PATH) $(1)_build_env+=PATH=$(build_prefix)/bin:$(PATH) $(1)_stage_env+=PATH=$(build_prefix)/bin:$(PATH) -$(1)_autoconf=./configure --host=$($($(1)_type)_host) --disable-dependency-tracking --prefix=$($($(1)_type)_prefix) $$($(1)_config_opts) CC="$$($(1)_cc)" CXX="$$($(1)_cxx)" +$(1)_autoconf=./configure --host=$($($(1)_type)_host) --prefix=$($($(1)_type)_prefix) $$($(1)_config_opts) CC="$$($(1)_cc)" CXX="$$($(1)_cxx)" ifneq ($($(1)_nm),) $(1)_autoconf += NM="$$($(1)_nm)" diff --git a/depends/packages/bdb.mk b/depends/packages/bdb.mk index 6cdb79592b..b679438c6f 100644 --- a/depends/packages/bdb.mk +++ b/depends/packages/bdb.mk @@ -6,7 +6,7 @@ $(package)_sha256_hash=12edc0df75bf9abd7f82f821795bcee50f42cb2e5f76a6a281b857327 $(package)_build_subdir=build_unix define $(package)_set_vars -$(package)_config_opts=--disable-shared --enable-cxx --disable-replication +$(package)_config_opts=--disable-shared --enable-cxx --disable-replication --enable-option-checking $(package)_config_opts_mingw32=--enable-mingw $(package)_config_opts_linux=--with-pic $(package)_cxxflags=-std=c++11 diff --git a/depends/packages/boost.mk b/depends/packages/boost.mk index 5df49b2af8..766b8d224e 100644 --- a/depends/packages/boost.mk +++ b/depends/packages/boost.mk @@ -10,15 +10,14 @@ $(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_BZIP2=1 -sNO_ZLIB=1 $(package)_config_opts_linux=threadapi=pthread runtime-link=shared -$(package)_config_opts_darwin=--toolset=darwin-4.2.1 runtime-link=shared +$(package)_config_opts_darwin=--toolset=clang-darwin runtime-link=shared $(package)_config_opts_mingw32=binary-format=pe target-os=windows threadapi=win32 runtime-link=static $(package)_config_opts_x86_64_mingw32=address-model=64 $(package)_config_opts_i686_mingw32=address-model=32 $(package)_config_opts_i686_linux=address-model=32 architecture=x86 $(package)_toolset_$(host_os)=gcc $(package)_archiver_$(host_os)=$($(package)_ar) -$(package)_toolset_darwin=darwin -$(package)_archiver_darwin=$($(package)_libtool) +$(package)_toolset_darwin=clang-darwin $(package)_config_libraries=chrono,filesystem,system,thread,test $(package)_cxxflags=-std=c++11 -fvisibility=hidden $(package)_cxxflags_linux=-fPIC diff --git a/depends/packages/expat.mk b/depends/packages/expat.mk index 4784381915..902fe43be2 100644 --- a/depends/packages/expat.mk +++ b/depends/packages/expat.mk @@ -6,6 +6,7 @@ $(package)_sha256_hash=cbc9102f4a31a8dafd42d642e9a3aa31e79a0aedaa1f6efd2795ebc83 define $(package)_set_vars $(package)_config_opts=--disable-shared --without-docbook --without-tests --without-examples + $(package)_config_opts += --disable-dependency-tracking --enable-option-checking $(package)_config_opts_linux=--with-pic endef diff --git a/depends/packages/fontconfig.mk b/depends/packages/fontconfig.mk index ed21fbba33..128599ba77 100644 --- a/depends/packages/fontconfig.mk +++ b/depends/packages/fontconfig.mk @@ -7,6 +7,7 @@ $(package)_dependencies=freetype expat define $(package)_set_vars $(package)_config_opts=--disable-docs --disable-static --disable-libxml2 --disable-iconv + $(package)_config_opts += --disable-dependency-tracking --enable-option-checking endef define $(package)_config_cmds diff --git a/depends/packages/freetype.mk b/depends/packages/freetype.mk index f24fc69d81..a1584608e1 100644 --- a/depends/packages/freetype.mk +++ b/depends/packages/freetype.mk @@ -6,6 +6,7 @@ $(package)_sha256_hash=3a3bb2c4e15ffb433f2032f50a5b5a92558206822e22bfe8cbe339af4 define $(package)_set_vars $(package)_config_opts=--without-zlib --without-png --without-harfbuzz --without-bzip2 --disable-static + $(package)_config_opts += --enable-option-checking $(package)_config_opts_linux=--with-pic endef diff --git a/depends/packages/libXau.mk b/depends/packages/libXau.mk index 058416f793..4c55c2df04 100644 --- a/depends/packages/libXau.mk +++ b/depends/packages/libXau.mk @@ -9,6 +9,7 @@ $(package)_dependencies=xproto # --disable-xthreads. It is currently enabled. define $(package)_set_vars $(package)_config_opts=--disable-shared --disable-lint-library --without-lint + $(package)_config_opts += --disable-dependency-tracking --enable-option-checking $(package)_config_opts_linux=--with-pic endef diff --git a/depends/packages/libevent.mk b/depends/packages/libevent.mk index a3ade899b7..300c806a8d 100644 --- a/depends/packages/libevent.mk +++ b/depends/packages/libevent.mk @@ -10,6 +10,7 @@ endef define $(package)_set_vars $(package)_config_opts=--disable-shared --disable-openssl --disable-libevent-regress --disable-samples + $(package)_config_opts += --disable-dependency-tracking --enable-option-checking $(package)_config_opts_release=--disable-debug-mode $(package)_config_opts_linux=--with-pic endef diff --git a/depends/packages/libxcb.mk b/depends/packages/libxcb.mk index 49d3e3d15b..2204b38195 100644 --- a/depends/packages/libxcb.mk +++ b/depends/packages/libxcb.mk @@ -7,6 +7,7 @@ $(package)_dependencies=xcb_proto libXau define $(package)_set_vars $(package)_config_opts=--disable-static --disable-build-docs --without-doxygen --without-launchd +$(package)_config_opts += --disable-dependency-tracking --enable-option-checking # Because we pass -qt-xcb to Qt, it will compile in a set of xcb helper libraries and extensions, # so we skip building all of the extensions here. # More info is available from: https://doc.qt.io/qt-5.9/linux-requirements.html diff --git a/depends/packages/native_libdmg-hfsplus.mk b/depends/packages/native_libdmg-hfsplus.mk index a4ffb6046c..8493f1d979 100644 --- a/depends/packages/native_libdmg-hfsplus.mk +++ b/depends/packages/native_libdmg-hfsplus.mk @@ -1,16 +1,18 @@ package=native_libdmg-hfsplus -$(package)_version=0.1 -$(package)_download_path=https://github.com/theuni/libdmg-hfsplus/archive -$(package)_file_name=libdmg-hfsplus-v$($(package)_version).tar.gz -$(package)_sha256_hash=6569a02eb31c2827080d7d59001869ea14484c281efab0ae7f2b86af5c3120b3 +$(package)_version=7ac55ec64c96f7800d9818ce64c79670e7f02b67 +$(package)_download_path=https://github.com/planetbeing/libdmg-hfsplus/archive +$(package)_file_name=$($(package)_version).tar.gz +$(package)_sha256_hash=56fbdc48ec110966342f0ecddd6f8f89202f4143ed2a3336e42bbf88f940850c $(package)_build_subdir=build +$(package)_patches=remove-libcrypto-dependency.patch define $(package)_preprocess_cmds + patch -p1 < $($(package)_patch_dir)/remove-libcrypto-dependency.patch && \ mkdir build endef define $(package)_config_cmds - cmake -DCMAKE_INSTALL_PREFIX:PATH=$(build_prefix)/bin .. + cmake -DCMAKE_INSTALL_PREFIX:PATH=$(build_prefix) .. endef define $(package)_build_cmds diff --git a/depends/packages/native_protobuf.mk b/depends/packages/native_protobuf.mk deleted file mode 100644 index 1de8c37d36..0000000000 --- a/depends/packages/native_protobuf.mk +++ /dev/null @@ -1,25 +0,0 @@ -package=native_protobuf -$(package)_version=2.6.1 -$(package)_download_path=https://github.com/google/protobuf/releases/download/v$($(package)_version) -$(package)_file_name=protobuf-$($(package)_version).tar.bz2 -$(package)_sha256_hash=ee445612d544d885ae240ffbcbf9267faa9f593b7b101f21d58beceb92661910 - -define $(package)_set_vars -$(package)_config_opts=--disable-shared --without-zlib -endef - -define $(package)_config_cmds - $($(package)_autoconf) -endef - -define $(package)_build_cmds - $(MAKE) -C src protoc -endef - -define $(package)_stage_cmds - $(MAKE) -C src DESTDIR=$($(package)_staging_dir) install-strip -endef - -define $(package)_postprocess_cmds - rm -rf lib include -endef diff --git a/depends/packages/openssl.mk b/depends/packages/openssl.mk index 3e8a22a1b0..3498a3f6ee 100644 --- a/depends/packages/openssl.mk +++ b/depends/packages/openssl.mk @@ -71,7 +71,7 @@ define $(package)_config_cmds endef define $(package)_build_cmds - $(MAKE) -j1 build_libs libcrypto.pc libssl.pc openssl.pc + $(MAKE) -j1 build_crypto libcrypto.pc libssl.pc openssl.pc endef define $(package)_stage_cmds diff --git a/depends/packages/packages.mk b/depends/packages/packages.mk index 667fde5271..35f8b829db 100644 --- a/depends/packages/packages.mk +++ b/depends/packages/packages.mk @@ -1,8 +1,5 @@ packages:=boost openssl libevent -protobuf_native_packages = native_protobuf -protobuf_packages = protobuf - qt_packages = qrencode zlib qt_linux_packages:=qt expat libxcb xcb_proto libXau xproto freetype fontconfig diff --git a/depends/packages/protobuf.mk b/depends/packages/protobuf.mk deleted file mode 100644 index 52975b14ec..0000000000 --- a/depends/packages/protobuf.mk +++ /dev/null @@ -1,34 +0,0 @@ -package=protobuf -$(package)_version=$(native_$(package)_version) -$(package)_download_path=$(native_$(package)_download_path) -$(package)_file_name=$(native_$(package)_file_name) -$(package)_sha256_hash=$(native_$(package)_sha256_hash) -$(package)_dependencies=native_$(package) -$(package)_cxxflags=-std=c++11 - -define $(package)_set_vars - $(package)_config_opts=--disable-shared --with-protoc=$(build_prefix)/bin/protoc - $(package)_config_opts_linux=--with-pic -endef - -define $(package)_preprocess_cmds - cp -f $(BASEDIR)/config.guess $(BASEDIR)/config.sub . &&\ - cp -f $(BASEDIR)/config.guess $(BASEDIR)/config.sub gtest/build-aux -endef - -define $(package)_config_cmds - $($(package)_autoconf) -endef - -define $(package)_build_cmds - $(MAKE) -C src libprotobuf.la -endef - -define $(package)_stage_cmds - $(MAKE) DESTDIR=$($(package)_staging_dir) -C src install-libLTLIBRARIES install-nobase_includeHEADERS &&\ - $(MAKE) DESTDIR=$($(package)_staging_dir) install-pkgconfigDATA -endef - -define $(package)_postprocess_cmds - rm lib/libprotoc.a lib/*.la -endef diff --git a/depends/packages/qrencode.mk b/depends/packages/qrencode.mk index 3bc2cb768c..21570726ff 100644 --- a/depends/packages/qrencode.mk +++ b/depends/packages/qrencode.mk @@ -7,6 +7,7 @@ $(package)_sha256_hash=efe5188b1ddbcbf98763b819b146be6a90481aac30cfc8d858ab78a19 define $(package)_set_vars $(package)_config_opts=--disable-shared --without-tools --without-tests --disable-sdltest $(package)_config_opts += --disable-gprof --disable-gcov --disable-mudflap +$(package)_config_opts += --disable-dependency-tracking --enable-option-checking $(package)_config_opts_linux=--with-pic endef diff --git a/depends/packages/qt.mk b/depends/packages/qt.mk index f4832b6168..0685eb2da2 100644 --- a/depends/packages/qt.mk +++ b/depends/packages/qt.mk @@ -4,7 +4,7 @@ $(package)_download_path=https://download.qt.io/official_releases/qt/5.9/$($(pac $(package)_suffix=opensource-src-$($(package)_version).tar.xz $(package)_file_name=qtbase-$($(package)_suffix) $(package)_sha256_hash=9b9dec1f67df1f94bce2955c5604de992d529dde72050239154c56352da0907d -$(package)_dependencies=openssl zlib +$(package)_dependencies=zlib $(package)_linux_dependencies=freetype fontconfig libxcb $(package)_build_subdir=qtbase $(package)_qt_libs=corelib network widgets gui plugins testlib @@ -42,9 +42,11 @@ $(package)_config_opts += -no-linuxfb $(package)_config_opts += -no-libjpeg $(package)_config_opts += -no-libudev $(package)_config_opts += -no-mtdev +$(package)_config_opts += -no-openssl $(package)_config_opts += -no-openvg $(package)_config_opts += -no-reduce-relocations $(package)_config_opts += -no-qml-debug +$(package)_config_opts += -no-securetransport $(package)_config_opts += -no-sql-db2 $(package)_config_opts += -no-sql-ibase $(package)_config_opts += -no-sql-oci @@ -59,7 +61,6 @@ $(package)_config_opts += -no-xinput2 $(package)_config_opts += -nomake examples $(package)_config_opts += -nomake tests $(package)_config_opts += -opensource -$(package)_config_opts += -openssl-linked $(package)_config_opts += -optimized-qmake $(package)_config_opts += -pch $(package)_config_opts += -pkg-config diff --git a/depends/packages/xcb_proto.mk b/depends/packages/xcb_proto.mk index 44110394bd..85d01ecd2f 100644 --- a/depends/packages/xcb_proto.mk +++ b/depends/packages/xcb_proto.mk @@ -5,7 +5,7 @@ $(package)_file_name=xcb-proto-$($(package)_version).tar.bz2 $(package)_sha256_hash=7ef40ddd855b750bc597d2a435da21e55e502a0fefa85b274f2c922800baaf05 define $(package)_set_vars - $(package)_config_opts=--disable-shared + $(package)_config_opts=--disable-shared --enable-option-checking $(package)_config_opts_linux=--with-pic endef diff --git a/depends/packages/xproto.mk b/depends/packages/xproto.mk index 2462f3c647..6bd867d02b 100644 --- a/depends/packages/xproto.mk +++ b/depends/packages/xproto.mk @@ -6,6 +6,7 @@ $(package)_sha256_hash=636162c1759805a5a0114a369dffdeccb8af8c859ef6e1445f26a4e6e define $(package)_set_vars $(package)_config_opts=--without-fop --without-xmlto --without-xsltproc --disable-specs +$(package)_config_opts += --disable-dependency-tracking --enable-option-checking endef define $(package)_preprocess_cmds diff --git a/depends/packages/zeromq.mk b/depends/packages/zeromq.mk index 9ac037ebb5..ce85c437bb 100644 --- a/depends/packages/zeromq.mk +++ b/depends/packages/zeromq.mk @@ -6,9 +6,10 @@ $(package)_sha256_hash=bcbabe1e2c7d0eec4ed612e10b94b112dd5f06fcefa994a0c79a45d83 $(package)_patches=0001-fix-build-with-older-mingw64.patch 0002-disable-pthread_set_name_np.patch define $(package)_set_vars - $(package)_config_opts=--without-docs --disable-shared --disable-curve --disable-curve-keygen --disable-perf --disable-Werror --disable-drafts + $(package)_config_opts=--without-docs --disable-shared --disable-curve --disable-curve-keygen --disable-perf $(package)_config_opts += --without-libsodium --without-libgssapi_krb5 --without-pgm --without-norm --without-vmci - $(package)_config_opts += --disable-libunwind --disable-radix-tree --without-gcov + $(package)_config_opts += --disable-libunwind --disable-radix-tree --without-gcov --disable-dependency-tracking + $(package)_config_opts += --disable-Werror --disable-drafts --enable-option-checking $(package)_config_opts_linux=--with-pic $(package)_cxxflags=-std=c++11 endef diff --git a/depends/patches/native_libdmg-hfsplus/remove-libcrypto-dependency.patch b/depends/patches/native_libdmg-hfsplus/remove-libcrypto-dependency.patch new file mode 100644 index 0000000000..f346c8f2cf --- /dev/null +++ b/depends/patches/native_libdmg-hfsplus/remove-libcrypto-dependency.patch @@ -0,0 +1,45 @@ +From 3e5fd3fb56bc9ff03beb535979e33dcf83fe1f70 Mon Sep 17 00:00:00 2001 +From: Cory Fields <cory-nospam-@coryfields.com> +Date: Thu, 8 May 2014 12:39:42 -0400 +Subject: [PATCH] dmg: remove libcrypto dependency + +--- + dmg/CMakeLists.txt | 16 ---------------- + 1 file changed, 16 deletions(-) + +diff --git a/dmg/CMakeLists.txt b/dmg/CMakeLists.txt +index eec62d6..3969f64 100644 +--- a/dmg/CMakeLists.txt ++++ b/dmg/CMakeLists.txt +@@ -1,12 +1,5 @@ +-INCLUDE(FindOpenSSL) + INCLUDE(FindZLIB) + +-FIND_LIBRARY(CRYPTO_LIBRARIES crypto +- PATHS +- /usr/lib +- /usr/local/lib +- ) +- + IF(NOT ZLIB_FOUND) + message(FATAL_ERROR "zlib is required for dmg!") + ENDIF(NOT ZLIB_FOUND) +@@ -18,15 +11,6 @@ link_directories(${PROJECT_BINARY_DIR}/common ${PROJECT_BINARY_DIR}/hfs) + + add_library(dmg adc.c base64.c checksum.c dmgfile.c dmglib.c filevault.c io.c partition.c resources.c udif.c) + +-IF(OPENSSL_FOUND) +- add_definitions(-DHAVE_CRYPT) +- include_directories(${OPENSSL_INCLUDE_DIR}) +- target_link_libraries(dmg ${CRYPTO_LIBRARIES}) +- IF(WIN32) +- TARGET_LINK_LIBRARIES(dmg gdi32) +- ENDIF(WIN32) +-ENDIF(OPENSSL_FOUND) +- + target_link_libraries(dmg common hfs z) + + add_executable(dmg-bin dmg.c) +-- +2.22.0 + diff --git a/doc/bips.md b/doc/bips.md index 90d0e341df..45562cec62 100644 --- a/doc/bips.md +++ b/doc/bips.md @@ -18,23 +18,23 @@ BIPs that are implemented by Bitcoin Core (up-to-date up to **v0.19.0**): * [`BIP 61`](https://github.com/bitcoin/bips/blob/master/bip-0061.mediawiki): The 'reject' protocol message (and the protocol version bump to 70002) was added in **v0.9.0** ([PR #3185](https://github.com/bitcoin/bitcoin/pull/3185)). Starting **v0.17.0**, whether to send reject messages can be configured with the `-enablebip61` option, and support is deprecated (disabled by default) as of **v0.18.0**. Support was removed in **v0.20.0** ([PR #15437](https://github.com/bitcoin/bitcoin/pull/15437)). * [`BIP 65`](https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki): The CHECKLOCKTIMEVERIFY softfork was merged in **v0.12.0** ([PR #6351](https://github.com/bitcoin/bitcoin/pull/6351)), and backported to **v0.11.2** and **v0.10.4**. Mempool-only CLTV was added in [PR #6124](https://github.com/bitcoin/bitcoin/pull/6124). * [`BIP 66`](https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki): The strict DER rules and associated version 3 blocks have been implemented since **v0.10.0** ([PR #5713](https://github.com/bitcoin/bitcoin/pull/5713)). -* [`BIP 68`](https://github.com/bitcoin/bips/blob/master/bip-0068.mediawiki): Sequence locks have been implemented as of **v0.12.1** ([PR #7184](https://github.com/bitcoin/bitcoin/pull/7184)), and have been activated since *block 419328*. +* [`BIP 68`](https://github.com/bitcoin/bips/blob/master/bip-0068.mediawiki): Sequence locks have been implemented as of **v0.12.1** ([PR #7184](https://github.com/bitcoin/bitcoin/pull/7184)), and have been *buried* since **v0.19.0** ([PR #16060](https://github.com/bitcoin/bitcoin/pull/16060)). * [`BIP 70`](https://github.com/bitcoin/bips/blob/master/bip-0070.mediawiki) [`71`](https://github.com/bitcoin/bips/blob/master/bip-0071.mediawiki) [`72`](https://github.com/bitcoin/bips/blob/master/bip-0072.mediawiki): Payment Protocol support has been available in Bitcoin Core GUI since **v0.9.0** ([PR #5216](https://github.com/bitcoin/bitcoin/pull/5216)). Support can be optionally disabled at build time since **v0.18.0** ([PR 14451](https://github.com/bitcoin/bitcoin/pull/14451)), and is disabled by default at build time since **v0.19.0** ([PR #15584](https://github.com/bitcoin/bitcoin/pull/15584)). * [`BIP 90`](https://github.com/bitcoin/bips/blob/master/bip-0090.mediawiki): Trigger mechanism for activation of BIPs 34, 65, and 66 has been simplified to block height checks since **v0.14.0** ([PR #8391](https://github.com/bitcoin/bitcoin/pull/8391)). * [`BIP 111`](https://github.com/bitcoin/bips/blob/master/bip-0111.mediawiki): `NODE_BLOOM` service bit added, and enforced for all peer versions as of **v0.13.0** ([PR #6579](https://github.com/bitcoin/bitcoin/pull/6579) and [PR #6641](https://github.com/bitcoin/bitcoin/pull/6641)). -* [`BIP 112`](https://github.com/bitcoin/bips/blob/master/bip-0112.mediawiki): The CHECKSEQUENCEVERIFY opcode has been implemented since **v0.12.1** ([PR #7524](https://github.com/bitcoin/bitcoin/pull/7524)) and has been activated since *block 419328*. -* [`BIP 113`](https://github.com/bitcoin/bips/blob/master/bip-0113.mediawiki): Median time past lock-time calculations have been implemented since **v0.12.1** ([PR #6566](https://github.com/bitcoin/bitcoin/pull/6566)) and have been activated since *block 419328*. +* [`BIP 112`](https://github.com/bitcoin/bips/blob/master/bip-0112.mediawiki): The CHECKSEQUENCEVERIFY opcode has been implemented since **v0.12.1** ([PR #7524](https://github.com/bitcoin/bitcoin/pull/7524)), and has been *buried* since **v0.19.0** ([PR #16060](https://github.com/bitcoin/bitcoin/pull/16060)). +* [`BIP 113`](https://github.com/bitcoin/bips/blob/master/bip-0113.mediawiki): Median time past lock-time calculations have been implemented since **v0.12.1** ([PR #6566](https://github.com/bitcoin/bitcoin/pull/6566)), and has been *buried* since **v0.19.0** ([PR #16060](https://github.com/bitcoin/bitcoin/pull/16060)). * [`BIP 125`](https://github.com/bitcoin/bips/blob/master/bip-0125.mediawiki): Opt-in full replace-by-fee signaling honoured in mempool and mining as of **v0.12.0** ([PR 6871](https://github.com/bitcoin/bitcoin/pull/6871)). Enabled by default in the wallet GUI as of **v0.18.1** ([PR #11605](https://github.com/bitcoin/bitcoin/pull/11605)) * [`BIP 130`](https://github.com/bitcoin/bips/blob/master/bip-0130.mediawiki): direct headers announcement is negotiated with peer versions `>=70012` as of **v0.12.0** ([PR 6494](https://github.com/bitcoin/bitcoin/pull/6494)). * [`BIP 133`](https://github.com/bitcoin/bips/blob/master/bip-0133.mediawiki): feefilter messages are respected and sent for peer versions `>=70013` as of **v0.13.0** ([PR 7542](https://github.com/bitcoin/bitcoin/pull/7542)). -* [`BIP 141`](https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki): Segregated Witness (Consensus Layer) as of **v0.13.0** ([PR 8149](https://github.com/bitcoin/bitcoin/pull/8149)), and defined for mainnet as of **v0.13.1** ([PR 8937](https://github.com/bitcoin/bitcoin/pull/8937)). -* [`BIP 143`](https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki): Transaction Signature Verification for Version 0 Witness Program as of **v0.13.0** ([PR 8149](https://github.com/bitcoin/bitcoin/pull/8149)) and defined for mainnet as of **v0.13.1** ([PR 8937](https://github.com/bitcoin/bitcoin/pull/8937)). +* [`BIP 141`](https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki): Segregated Witness (Consensus Layer) as of **v0.13.0** ([PR 8149](https://github.com/bitcoin/bitcoin/pull/8149)), defined for mainnet as of **v0.13.1** ([PR 8937](https://github.com/bitcoin/bitcoin/pull/8937)), and *buried* since **v0.19.0** ([PR #16060](https://github.com/bitcoin/bitcoin/pull/16060)). +* [`BIP 143`](https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki): Transaction Signature Verification for Version 0 Witness Program as of **v0.13.0** ([PR 8149](https://github.com/bitcoin/bitcoin/pull/8149)), defined for mainnet as of **v0.13.1** ([PR 8937](https://github.com/bitcoin/bitcoin/pull/8937)), and *buried* since **v0.19.0** ([PR #16060](https://github.com/bitcoin/bitcoin/pull/16060)). * [`BIP 144`](https://github.com/bitcoin/bips/blob/master/bip-0144.mediawiki): Segregated Witness as of **0.13.0** ([PR 8149](https://github.com/bitcoin/bitcoin/pull/8149)). * [`BIP 145`](https://github.com/bitcoin/bips/blob/master/bip-0145.mediawiki): getblocktemplate updates for Segregated Witness as of **v0.13.0** ([PR 8149](https://github.com/bitcoin/bitcoin/pull/8149)). -* [`BIP 147`](https://github.com/bitcoin/bips/blob/master/bip-0147.mediawiki): NULLDUMMY softfork as of **v0.13.1** ([PR 8636](https://github.com/bitcoin/bitcoin/pull/8636) and [PR 8937](https://github.com/bitcoin/bitcoin/pull/8937)). +* [`BIP 147`](https://github.com/bitcoin/bips/blob/master/bip-0147.mediawiki): NULLDUMMY softfork as of **v0.13.1** ([PR 8636](https://github.com/bitcoin/bitcoin/pull/8636) and [PR 8937](https://github.com/bitcoin/bitcoin/pull/8937)), *buried* since **v0.19.0** ([PR #16060](https://github.com/bitcoin/bitcoin/pull/16060)). * [`BIP 152`](https://github.com/bitcoin/bips/blob/master/bip-0152.mediawiki): Compact block transfer and related optimizations are used as of **v0.13.0** ([PR 8068](https://github.com/bitcoin/bitcoin/pull/8068)). - [`BIP 158`](https://github.com/bitcoin/bips/blob/master/bip-0158.mediawiki): Compact Block Filters for Light Clients can be indexed as of **v0.19.0** ([PR #14121](https://github.com/bitcoin/bitcoin/pull/14121)). -* [`BIP 159`](https://github.com/bitcoin/bips/blob/master/bip-0159.mediawiki): The NODE_NETWORK_LIMITED service bit is signalled as of **v0.16.0** ([PR 11740](https://github.com/bitcoin/bitcoin/pull/11740)), and such nodes are connected to as of **v0.17.0** ([PR 10387](https://github.com/bitcoin/bitcoin/pull/10387)). +* [`BIP 159`](https://github.com/bitcoin/bips/blob/master/bip-0159.mediawiki): The `NODE_NETWORK_LIMITED` service bit is signalled as of **v0.16.0** ([PR 11740](https://github.com/bitcoin/bitcoin/pull/11740)), and such nodes are connected to as of **v0.17.0** ([PR 10387](https://github.com/bitcoin/bitcoin/pull/10387)). * [`BIP 173`](https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki): Bech32 addresses for native Segregated Witness outputs are supported as of **v0.16.0** ([PR 11167](https://github.com/bitcoin/bitcoin/pull/11167)). Bech32 addresses are generated by default as of **v0.20.0** ([PR 16884](https://github.com/bitcoin/bitcoin/pull/16884)). * [`BIP 174`](https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki): RPCs to operate on Partially Signed Bitcoin Transactions (PSBT) are present as of **v0.17.0** ([PR 13557](https://github.com/bitcoin/bitcoin/pull/13557)). * [`BIP 176`](https://github.com/bitcoin/bips/blob/master/bip-0176.mediawiki): Bits Denomination [QT only] is supported as of **v0.16.0** ([PR 12035](https://github.com/bitcoin/bitcoin/pull/12035)). diff --git a/doc/build-unix.md b/doc/build-unix.md index 069c983e6e..d048bdeff5 100644 --- a/doc/build-unix.md +++ b/doc/build-unix.md @@ -44,7 +44,6 @@ Optional dependencies: miniupnpc | UPnP Support | Firewall-jumping support libdb4.8 | Berkeley DB | Wallet storage (only needed when wallet enabled) qt | GUI | GUI toolkit (only needed when GUI enabled) - protobuf | Payments in GUI | Data interchange format used for payment protocol (only needed when BIP70 enabled) libqrencode | QR codes in GUI | Optional for generating QR codes (only needed when GUI enabled) univalue | Utility | JSON parsing and encoding (bundled version will be used unless --with-system-univalue passed to configure) libzmq3 | ZMQ notification | Optional, allows generating ZMQ notifications (requires ZMQ version >= 4.0.0) @@ -118,10 +117,6 @@ libqrencode (optional) can be installed with: sudo apt-get install libqrencode-dev -protobuf (optional) can be installed with: - - sudo apt-get install libprotobuf-dev protobuf-compiler - Once these are installed, they will be found by configure and a bitcoin-qt executable will be built by default. @@ -150,10 +145,6 @@ libqrencode (optional) can be installed with: sudo dnf install qrencode-devel -protobuf (optional) can be installed with: - - sudo dnf install protobuf-devel - Notes ----- The release is built with GCC and then "strip bitcoind" to strip the debug @@ -163,8 +154,8 @@ symbols, which reduces the executable size by about 90%. miniupnpc --------- -[miniupnpc](http://miniupnp.free.fr/) may be used for UPnP port mapping. It can be downloaded from [here]( -http://miniupnp.tuxfamily.org/files/). UPnP support is compiled in and +[miniupnpc](https://miniupnp.tuxfamily.org) may be used for UPnP port mapping. It can be downloaded from [here]( +https://miniupnp.tuxfamily.org/files/). UPnP support is compiled in and turned off by default. See the configure options for upnp behavior desired: --without-miniupnpc No UPnP support miniupnp not required diff --git a/doc/build-windows.md b/doc/build-windows.md index 5ca9f98475..f8095f6a65 100644 --- a/doc/build-windows.md +++ b/doc/build-windows.md @@ -62,8 +62,7 @@ First, install the general dependencies: sudo apt install build-essential libtool autotools-dev automake pkg-config bsdmainutils curl git A host toolchain (`build-essential`) is necessary because some dependency -packages (such as `protobuf`) need to build host utilities that are used in the -build process. +packages need to build host utilities that are used in the build process. See [dependencies.md](dependencies.md) for a complete overview. diff --git a/doc/dependencies.md b/doc/dependencies.md index e5b4084d99..dc88626761 100644 --- a/doc/dependencies.md +++ b/doc/dependencies.md @@ -19,7 +19,6 @@ These are the dependencies currently used by Bitcoin Core. You can find instruct | MiniUPnPc | [2.0.20180203](http://miniupnp.free.fr/files) | | No | | | | OpenSSL | [1.0.1k](https://www.openssl.org/source) | | Yes | | | | PCRE | | | | | [Yes](https://github.com/bitcoin/bitcoin/blob/master/depends/packages/qt.mk) | -| protobuf | [2.6.1](https://github.com/google/protobuf/releases) | | No | | | | Python (tests) | | [3.5](https://www.python.org/downloads) | | | | | qrencode | [3.4.4](https://fukuchi.org/works/qrencode) | | No | | | | Qt | [5.9.7](https://download.qt.io/official_releases/qt/) | [5.5.1](https://github.com/bitcoin/bitcoin/issues/13478) | No | | | @@ -35,7 +34,6 @@ Some dependencies are not needed in all configurations. The following are some f #### Options passed to `./configure` * MiniUPnPc is not needed with `--with-miniupnpc=no`. * Berkeley DB is not needed with `--disable-wallet`. -* protobuf is only needed with `--enable-bip70`. * Qt is not needed with `--without-gui`. * If the qrencode dependency is absent, QR support won't be added. To force an error when that happens, pass `--with-qrencode`. * ZeroMQ is needed only with the `--with-zmq` option. diff --git a/doc/developer-notes.md b/doc/developer-notes.md index f4a5e2d330..9cf4b4b075 100644 --- a/doc/developer-notes.md +++ b/doc/developer-notes.md @@ -87,7 +87,6 @@ code. - `++i` is preferred over `i++`. - `nullptr` is preferred over `NULL` or `(void*)0`. - `static_assert` is preferred over `assert` where possible. Generally; compile-time checking is preferred over run-time checking. - - `enum class` is preferred over `enum` where possible. Scoped enumerations avoid two potential pitfalls/problems with traditional C++ enumerations: implicit conversions to int, and name clashes due to enumerators being exported to the surrounding scope. Block style example: ```c++ @@ -563,6 +562,34 @@ class A - *Rationale*: Easier to understand what is happening, thus easier to spot mistakes, even for those that are not language lawyers. +- Prefer `enum class` (scoped enumerations) over `enum` (traditional enumerations) where possible. + + - *Rationale*: Scoped enumerations avoid two potential pitfalls/problems with traditional C++ enumerations: implicit conversions to `int`, and name clashes due to enumerators being exported to the surrounding scope. + +- `switch` statement on an enumeration example: + +```cpp +enum class Tabs { + INFO, + CONSOLE, + GRAPH, + PEERS +}; + +int GetInt(Tabs tab) +{ + switch (tab) { + case Tabs::INFO: return 0; + case Tabs::CONSOLE: return 1; + case Tabs::GRAPH: return 2; + case Tabs::PEERS: return 3; + } // no default case, so the compiler can warn about missing cases + assert(false); +} +``` + +*Rationale*: The comment documents skipping `default:` label, and it complies with `clang-format` rules. The assertion prevents firing of `-Wreturn-type` warning on some compilers. + Strings and formatting ------------------------ diff --git a/doc/files.md b/doc/files.md index 85c27f3fd0..c2296b45fa 100644 --- a/doc/files.md +++ b/doc/files.md @@ -1,37 +1,102 @@ -Filename | Description ---------------------|---------------------------------------------------------------------------------------------------------------------------- -banlist.dat | stores the IPs/Subnets of banned nodes -bitcoin.conf | contains configuration settings for bitcoind or bitcoin-qt -bitcoind.pid | stores the process id of bitcoind while running -blocks/blk000??.dat | block data (custom, 128 MiB per file); since 0.8.0 -blocks/rev000??.dat | block undo data (custom); since 0.8.0 (format changed since pre-0.8) -blocks/index/* | block index (LevelDB); since 0.8.0 -chainstate/* | blockchain state database (LevelDB); since 0.8.0 -database/* | BDB database environment; only used for wallet since 0.8.0; moved to wallets/ directory on new installs since 0.16.0 -db.log | wallet database log file; moved to wallets/ directory on new installs since 0.16.0 -debug.log | contains debug information and general logging generated by bitcoind or bitcoin-qt -fee_estimates.dat | stores statistics used to estimate minimum transaction fees and priorities required for confirmation; since 0.10.0 -indexes/txindex/* | optional transaction index database (LevelDB); since 0.17.0 -mempool.dat | dump of the mempool's transactions; since 0.14.0 -peers.dat | peer IP address database (custom format); since 0.7.0 -wallet.dat | personal wallet (BDB) with keys and transactions; moved to wallets/ directory on new installs since 0.16.0 -wallets/database/* | BDB database environment; used for wallets since 0.16.0 -wallets/db.log | wallet database log file; since 0.16.0 -wallets/wallet.dat | personal wallet (BDB) with keys and transactions; since 0.16.0 -.cookie | session RPC authentication cookie (written at start when cookie authentication is used, deleted on shutdown): since 0.12.0 -onion_private_key | cached Tor hidden service private key for `-listenonion`: since 0.12.0 -guisettings.ini.bak | backup of former GUI settings after `-resetguisettings` is used - -Only used in pre-0.8.0 ---------------------- -* blktree/*; block chain index (LevelDB); since pre-0.8, replaced by blocks/index/* in 0.8.0 -* coins/*; unspent transaction output database (LevelDB); since pre-0.8, replaced by chainstate/* in 0.8.0 - -Only used before 0.8.0 ---------------------- -* blkindex.dat: block chain index database (BDB); replaced by {chainstate/*,blocks/index/*,blocks/rev000??.dat} in 0.8.0 -* blk000?.dat: block data (custom, 2 GiB per file); replaced by blocks/blk000??.dat in 0.8.0 - -Only used before 0.7.0 ---------------------- -* addr.dat: peer IP address database (BDB); replaced by peers.dat in 0.7.0 +# Bitcoin Core file system + +**Contents** + +- [Data directory location](#data-directory-location) + +- [Data directory layout](#data-directory-layout) + +- [Multi-wallet environment](#multi-wallet-environment) + +- [GUI settings](#gui-settings) + +- [Legacy subdirectories and files](#legacy-subdirectories-and-files) + +- [Notes](#notes) + +## Data directory location + +The data directory is the default location where the Bitcoin Core files are stored. + +1. The default data directory paths for supported platforms are: + +Platform | Data directory path +---------|-------------------- +Linux | `$HOME/.bitcoin/` +macOS | `$HOME/Library/Application Support/Bitcoin/` +Windows | `%APPDATA%\Bitcoin\` <sup>[\[1\]](#note1)</sup> + +2. The non-default data directory path can be specified by `-datadir` option. + +3. All content of the data directory, except for `bitcoin.conf` file, is chain-specific. This means the actual data directory paths for non-mainnet cases differ: + +Chain option | Data directory path +--------------------|-------------------- +no option (mainnet) | *path_to_datadir*`/` +`-testnet` | *path_to_datadir*`/testnet3/` +`-regtest` | *path_to_datadir*`/regtest/` + +## Data directory layout + +Subdirectory | File(s) | Description +-------------------|-----------------------|------------ +`blocks/` | | Blocks directory; can be specified by `-blocksdir` option (except for `blocks/index/`) +`blocks/index/` | LevelDB database | Block index; `-blocksdir` option does not affect this path +`blocks/` | `blkNNNNN.dat`<sup>[\[2\]](#note2)</sup> | Actual Bitcoin blocks (in network format, dumped in raw on disk, 128 MiB per file) +`blocks/` | `revNNNNN.dat`<sup>[\[2\]](#note2)</sup> | Block undo data (custom format) +`chainstate/` | LevelDB database | Blockchain state (a compact representation of all currently unspent transaction outputs and some metadata about the transactions they are from) +`indexes/txindex/` | LevelDB database | Transaction index; *optional*, used if `-txindex=1` +`indexes/blockfilter/basic/db/` | LevelDB database | Blockfilter index LevelDB database for the basic filtertype; *optional*, used if `-blockfilterindex=basic` +`indexes/blockfilter/basic/` | `fltrNNNNN.dat`<sup>[\[2\]](#note2)</sup> | Blockfilter index filters for the basic filtertype; *optional*, used if `-blockfilterindex=basic` +`wallets/` | | [Contains wallets](#multi-wallet-environment); can be specified by `-walletdir` option; if `wallets/` subdirectory does not exist, a wallet resides in the data directory +`./` | `banlist.dat` | Stores the IPs/subnets of banned nodes +`./` | `bitcoin.conf` | Contains [configuration settings](bitcoin-conf.md) for `bitcoind` or `bitcoin-qt`; can be specified by `-conf` option +`./` | `bitcoind.pid` | Stores the process ID (PID) of `bitcoind` or `bitcoin-qt` while running; created at start and deleted on shutdown; can be specified by `-pid` option +`./` | `debug.log` | Contains debug information and general logging generated by `bitcoind` or `bitcoin-qt`; can be specified by `-debuglogfile` option +`./` | `fee_estimates.dat` | Stores statistics used to estimate minimum transaction fees and priorities required for confirmation +`./` | `guisettings.ini.bak` | Backup of former [GUI settings](#gui-settings) after `-resetguisettings` option is used +`./` | `mempool.dat` | Dump of the mempool's transactions +`./` | `onion_private_key` | Cached Tor hidden service private key for `-listenonion` option +`./` | `peers.dat` | Peer IP address database (custom format) +`./` | `.cookie` | Session RPC authentication cookie; if used, created at start and deleted on shutdown; can be specified by `-rpccookiefile` option +`./` | `.lock` | Data directory lock file + +## Multi-wallet environment + +Wallets are Berkeley DB (BDB) databases: + +Subdirectory | File(s) | Description +-------------|-------------------|------------ +`database/` | BDB logging files | Part of BDB environment; created at start and deleted on shutdown; a user *must keep it as safe* as personal wallet `wallet.dat` +`./` | `db.log` | BDB error file +`./` | `wallet.dat` | Personal wallet (BDB) with keys and transactions +`./` | `.walletlock` | Wallet lock file + +1. Each user-defined wallet named "wallet_name" resides in `wallets/wallet_name/` subdirectory. + +2. The default (unnamed) wallet resides in `wallets/` subdirectory; if the latter does not exist, the wallet resides in the data directory. + +3. A wallet database path can be specified by `-wallet` option. + +## GUI settings + +`bitcoin-qt` uses [`QSettings`](https://doc.qt.io/qt-5/qsettings.html) class; this implies platform-specific [locations where application settings are stored](https://doc.qt.io/qt-5/qsettings.html#locations-where-application-settings-are-stored). + +## Legacy subdirectories and files + +These subdirectories and files are no longer used by the Bitcoin Core: + +Path | Description | Repository notes +---------------|-------------|----------------- +`blktree/` | Blockchain index; replaced by `blocks/index/` in [0.8.0](https://github.com/bitcoin/bitcoin/blob/master/doc/release-notes/release-notes-0.8.0.md#improvements) | [PR #2231](https://github.com/bitcoin/bitcoin/pull/2231), [`8fdc94cc`](https://github.com/bitcoin/bitcoin/commit/8fdc94cc8f0341e96b1edb3a5b56811c0b20bd15) +`coins/` | Unspent transaction output database; replaced by `chainstate/` in 0.8.0 | [PR #2231](https://github.com/bitcoin/bitcoin/pull/2231), [`8fdc94cc`](https://github.com/bitcoin/bitcoin/commit/8fdc94cc8f0341e96b1edb3a5b56811c0b20bd15) +`blkindex.dat` | Blockchain index BDB database; replaced by {`chainstate/`, `blocks/index/`, `blocks/revNNNNN.dat`<sup>[\[2\]](#note2)</sup>} in 0.8.0 | [PR #1677](https://github.com/bitcoin/bitcoin/pull/1677) +`blk000?.dat` | Block data (custom format, 2 GiB per file); replaced by `blocks/blkNNNNN.dat`<sup>[\[2\]](#note2)</sup> in 0.8.0 | [PR #1677](https://github.com/bitcoin/bitcoin/pull/1677) +`addr.dat` | Peer IP address BDB database; replaced by `peers.dat` in [0.7.0](https://github.com/bitcoin/bitcoin/blob/master/doc/release-notes/release-notes-0.7.0.md) | [PR #1198](https://github.com/bitcoin/bitcoin/pull/1198), [`928d3a01`](https://github.com/bitcoin/bitcoin/commit/928d3a011cc66c7f907c4d053f674ea77dc611cc) + +## Notes + +<a name="note1">1</a>. The `/` (slash, U+002F) is used as the platform-independent path component separator in this paper. + +<a name="note2">2</a>. `NNNNN` matches `[0-9]{5}` regex. + diff --git a/doc/release-notes-15437.md b/doc/release-notes-15437.md index 031e90ccd2..6614207757 100644 --- a/doc/release-notes-15437.md +++ b/doc/release-notes-15437.md @@ -32,3 +32,22 @@ Please use the recommended alternatives if you rely on this deprecated feature: could wait until the transaction has confirmed (taking into account the fee target they set (compare the RPC `estimatesmartfee`)) or listen for the transaction announcement by other network peers to check for propagation. + +The removal of BIP61 REJECT message support also has the following minor RPC +and logging implications: + +* `testmempoolaccept` and `sendrawtransaction` no longer return the P2P REJECT + code when a transaction is not accepted to the mempool. They still return the + verbal reject reason. + +* Log messages that previously reported the REJECT code when a transaction was + not accepted to the mempool now no longer report the REJECT code. The reason + for rejection is still reported. + +Updated RPCs +------------ + +- `testmempoolaccept` and `sendrawtransaction` no longer return the P2P REJECT + code when a transaction is not accepted to the mempool. See the Section + _Removal of reject network messages from Bitcoin Core (BIP61)_ for details on + the removal of BIP61 REJECT message support. diff --git a/share/qt/Info.plist.in b/share/qt/Info.plist.in index 477985bb33..ffa001bb7f 100644 --- a/share/qt/Info.plist.in +++ b/share/qt/Info.plist.in @@ -54,43 +54,6 @@ </dict> </array> - <key>UTExportedTypeDeclarations</key> - <array> - <dict> - <key>UTTypeIdentifier</key> - <string>org.bitcoin.paymentrequest</string> - <key>UTTypeDescription</key> - <string>Bitcoin payment request</string> - <key>UTTypeConformsTo</key> - <array> - <string>public.data</string> - </array> - <key>UTTypeTagSpecification</key> - <dict> - <key>public.mime-type</key> - <string>application/x-bitcoin-payment-request</string> - <key>public.filename-extension</key> - <array> - <string>bitcoinpaymentrequest</string> - </array> - </dict> - </dict> - </array> - - <key>CFBundleDocumentTypes</key> - <array> - <dict> - <key>CFBundleTypeRole</key> - <string>Editor</string> - <key>LSItemContentTypes</key> - <array> - <string>org.bitcoin.paymentrequest</string> - </array> - <key>LSHandlerRank</key> - <string>Owner</string> - </dict> - </array> - <key>NSPrincipalClass</key> <string>NSApplication</string> diff --git a/src/.clang-format b/src/.clang-format index 38e19edf2c..aae039dd77 100644 --- a/src/.clang-format +++ b/src/.clang-format @@ -5,6 +5,7 @@ AlignEscapedNewlinesLeft: true AlignTrailingComments: true AllowAllParametersOfDeclarationOnNextLine: false AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: true AllowShortFunctionsOnASingleLine: All AllowShortIfStatementsOnASingleLine: true AllowShortLoopsOnASingleLine: false diff --git a/src/Makefile.am b/src/Makefile.am index eec84122ae..82cc19d57c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -19,7 +19,7 @@ else LIBUNIVALUE = $(UNIVALUE_LIBS) endif -BITCOIN_INCLUDES=-I$(builddir) $(BDB_CPPFLAGS) $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS) $(CRYPTO_CFLAGS) $(SSL_CFLAGS) +BITCOIN_INCLUDES=-I$(builddir) $(BDB_CPPFLAGS) $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS) $(CRYPTO_CFLAGS) BITCOIN_INCLUDES += -I$(srcdir)/secp256k1/include BITCOIN_INCLUDES += $(UNIVALUE_CFLAGS) @@ -206,6 +206,7 @@ BITCOIN_CORE_H = \ undo.h \ util/bip32.h \ util/bytevectorhash.h \ + util/check.h \ util/error.h \ util/fees.h \ util/spanparsing.h \ @@ -220,6 +221,7 @@ BITCOIN_CORE_H = \ util/translation.h \ util/url.h \ util/validation.h \ + util/vector.h \ validation.h \ validationinterface.h \ versionbits.h \ @@ -700,12 +702,6 @@ if HARDEN $(AM_V_at) READELF=$(READELF) OBJDUMP=$(OBJDUMP) $(PYTHON) $(top_srcdir)/contrib/devtools/security-check.py < $(bin_PROGRAMS) endif -if ENABLE_BIP70 -%.pb.cc %.pb.h: %.proto - @test -f $(PROTOC) - $(AM_V_GEN) $(PROTOC) --cpp_out=$(@D) --proto_path=$(<D) $< -endif - if EMBEDDED_LEVELDB include Makefile.leveldb.include endif diff --git a/src/Makefile.bench.include b/src/Makefile.bench.include index e421b377a0..38143e32b9 100644 --- a/src/Makefile.bench.include +++ b/src/Makefile.bench.include @@ -39,6 +39,8 @@ bench_bench_bitcoin_SOURCES = \ bench/lockedpool.cpp \ bench/poly1305.cpp \ bench/prevector.cpp \ + test/lib/transaction_utils.h \ + test/lib/transaction_utils.cpp \ test/setup_common.h \ test/setup_common.cpp \ test/util.h \ diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index 9ab7f02e22..13b1470b58 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -95,16 +95,6 @@ QT_QRC = qt/bitcoin.qrc QT_QRC_LOCALE_CPP = qt/qrc_bitcoin_locale.cpp QT_QRC_LOCALE = qt/bitcoin_locale.qrc -if ENABLE_BIP70 -PROTOBUF_CC = qt/paymentrequest.pb.cc -PROTOBUF_H = qt/paymentrequest.pb.h -PROTOBUF_PROTO = qt/paymentrequest.proto -else -PROTOBUF_CC = -PROTOBUF_H = -PROTOBUF_PROTO = -endif - BITCOIN_QT_H = \ qt/addressbookpage.h \ qt/addresstablemodel.h \ @@ -134,7 +124,6 @@ BITCOIN_QT_H = \ qt/optionsdialog.h \ qt/optionsmodel.h \ qt/overviewpage.h \ - qt/paymentrequestplus.h \ qt/paymentserver.h \ qt/peertablemodel.h \ qt/platformstyle.h \ @@ -269,18 +258,12 @@ BITCOIN_QT_WALLET_CPP = \ qt/walletmodeltransaction.cpp \ qt/walletview.cpp -BITCOIN_QT_WALLET_BIP70_CPP = \ - qt/paymentrequestplus.cpp - BITCOIN_QT_CPP = $(BITCOIN_QT_BASE_CPP) if TARGET_WINDOWS BITCOIN_QT_CPP += $(BITCOIN_QT_WINDOWS_CPP) endif if ENABLE_WALLET BITCOIN_QT_CPP += $(BITCOIN_QT_WALLET_CPP) -if ENABLE_BIP70 -BITCOIN_QT_CPP += $(BITCOIN_QT_WALLET_BIP70_CPP) -endif # ENABLE_BIP70 endif # ENABLE_WALLET RES_IMAGES = @@ -292,18 +275,17 @@ BITCOIN_RC = qt/res/bitcoin-qt-res.rc BITCOIN_QT_INCLUDES = -DQT_NO_KEYWORDS qt_libbitcoinqt_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(BITCOIN_QT_INCLUDES) \ - $(QT_INCLUDES) $(QT_DBUS_INCLUDES) $(PROTOBUF_CFLAGS) $(QR_CFLAGS) + $(QT_INCLUDES) $(QT_DBUS_INCLUDES) $(QR_CFLAGS) qt_libbitcoinqt_a_CXXFLAGS = $(AM_CXXFLAGS) $(QT_PIE_FLAGS) qt_libbitcoinqt_a_OBJCXXFLAGS = $(AM_OBJCXXFLAGS) $(QT_PIE_FLAGS) qt_libbitcoinqt_a_SOURCES = $(BITCOIN_QT_CPP) $(BITCOIN_QT_H) $(QT_FORMS_UI) \ - $(QT_QRC) $(QT_QRC_LOCALE) $(QT_TS) $(PROTOBUF_PROTO) $(RES_ICONS) $(RES_IMAGES) $(RES_MOVIES) + $(QT_QRC) $(QT_QRC_LOCALE) $(QT_TS) $(RES_ICONS) $(RES_IMAGES) $(RES_MOVIES) if TARGET_DARWIN qt_libbitcoinqt_a_SOURCES += $(BITCOIN_MM) endif -nodist_qt_libbitcoinqt_a_SOURCES = $(QT_MOC_CPP) $(QT_MOC) $(PROTOBUF_CC) \ - $(PROTOBUF_H) $(QT_QRC_CPP) $(QT_QRC_LOCALE_CPP) +nodist_qt_libbitcoinqt_a_SOURCES = $(QT_MOC_CPP) $(QT_MOC) $(QT_QRC_CPP) $(QT_QRC_LOCALE_CPP) # forms/foo.h -> forms/ui_foo.h QT_FORMS_H=$(join $(dir $(QT_FORMS_UI)),$(addprefix ui_, $(notdir $(QT_FORMS_UI:.ui=.h)))) @@ -313,14 +295,9 @@ QT_FORMS_H=$(join $(dir $(QT_FORMS_UI)),$(addprefix ui_, $(notdir $(QT_FORMS_UI: $(QT_MOC): $(QT_FORMS_H) $(qt_libbitcoinqt_a_OBJECTS) $(qt_bitcoin_qt_OBJECTS) : | $(QT_MOC) -#Generating these with a half-written protobuf header leads to wacky results. -#This makes sure it's done. -$(QT_MOC): $(PROTOBUF_H) -$(QT_MOC_CPP): $(PROTOBUF_H) - # bitcoin-qt binary # qt_bitcoin_qt_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(BITCOIN_QT_INCLUDES) \ - $(QT_INCLUDES) $(PROTOBUF_CFLAGS) $(QR_CFLAGS) + $(QT_INCLUDES) $(QR_CFLAGS) qt_bitcoin_qt_CXXFLAGS = $(AM_CXXFLAGS) $(QT_PIE_FLAGS) qt_bitcoin_qt_SOURCES = qt/main.cpp @@ -335,15 +312,8 @@ if ENABLE_ZMQ qt_bitcoin_qt_LDADD += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS) endif qt_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) $(PROTOBUF_LIBS) $(BDB_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1) \ + $(BOOST_LIBS) $(QT_LIBS) $(QT_DBUS_LIBS) $(QR_LIBS) $(BDB_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1) \ $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) -if ENABLE_BIP70 -qt_bitcoin_qt_LDADD += $(SSL_LIBS) -else -if TARGET_WINDOWS -qt_bitcoin_qt_LDADD += $(SSL_LIBS) -endif -endif qt_bitcoin_qt_LDADD += $(CRYPTO_LIBS) qt_bitcoin_qt_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) qt_bitcoin_qt_LIBTOOLFLAGS = $(AM_LIBTOOLFLAGS) --tag CXX @@ -368,7 +338,7 @@ $(QT_QRC_LOCALE_CPP): $(QT_QRC_LOCALE) $(QT_QM) $(SED) -e '/^\*\*.*Created:/d' -e '/^\*\*.*by:/d' > $@ @rm $(@D)/temp_$(<F) -$(QT_QRC_CPP): $(QT_QRC) $(QT_FORMS_H) $(RES_ICONS) $(RES_IMAGES) $(RES_MOVIES) $(PROTOBUF_H) +$(QT_QRC_CPP): $(QT_QRC) $(QT_FORMS_H) $(RES_ICONS) $(RES_IMAGES) $(RES_MOVIES) @test -f $(RCC) $(AM_V_GEN) QT_SELECT=$(QT_SELECT) $(RCC) -name bitcoin $< | \ $(SED) -e '/^\*\*.*Created:/d' -e '/^\*\*.*by:/d' > $@ diff --git a/src/Makefile.qttest.include b/src/Makefile.qttest.include index 4acfff809e..c309340fd7 100644 --- a/src/Makefile.qttest.include +++ b/src/Makefile.qttest.include @@ -15,10 +15,6 @@ if ENABLE_WALLET TEST_QT_MOC_CPP += \ qt/test/moc_addressbooktests.cpp \ qt/test/moc_wallettests.cpp -if ENABLE_BIP70 -TEST_QT_MOC_CPP += \ - qt/test/moc_paymentservertests.cpp -endif # ENABLE_BIP70 endif # ENABLE_WALLET TEST_QT_H = \ @@ -28,8 +24,6 @@ TEST_QT_H = \ qt/test/rpcnestedtests.h \ qt/test/uritests.h \ qt/test/util.h \ - qt/test/paymentrequestdata.h \ - qt/test/paymentservertests.h \ qt/test/wallettests.h TEST_BITCOIN_CPP = \ @@ -39,7 +33,7 @@ TEST_BITCOIN_H = \ test/setup_common.h qt_test_test_bitcoin_qt_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(BITCOIN_QT_INCLUDES) \ - $(QT_INCLUDES) $(QT_TEST_INCLUDES) $(PROTOBUF_CFLAGS) + $(QT_INCLUDES) $(QT_TEST_INCLUDES) qt_test_test_bitcoin_qt_SOURCES = \ qt/test/apptests.cpp \ @@ -56,10 +50,6 @@ qt_test_test_bitcoin_qt_SOURCES += \ qt/test/addressbooktests.cpp \ qt/test/wallettests.cpp \ wallet/test/wallet_test_fixture.cpp -if ENABLE_BIP70 -qt_test_test_bitcoin_qt_SOURCES += \ - qt/test/paymentservertests.cpp -endif # ENABLE_BIP70 endif # ENABLE_WALLET nodist_qt_test_test_bitcoin_qt_SOURCES = $(TEST_QT_MOC_CPP) @@ -73,7 +63,7 @@ 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_DBUS_LIBS) $(QT_TEST_LIBS) $(QT_LIBS) \ - $(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1) \ + $(QR_LIBS) $(BDB_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1) \ $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) qt_test_test_bitcoin_qt_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) qt_test_test_bitcoin_qt_CXXFLAGS = $(AM_CXXFLAGS) $(QT_PIE_FLAGS) diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 48df50d100..019e832cc6 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -16,12 +16,16 @@ FUZZ_TARGETS = \ test/fuzz/blockundo_deserialize \ test/fuzz/bloomfilter_deserialize \ test/fuzz/coins_deserialize \ + test/fuzz/descriptor_parse \ test/fuzz/diskblockindex_deserialize \ + test/fuzz/eval_script \ test/fuzz/inv_deserialize \ test/fuzz/messageheader_deserialize \ test/fuzz/netaddr_deserialize \ + test/fuzz/script \ test/fuzz/script_flags \ test/fuzz/service_deserialize \ + test/fuzz/spanparsing \ test/fuzz/transaction \ test/fuzz/txoutcompressor_deserialize \ test/fuzz/txundo_deserialize @@ -51,6 +55,8 @@ RAW_TEST_FILES = GENERATED_TEST_FILES = $(JSON_TEST_FILES:.json=.json.h) $(RAW_TEST_FILES:.raw=.raw.h) BITCOIN_TEST_SUITE = \ + test/lib/transaction_utils.h \ + test/lib/transaction_utils.cpp \ test/main.cpp \ test/setup_common.h \ test/setup_common.cpp @@ -59,7 +65,8 @@ FUZZ_SUITE = \ test/setup_common.h \ test/setup_common.cpp \ test/fuzz/fuzz.cpp \ - test/fuzz/fuzz.h + test/fuzz/fuzz.h \ + test/fuzz/FuzzedDataProvider.h FUZZ_SUITE_LD_COMMON = \ $(LIBBITCOIN_SERVER) \ @@ -250,12 +257,24 @@ test_fuzz_coins_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) test_fuzz_coins_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) test_fuzz_coins_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON) +test_fuzz_descriptor_parse_SOURCES = $(FUZZ_SUITE) test/fuzz/descriptor_parse.cpp +test_fuzz_descriptor_parse_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) +test_fuzz_descriptor_parse_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) +test_fuzz_descriptor_parse_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) +test_fuzz_descriptor_parse_LDADD = $(FUZZ_SUITE_LD_COMMON) + test_fuzz_netaddr_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp test_fuzz_netaddr_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DNETADDR_DESERIALIZE=1 test_fuzz_netaddr_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) test_fuzz_netaddr_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) test_fuzz_netaddr_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON) +test_fuzz_script_SOURCES = $(FUZZ_SUITE) test/fuzz/script.cpp +test_fuzz_script_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) +test_fuzz_script_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) +test_fuzz_script_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) +test_fuzz_script_LDADD = $(FUZZ_SUITE_LD_COMMON) + test_fuzz_script_flags_SOURCES = $(FUZZ_SUITE) test/fuzz/script_flags.cpp test_fuzz_script_flags_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) test_fuzz_script_flags_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) @@ -268,6 +287,12 @@ test_fuzz_service_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) test_fuzz_service_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) test_fuzz_service_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON) +test_fuzz_spanparsing_SOURCES = $(FUZZ_SUITE) test/fuzz/spanparsing.cpp +test_fuzz_spanparsing_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) +test_fuzz_spanparsing_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) +test_fuzz_spanparsing_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) +test_fuzz_spanparsing_LDADD = $(FUZZ_SUITE_LD_COMMON) + test_fuzz_messageheader_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp test_fuzz_messageheader_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGEHEADER_DESERIALIZE=1 test_fuzz_messageheader_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) @@ -298,6 +323,12 @@ test_fuzz_diskblockindex_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) test_fuzz_diskblockindex_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) test_fuzz_diskblockindex_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON) +test_fuzz_eval_script_SOURCES = $(FUZZ_SUITE) test/fuzz/eval_script.cpp +test_fuzz_eval_script_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) +test_fuzz_eval_script_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) +test_fuzz_eval_script_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) +test_fuzz_eval_script_LDADD = $(FUZZ_SUITE_LD_COMMON) + test_fuzz_txoutcompressor_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp test_fuzz_txoutcompressor_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DTXOUTCOMPRESSOR_DESERIALIZE=1 test_fuzz_txoutcompressor_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) diff --git a/src/arith_uint256.cpp b/src/arith_uint256.cpp index be145a0e63..1111f27771 100644 --- a/src/arith_uint256.cpp +++ b/src/arith_uint256.cpp @@ -8,8 +8,6 @@ #include <uint256.h> #include <crypto/common.h> -#include <stdio.h> -#include <string.h> template <unsigned int BITS> base_uint<BITS>::base_uint(const std::string& str) diff --git a/src/arith_uint256.h b/src/arith_uint256.h index bd0360087d..171135b01f 100644 --- a/src/arith_uint256.h +++ b/src/arith_uint256.h @@ -6,13 +6,11 @@ #ifndef BITCOIN_ARITH_UINT256_H #define BITCOIN_ARITH_UINT256_H -#include <assert.h> #include <cstring> #include <limits> #include <stdexcept> #include <stdint.h> #include <string> -#include <vector> class uint256; diff --git a/src/bech32.cpp b/src/bech32.cpp index 4c966350b4..1e0471f110 100644 --- a/src/bech32.cpp +++ b/src/bech32.cpp @@ -3,6 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <bech32.h> +#include <util/vector.h> #include <assert.h> @@ -26,13 +27,6 @@ const int8_t CHARSET_REV[128] = { 1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, -1, -1 }; -/** Concatenate two byte arrays. */ -data Cat(data x, const data& y) -{ - x.insert(x.end(), y.begin(), y.end()); - return x; -} - /** This function will compute what 6 5-bit values to XOR into the last 6 input values, in order to * make the checksum 0. These 6 values are packed together in a single 30-bit integer. The higher * bits correspond to earlier values. */ diff --git a/src/bench/base58.cpp b/src/bench/base58.cpp index 0f4b52cf79..40a7b5e320 100644 --- a/src/bench/base58.cpp +++ b/src/bench/base58.cpp @@ -8,7 +8,6 @@ #include <array> #include <vector> -#include <string> static void Base58Encode(benchmark::State& state) diff --git a/src/bench/bench.h b/src/bench/bench.h index 35eeab3393..3a8c487b9a 100644 --- a/src/bench/bench.h +++ b/src/bench/bench.h @@ -6,7 +6,6 @@ #define BITCOIN_BENCH_BENCH_H #include <functional> -#include <limits> #include <map> #include <string> #include <vector> diff --git a/src/bench/bench_bitcoin.cpp b/src/bench/bench_bitcoin.cpp index d0d7c03ee1..655a5a3459 100644 --- a/src/bench/bench_bitcoin.cpp +++ b/src/bench/bench_bitcoin.cpp @@ -51,6 +51,13 @@ int main(int argc, char** argv) std::string scaling_str = gArgs.GetArg("-scaling", DEFAULT_BENCH_SCALING); bool is_list_only = gArgs.GetBoolArg("-list", false); + if (evaluations == 0) { + return EXIT_SUCCESS; + } else if (evaluations < 0) { + tfm::format(std::cerr, "Error parsing evaluations argument: %d\n", evaluations); + return EXIT_FAILURE; + } + double scaling_factor; if (!ParseDouble(scaling_str, &scaling_factor)) { tfm::format(std::cerr, "Error parsing scaling factor as double: %s\n", scaling_str.c_str()); diff --git a/src/bench/block_assemble.cpp b/src/bench/block_assemble.cpp index fb33c09ab2..157f936a95 100644 --- a/src/bench/block_assemble.cpp +++ b/src/bench/block_assemble.cpp @@ -10,7 +10,6 @@ #include <validation.h> -#include <list> #include <vector> static void AssembleBlock(benchmark::State& state) diff --git a/src/bench/chacha20.cpp b/src/bench/chacha20.cpp index 030067aca5..f1b0a9a989 100644 --- a/src/bench/chacha20.cpp +++ b/src/bench/chacha20.cpp @@ -2,7 +2,6 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include <iostream> #include <bench/bench.h> #include <crypto/chacha20.h> diff --git a/src/bench/chacha_poly_aead.cpp b/src/bench/chacha_poly_aead.cpp index f5f7297490..a02a5315a4 100644 --- a/src/bench/chacha_poly_aead.cpp +++ b/src/bench/chacha_poly_aead.cpp @@ -2,7 +2,6 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include <iostream> #include <bench/bench.h> #include <crypto/chacha_poly_aead.h> diff --git a/src/bench/crypto_hash.cpp b/src/bench/crypto_hash.cpp index fb2bab9dee..674753c191 100644 --- a/src/bench/crypto_hash.cpp +++ b/src/bench/crypto_hash.cpp @@ -2,7 +2,6 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include <iostream> #include <bench/bench.h> #include <hash.h> diff --git a/src/bench/duplicate_inputs.cpp b/src/bench/duplicate_inputs.cpp index 2440341287..6cfa3750d6 100644 --- a/src/bench/duplicate_inputs.cpp +++ b/src/bench/duplicate_inputs.cpp @@ -4,15 +4,12 @@ #include <bench/bench.h> #include <chainparams.h> -#include <coins.h> #include <consensus/merkle.h> #include <consensus/validation.h> #include <pow.h> #include <txmempool.h> #include <validation.h> -#include <list> -#include <vector> static void DuplicateInputs(benchmark::State& state) diff --git a/src/bench/lockedpool.cpp b/src/bench/lockedpool.cpp index 0712eab4bc..0d9b123400 100644 --- a/src/bench/lockedpool.cpp +++ b/src/bench/lockedpool.cpp @@ -6,7 +6,6 @@ #include <support/lockedpool.h> -#include <iostream> #include <vector> #define ASIZE 2048 diff --git a/src/bench/mempool_eviction.cpp b/src/bench/mempool_eviction.cpp index ac8a182358..a2a21c673b 100644 --- a/src/bench/mempool_eviction.cpp +++ b/src/bench/mempool_eviction.cpp @@ -6,8 +6,6 @@ #include <policy/policy.h> #include <txmempool.h> -#include <list> -#include <vector> static void AddTx(const CTransactionRef& tx, const CAmount& nFee, CTxMemPool& pool) EXCLUSIVE_LOCKS_REQUIRED(cs_main, pool.cs) { diff --git a/src/bench/poly1305.cpp b/src/bench/poly1305.cpp index 16342d0fbe..02e5fecc0d 100644 --- a/src/bench/poly1305.cpp +++ b/src/bench/poly1305.cpp @@ -2,7 +2,6 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include <iostream> #include <bench/bench.h> #include <crypto/poly1305.h> diff --git a/src/bench/rollingbloom.cpp b/src/bench/rollingbloom.cpp index 4016530dac..cffdb388f8 100644 --- a/src/bench/rollingbloom.cpp +++ b/src/bench/rollingbloom.cpp @@ -2,7 +2,6 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include <iostream> #include <bench/bench.h> #include <bloom.h> diff --git a/src/bench/rpc_blockchain.cpp b/src/bench/rpc_blockchain.cpp index 29e448fc43..2fc6f116a4 100644 --- a/src/bench/rpc_blockchain.cpp +++ b/src/bench/rpc_blockchain.cpp @@ -7,7 +7,6 @@ #include <validation.h> #include <streams.h> -#include <consensus/validation.h> #include <rpc/blockchain.h> #include <univalue.h> diff --git a/src/bench/rpc_mempool.cpp b/src/bench/rpc_mempool.cpp index b35a744055..bf63cccf09 100644 --- a/src/bench/rpc_mempool.cpp +++ b/src/bench/rpc_mempool.cpp @@ -8,8 +8,6 @@ #include <univalue.h> -#include <list> -#include <vector> static void AddTx(const CTransactionRef& tx, const CAmount& fee, CTxMemPool& pool) EXCLUSIVE_LOCKS_REQUIRED(cs_main, pool.cs) { diff --git a/src/bench/verify_script.cpp b/src/bench/verify_script.cpp index 4891c57b3a..c9947f192e 100644 --- a/src/bench/verify_script.cpp +++ b/src/bench/verify_script.cpp @@ -10,44 +10,10 @@ #include <script/script.h> #include <script/standard.h> #include <streams.h> +#include <test/lib/transaction_utils.h> #include <array> -// FIXME: Dedup with BuildCreditingTransaction in test/script_tests.cpp. -static CMutableTransaction BuildCreditingTransaction(const CScript& scriptPubKey) -{ - CMutableTransaction txCredit; - txCredit.nVersion = 1; - txCredit.nLockTime = 0; - txCredit.vin.resize(1); - txCredit.vout.resize(1); - txCredit.vin[0].prevout.SetNull(); - txCredit.vin[0].scriptSig = CScript() << CScriptNum(0) << CScriptNum(0); - txCredit.vin[0].nSequence = CTxIn::SEQUENCE_FINAL; - txCredit.vout[0].scriptPubKey = scriptPubKey; - txCredit.vout[0].nValue = 1; - - return txCredit; -} - -// FIXME: Dedup with BuildSpendingTransaction in test/script_tests.cpp. -static CMutableTransaction BuildSpendingTransaction(const CScript& scriptSig, const CMutableTransaction& txCredit) -{ - CMutableTransaction txSpend; - txSpend.nVersion = 1; - txSpend.nLockTime = 0; - txSpend.vin.resize(1); - txSpend.vout.resize(1); - txSpend.vin[0].prevout.hash = txCredit.GetHash(); - txSpend.vin[0].prevout.n = 0; - txSpend.vin[0].scriptSig = scriptSig; - txSpend.vin[0].nSequence = CTxIn::SEQUENCE_FINAL; - txSpend.vout[0].scriptPubKey = CScript(); - txSpend.vout[0].nValue = txCredit.vout[0].nValue; - - return txSpend; -} - // Microbenchmark for verification of a basic P2WPKH script. Can be easily // modified to measure performance of other types of scripts. static void VerifyScriptBench(benchmark::State& state) @@ -71,8 +37,8 @@ static void VerifyScriptBench(benchmark::State& state) CScript scriptPubKey = CScript() << witnessversion << ToByteVector(pubkeyHash); CScript scriptSig; CScript witScriptPubkey = CScript() << OP_DUP << OP_HASH160 << ToByteVector(pubkeyHash) << OP_EQUALVERIFY << OP_CHECKSIG; - const CMutableTransaction& txCredit = BuildCreditingTransaction(scriptPubKey); - CMutableTransaction txSpend = BuildSpendingTransaction(scriptSig, txCredit); + const CMutableTransaction& txCredit = BuildCreditingTransaction(scriptPubKey, 1); + CMutableTransaction txSpend = BuildSpendingTransaction(scriptSig, CScriptWitness(), CTransaction(txCredit)); CScriptWitness& witness = txSpend.vin[0].scriptWitness; witness.stack.emplace_back(); key.Sign(SignatureHash(witScriptPubkey, txSpend, 0, SIGHASH_ALL, txCredit.vout[0].nValue, SigVersion::WITNESS_V0), witness.stack.back()); diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp index 73773c4ec5..93b7a7152c 100644 --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -9,7 +9,6 @@ #include <chainparamsbase.h> #include <clientversion.h> -#include <fs.h> #include <rpc/client.h> #include <rpc/protocol.h> #include <rpc/request.h> @@ -316,7 +315,20 @@ static UniValue CallRPC(BaseRequestHandler *rh, const std::string& strMethod, co // Synchronously look up hostname raii_evhttp_connection evcon = obtain_evhttp_connection_base(base.get(), host, port); - evhttp_connection_set_timeout(evcon.get(), gArgs.GetArg("-rpcclienttimeout", DEFAULT_HTTP_CLIENT_TIMEOUT)); + + // Set connection timeout + { + const int timeout = gArgs.GetArg("-rpcclienttimeout", DEFAULT_HTTP_CLIENT_TIMEOUT); + if (timeout > 0) { + evhttp_connection_set_timeout(evcon.get(), timeout); + } else { + // Indefinite request timeouts are not possible in libevent-http, so we + // set the timeout to a very long time period instead. + + constexpr int YEAR_IN_SECONDS = 31556952; // Average length of year in Gregorian calendar + evhttp_connection_set_timeout(evcon.get(), 5 * YEAR_IN_SECONDS); + } + } HTTPReply response; raii_evhttp_request req = obtain_evhttp_request(http_request_done, (void*)&response); diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index 88219f0d0f..cabea610f3 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -11,7 +11,6 @@ #include <consensus/consensus.h> #include <core_io.h> #include <key_io.h> -#include <policy/policy.h> #include <policy/rbf.h> #include <primitives/transaction.h> #include <script/script.h> diff --git a/src/bitcoin-wallet.cpp b/src/bitcoin-wallet.cpp index eb7f0098ec..eda4f8ce78 100644 --- a/src/bitcoin-wallet.cpp +++ b/src/bitcoin-wallet.cpp @@ -9,13 +9,11 @@ #include <chainparams.h> #include <chainparamsbase.h> #include <logging.h> -#include <util/strencodings.h> #include <util/system.h> #include <util/translation.h> #include <wallet/wallettool.h> #include <functional> -#include <stdio.h> const std::function<std::string(const char*)> G_TRANSLATION_FUN = nullptr; diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp index 17989a4214..ddd6f8839c 100644 --- a/src/bitcoind.cpp +++ b/src/bitcoind.cpp @@ -10,7 +10,6 @@ #include <chainparams.h> #include <clientversion.h> #include <compat.h> -#include <fs.h> #include <init.h> #include <interfaces/chain.h> #include <noui.h> diff --git a/src/blockencodings.h b/src/blockencodings.h index 0c2b83ebcf..18a6e35f31 100644 --- a/src/blockencodings.h +++ b/src/blockencodings.h @@ -7,7 +7,6 @@ #include <primitives/block.h> -#include <memory> class CTxMemPool; diff --git a/src/chain.h b/src/chain.h index 1b67ebbe41..321bc95dbc 100644 --- a/src/chain.h +++ b/src/chain.h @@ -140,91 +140,65 @@ class CBlockIndex { public: //! pointer to the hash of the block, if any. Memory is owned by this CBlockIndex - const uint256* phashBlock; + const uint256* phashBlock{nullptr}; //! pointer to the index of the predecessor of this block - CBlockIndex* pprev; + CBlockIndex* pprev{nullptr}; //! pointer to the index of some further predecessor of this block - CBlockIndex* pskip; + CBlockIndex* pskip{nullptr}; //! height of the entry in the chain. The genesis block has height 0 - int nHeight; + int nHeight{0}; //! Which # file this block is stored in (blk?????.dat) - int nFile; + int nFile{0}; //! Byte offset within blk?????.dat where this block's data is stored - unsigned int nDataPos; + unsigned int nDataPos{0}; //! Byte offset within rev?????.dat where this block's undo data is stored - unsigned int nUndoPos; + unsigned int nUndoPos{0}; //! (memory only) Total amount of work (expected number of hashes) in the chain up to and including this block - arith_uint256 nChainWork; + arith_uint256 nChainWork{}; //! Number of transactions in this block. //! Note: in a potential headers-first mode, this number cannot be relied upon - unsigned int nTx; + unsigned int nTx{0}; //! (memory only) Number of transactions in the chain up to and including this block. //! This value will be non-zero only if and only if transactions for this block and all its parents are available. //! Change to 64-bit type when necessary; won't happen before 2030 - unsigned int nChainTx; + unsigned int nChainTx{0}; //! Verification status of this block. See enum BlockStatus - uint32_t nStatus; + uint32_t nStatus{0}; //! block header - int32_t nVersion; - uint256 hashMerkleRoot; - uint32_t nTime; - uint32_t nBits; - uint32_t nNonce; + int32_t nVersion{0}; + uint256 hashMerkleRoot{}; + uint32_t nTime{0}; + uint32_t nBits{0}; + uint32_t nNonce{0}; //! (memory only) Sequential id assigned to distinguish order in which blocks are received. - int32_t nSequenceId; + int32_t nSequenceId{0}; //! (memory only) Maximum nTime in the chain up to and including this block. - unsigned int nTimeMax; - - void SetNull() - { - phashBlock = nullptr; - pprev = nullptr; - pskip = nullptr; - nHeight = 0; - nFile = 0; - nDataPos = 0; - nUndoPos = 0; - nChainWork = arith_uint256(); - nTx = 0; - nChainTx = 0; - nStatus = 0; - nSequenceId = 0; - nTimeMax = 0; - - nVersion = 0; - hashMerkleRoot = uint256(); - nTime = 0; - nBits = 0; - nNonce = 0; - } + unsigned int nTimeMax{0}; CBlockIndex() { - SetNull(); } explicit CBlockIndex(const CBlockHeader& block) + : nVersion{block.nVersion}, + hashMerkleRoot{block.hashMerkleRoot}, + nTime{block.nTime}, + nBits{block.nBits}, + nNonce{block.nNonce} { - SetNull(); - - nVersion = block.nVersion; - hashMerkleRoot = block.hashMerkleRoot; - nTime = block.nTime; - nBits = block.nBits; - nNonce = block.nNonce; } FlatFilePos GetBlockPos() const { diff --git a/src/compat/byteswap.h b/src/compat/byteswap.h index fe47f4899f..c254fe7cbf 100644 --- a/src/compat/byteswap.h +++ b/src/compat/byteswap.h @@ -17,20 +17,13 @@ #if defined(MAC_OSX) -#if !defined(bswap_16) - -// Mac OS X / Darwin features; we include a check for bswap_16 because if it is already defined, protobuf has -// defined these macros for us already; if it isn't, we do it ourselves. In either case, we get the exact same -// result regardless which path was taken #include <libkern/OSByteOrder.h> #define bswap_16(x) OSSwapInt16(x) #define bswap_32(x) OSSwapInt32(x) #define bswap_64(x) OSSwapInt64(x) -#endif // !defined(bswap_16) - #else -// Non-Mac OS X / non-Darwin +// Non-MacOS / non-Darwin #if HAVE_DECL_BSWAP_16 == 0 inline uint16_t bswap_16(uint16_t x) diff --git a/src/compressor.cpp b/src/compressor.cpp index a2d9af8805..a7f45b5c1e 100644 --- a/src/compressor.cpp +++ b/src/compressor.cpp @@ -5,7 +5,6 @@ #include <compressor.h> -#include <hash.h> #include <pubkey.h> #include <script/standard.h> diff --git a/src/consensus/merkle.h b/src/consensus/merkle.h index 7675877de5..f28f76bd34 100644 --- a/src/consensus/merkle.h +++ b/src/consensus/merkle.h @@ -5,10 +5,8 @@ #ifndef BITCOIN_CONSENSUS_MERKLE_H #define BITCOIN_CONSENSUS_MERKLE_H -#include <stdint.h> #include <vector> -#include <primitives/transaction.h> #include <primitives/block.h> #include <uint256.h> diff --git a/src/consensus/params.h b/src/consensus/params.h index 2f8c490dc4..e191fd6d26 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -8,8 +8,6 @@ #include <uint256.h> #include <limits> -#include <map> -#include <string> namespace Consensus { diff --git a/src/consensus/tx_check.cpp b/src/consensus/tx_check.cpp index 00ebbbd1ab..6793f871cf 100644 --- a/src/consensus/tx_check.cpp +++ b/src/consensus/tx_check.cpp @@ -7,50 +7,51 @@ #include <primitives/transaction.h> #include <consensus/validation.h> -bool CheckTransaction(const CTransaction& tx, CValidationState &state, bool fCheckDuplicateInputs) +bool CheckTransaction(const CTransaction& tx, CValidationState& state) { // Basic checks that don't depend on any context if (tx.vin.empty()) - return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-txns-vin-empty"); + return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-txns-vin-empty"); if (tx.vout.empty()) - return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-txns-vout-empty"); + return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-txns-vout-empty"); // Size limits (this doesn't take the witness into account, as that hasn't been checked for malleability) if (::GetSerializeSize(tx, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * WITNESS_SCALE_FACTOR > MAX_BLOCK_WEIGHT) - return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-txns-oversize"); + return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-txns-oversize"); // Check for negative or overflow output values (see CVE-2010-5139) CAmount nValueOut = 0; for (const auto& txout : tx.vout) { if (txout.nValue < 0) - return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-txns-vout-negative"); + return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-txns-vout-negative"); if (txout.nValue > MAX_MONEY) - return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-txns-vout-toolarge"); + return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-txns-vout-toolarge"); nValueOut += txout.nValue; if (!MoneyRange(nValueOut)) - return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-txns-txouttotal-toolarge"); + return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-txns-txouttotal-toolarge"); } - // Check for duplicate inputs - note that this check is slow so we skip it in CheckBlock - if (fCheckDuplicateInputs) { - std::set<COutPoint> vInOutPoints; - for (const auto& txin : tx.vin) - { - if (!vInOutPoints.insert(txin.prevout).second) - return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-txns-inputs-duplicate"); - } + // Check for duplicate inputs (see CVE-2018-17144) + // While Consensus::CheckTxInputs does check if all inputs of a tx are available, and UpdateCoins marks all inputs + // of a tx as spent, it does not check if the tx has duplicate inputs. + // Failure to run this check will result in either a crash or an inflation bug, depending on the implementation of + // the underlying coins database. + std::set<COutPoint> vInOutPoints; + for (const auto& txin : tx.vin) { + if (!vInOutPoints.insert(txin.prevout).second) + return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-txns-inputs-duplicate"); } if (tx.IsCoinBase()) { if (tx.vin[0].scriptSig.size() < 2 || tx.vin[0].scriptSig.size() > 100) - return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-cb-length"); + return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-cb-length"); } else { for (const auto& txin : tx.vin) if (txin.prevout.IsNull()) - return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-txns-prevout-null"); + return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-txns-prevout-null"); } return true; diff --git a/src/consensus/tx_check.h b/src/consensus/tx_check.h index bcfdf36bf9..6f3f8fe969 100644 --- a/src/consensus/tx_check.h +++ b/src/consensus/tx_check.h @@ -15,6 +15,6 @@ class CTransaction; class CValidationState; -bool CheckTransaction(const CTransaction& tx, CValidationState& state, bool fCheckDuplicateInputs=true); +bool CheckTransaction(const CTransaction& tx, CValidationState& state); #endif // BITCOIN_CONSENSUS_TX_CHECK_H diff --git a/src/consensus/tx_verify.cpp b/src/consensus/tx_verify.cpp index 4b93cae848..ceeddc3f6d 100644 --- a/src/consensus/tx_verify.cpp +++ b/src/consensus/tx_verify.cpp @@ -160,7 +160,7 @@ bool Consensus::CheckTxInputs(const CTransaction& tx, CValidationState& state, c { // are the actual inputs available? if (!inputs.HaveInputs(tx)) { - return state.Invalid(ValidationInvalidReason::TX_MISSING_INPUTS, false, REJECT_INVALID, "bad-txns-inputs-missingorspent", + return state.Invalid(ValidationInvalidReason::TX_MISSING_INPUTS, false, "bad-txns-inputs-missingorspent", strprintf("%s: inputs missing/spent", __func__)); } @@ -172,27 +172,27 @@ bool Consensus::CheckTxInputs(const CTransaction& tx, CValidationState& state, c // If prev is coinbase, check that it's matured if (coin.IsCoinBase() && nSpendHeight - coin.nHeight < COINBASE_MATURITY) { - return state.Invalid(ValidationInvalidReason::TX_PREMATURE_SPEND, false, REJECT_INVALID, "bad-txns-premature-spend-of-coinbase", + return state.Invalid(ValidationInvalidReason::TX_PREMATURE_SPEND, false, "bad-txns-premature-spend-of-coinbase", strprintf("tried to spend coinbase at depth %d", nSpendHeight - coin.nHeight)); } // Check for negative or overflow input values nValueIn += coin.out.nValue; if (!MoneyRange(coin.out.nValue) || !MoneyRange(nValueIn)) { - return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-txns-inputvalues-outofrange"); + return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-txns-inputvalues-outofrange"); } } const CAmount value_out = tx.GetValueOut(); if (nValueIn < value_out) { - return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-txns-in-belowout", + return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-txns-in-belowout", strprintf("value in (%s) < value out (%s)", FormatMoney(nValueIn), FormatMoney(value_out))); } // Tally transaction fees const CAmount txfee_aux = nValueIn - value_out; if (!MoneyRange(txfee_aux)) { - return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-txns-fee-outofrange"); + return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-txns-fee-outofrange"); } txfee = txfee_aux; diff --git a/src/consensus/validation.h b/src/consensus/validation.h index 2e23f4b3a4..4920cdf881 100644 --- a/src/consensus/validation.h +++ b/src/consensus/validation.h @@ -12,20 +12,8 @@ #include <primitives/transaction.h> #include <primitives/block.h> -/** "reject" message codes */ -static const unsigned char REJECT_MALFORMED = 0x01; -static const unsigned char REJECT_INVALID = 0x10; -static const unsigned char REJECT_OBSOLETE = 0x11; -static const unsigned char REJECT_DUPLICATE = 0x12; -static const unsigned char REJECT_NONSTANDARD = 0x40; -// static const unsigned char REJECT_DUST = 0x41; // part of BIP 61 -static const unsigned char REJECT_INSUFFICIENTFEE = 0x42; -static const unsigned char REJECT_CHECKPOINT = 0x43; - /** A "reason" why something was invalid, suitable for determining whether the * provider of the object should be banned/ignored/disconnected/etc. - * These are much more granular than the rejection codes, which may be more - * useful for some other use-cases. */ enum class ValidationInvalidReason { // txn and blocks: @@ -104,15 +92,13 @@ private: } mode; ValidationInvalidReason m_reason; std::string strRejectReason; - unsigned int chRejectCode; std::string strDebugMessage; public: - CValidationState() : mode(MODE_VALID), m_reason(ValidationInvalidReason::NONE), chRejectCode(0) {} + CValidationState() : mode(MODE_VALID), m_reason(ValidationInvalidReason::NONE) {} bool Invalid(ValidationInvalidReason reasonIn, bool ret = false, - unsigned int chRejectCodeIn=0, const std::string &strRejectReasonIn="", + const std::string &strRejectReasonIn="", const std::string &strDebugMessageIn="") { m_reason = reasonIn; - chRejectCode = chRejectCodeIn; strRejectReason = strRejectReasonIn; strDebugMessage = strDebugMessageIn; if (mode == MODE_ERROR) @@ -136,7 +122,6 @@ public: return mode == MODE_ERROR; } ValidationInvalidReason GetReason() const { return m_reason; } - unsigned int GetRejectCode() const { return chRejectCode; } std::string GetRejectReason() const { return strRejectReason; } std::string GetDebugMessage() const { return strDebugMessage; } }; diff --git a/src/crypto/aes.cpp b/src/crypto/aes.cpp index b3fb927760..6ed9088434 100644 --- a/src/crypto/aes.cpp +++ b/src/crypto/aes.cpp @@ -4,7 +4,6 @@ #include <crypto/aes.h> -#include <assert.h> #include <string.h> extern "C" { diff --git a/src/crypto/chacha_poly_aead.cpp b/src/crypto/chacha_poly_aead.cpp index 6a3d43deb1..0582a60c4f 100644 --- a/src/crypto/chacha_poly_aead.cpp +++ b/src/crypto/chacha_poly_aead.cpp @@ -4,7 +4,6 @@ #include <crypto/chacha_poly_aead.h> -#include <crypto/common.h> #include <crypto/poly1305.h> #include <support/cleanse.h> diff --git a/src/crypto/sha256.cpp b/src/crypto/sha256.cpp index cab37e0322..3257ee7f97 100644 --- a/src/crypto/sha256.cpp +++ b/src/crypto/sha256.cpp @@ -7,7 +7,6 @@ #include <assert.h> #include <string.h> -#include <atomic> #if defined(__x86_64__) || defined(__amd64__) || defined(__i386__) #if defined(USE_ASM) diff --git a/src/crypto/sha256_shani.cpp b/src/crypto/sha256_shani.cpp index e561da42c5..7ea0c34796 100644 --- a/src/crypto/sha256_shani.cpp +++ b/src/crypto/sha256_shani.cpp @@ -11,7 +11,6 @@ #include <stdint.h> #include <immintrin.h> -#include <crypto/common.h> namespace { diff --git a/src/dbwrapper.h b/src/dbwrapper.h index 416f5e8399..061c9b6bca 100644 --- a/src/dbwrapper.h +++ b/src/dbwrapper.h @@ -11,7 +11,6 @@ #include <streams.h> #include <util/system.h> #include <util/strencodings.h> -#include <version.h> #include <leveldb/db.h> #include <leveldb/write_batch.h> diff --git a/src/dummywallet.cpp b/src/dummywallet.cpp index 126e3479f3..0edcb0286d 100644 --- a/src/dummywallet.cpp +++ b/src/dummywallet.cpp @@ -2,7 +2,6 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include <stdio.h> #include <util/system.h> #include <walletinitinterface.h> #include <support/allocators/secure.h> @@ -71,12 +70,12 @@ std::vector<std::shared_ptr<CWallet>> GetWallets() throw std::logic_error("Wallet function called in non-wallet build."); } -std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const std::string& name, std::string& error, std::string& warning) +std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const std::string& name, std::string& error, std::vector<std::string>& warnings) { throw std::logic_error("Wallet function called in non-wallet build."); } -WalletCreationStatus CreateWallet(interfaces::Chain& chain, const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, std::string& error, std::string& warning, std::shared_ptr<CWallet>& result) +WalletCreationStatus CreateWallet(interfaces::Chain& chain, const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, std::string& error, std::vector<std::string>& warnings, std::shared_ptr<CWallet>& result) { throw std::logic_error("Wallet function called in non-wallet build."); } diff --git a/src/httprpc.cpp b/src/httprpc.cpp index 306d718574..2c2f67b169 100644 --- a/src/httprpc.cpp +++ b/src/httprpc.cpp @@ -7,10 +7,8 @@ #include <chainparams.h> #include <crypto/hmac_sha256.h> #include <httpserver.h> -#include <key_io.h> #include <rpc/protocol.h> #include <rpc/server.h> -#include <sync.h> #include <ui_interface.h> #include <util/strencodings.h> #include <util/system.h> diff --git a/src/httprpc.h b/src/httprpc.h index 2230a8ca4e..91c2ec0c9d 100644 --- a/src/httprpc.h +++ b/src/httprpc.h @@ -5,8 +5,6 @@ #ifndef BITCOIN_HTTPRPC_H #define BITCOIN_HTTPRPC_H -#include <string> -#include <map> /** Start HTTP RPC subsystem. * Precondition; HTTP and RPC has been started. diff --git a/src/httpserver.cpp b/src/httpserver.cpp index d17667223b..d9c7113323 100644 --- a/src/httpserver.cpp +++ b/src/httpserver.cpp @@ -15,6 +15,7 @@ #include <sync.h> #include <ui_interface.h> +#include <deque> #include <memory> #include <stdio.h> #include <stdlib.h> @@ -22,7 +23,6 @@ #include <sys/types.h> #include <sys/stat.h> -#include <signal.h> #include <event2/thread.h> #include <event2/buffer.h> diff --git a/src/httpserver.h b/src/httpserver.h index 7943f0094b..bc72fc8512 100644 --- a/src/httpserver.h +++ b/src/httpserver.h @@ -6,7 +6,6 @@ #define BITCOIN_HTTPSERVER_H #include <string> -#include <stdint.h> #include <functional> static const int DEFAULT_HTTP_THREADS=4; diff --git a/src/index/base.h b/src/index/base.h index 31acbed0c1..f95eeb8197 100644 --- a/src/index/base.h +++ b/src/index/base.h @@ -9,7 +9,6 @@ #include <primitives/block.h> #include <primitives/transaction.h> #include <threadinterrupt.h> -#include <uint256.h> #include <validationinterface.h> class CBlockIndex; diff --git a/src/init.cpp b/src/init.cpp index 035725b090..da4d322669 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -354,7 +354,7 @@ void SetupServerArgs() std::vector<std::string> hidden_args = { "-dbcrashratio", "-forcecompactdb", // GUI args. These will be overwritten by SetupUIArgs for the GUI - "-allowselfsignedrootcertificates", "-choosedatadir", "-lang=<lang>", "-min", "-resetguisettings", "-rootcertificates=<file>", "-splash", "-uiplatform"}; + "-choosedatadir", "-lang=<lang>", "-min", "-resetguisettings", "-splash", "-uiplatform"}; gArgs.AddArg("-version", "Print version and exit", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); #if HAVE_SYSTEM diff --git a/src/interfaces/chain.cpp b/src/interfaces/chain.cpp index b8b9ecded9..b2c20573fb 100644 --- a/src/interfaces/chain.cpp +++ b/src/interfaces/chain.cpp @@ -18,12 +18,10 @@ #include <policy/settings.h> #include <primitives/block.h> #include <primitives/transaction.h> -#include <protocol.h> #include <rpc/protocol.h> #include <rpc/server.h> #include <shutdown.h> #include <sync.h> -#include <threadsafety.h> #include <timedata.h> #include <txmempool.h> #include <ui_interface.h> @@ -298,6 +296,11 @@ public: { ::mempool.GetTransactionAncestry(txid, ancestors, descendants); } + void getPackageLimits(unsigned int& limit_ancestor_count, unsigned int& limit_descendant_count) override + { + limit_ancestor_count = gArgs.GetArg("-limitancestorcount", DEFAULT_ANCESTOR_LIMIT); + limit_descendant_count = gArgs.GetArg("-limitdescendantcount", DEFAULT_DESCENDANT_LIMIT); + } bool checkChainLimits(const CTransactionRef& tx) override { LockPoints lp; diff --git a/src/interfaces/chain.h b/src/interfaces/chain.h index da670a3370..73a78e21fb 100644 --- a/src/interfaces/chain.h +++ b/src/interfaces/chain.h @@ -163,6 +163,11 @@ public: //! Calculate mempool ancestor and descendant counts for the given transaction. virtual void getTransactionAncestry(const uint256& txid, size_t& ancestors, size_t& descendants) = 0; + //! Get the node's package limits. + //! Currently only returns the ancestor and descendant count limits, but could be enhanced to + //! return more policy settings. + virtual void getPackageLimits(unsigned int& limit_ancestor_count, unsigned int& limit_descendant_count) = 0; + //! Check if transaction will pass the mempool's chain limits. virtual bool checkChainLimits(const CTransactionRef& tx) = 0; diff --git a/src/interfaces/node.cpp b/src/interfaces/node.cpp index 3d89e17163..6577895d50 100644 --- a/src/interfaces/node.cpp +++ b/src/interfaces/node.cpp @@ -5,7 +5,6 @@ #include <interfaces/node.h> #include <addrdb.h> -#include <amount.h> #include <banman.h> #include <chain.h> #include <chainparams.h> @@ -19,7 +18,6 @@ #include <netbase.h> #include <policy/feerate.h> #include <policy/fees.h> -#include <policy/policy.h> #include <policy/settings.h> #include <primitives/block.h> #include <rpc/server.h> @@ -36,15 +34,14 @@ #include <config/bitcoin-config.h> #endif -#include <atomic> #include <univalue.h> class CWallet; fs::path GetWalletDir(); std::vector<fs::path> ListWalletDir(); std::vector<std::shared_ptr<CWallet>> GetWallets(); -std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const std::string& name, std::string& error, std::string& warning); -WalletCreationStatus CreateWallet(interfaces::Chain& chain, const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, std::string& error, std::string& warning, std::shared_ptr<CWallet>& result); +std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const std::string& name, std::string& error, std::vector<std::string>& warnings); +WalletCreationStatus CreateWallet(interfaces::Chain& chain, const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, std::string& error, std::vector<std::string>& warnings, std::shared_ptr<CWallet>& result); namespace interfaces { @@ -256,14 +253,14 @@ public: } return wallets; } - std::unique_ptr<Wallet> loadWallet(const std::string& name, std::string& error, std::string& warning) override + std::unique_ptr<Wallet> loadWallet(const std::string& name, std::string& error, std::vector<std::string>& warnings) override { - return MakeWallet(LoadWallet(*m_interfaces.chain, name, error, warning)); + return MakeWallet(LoadWallet(*m_interfaces.chain, name, error, warnings)); } - WalletCreationStatus createWallet(const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, std::string& error, std::string& warning, std::unique_ptr<Wallet>& result) override + WalletCreationStatus createWallet(const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, std::string& error, std::vector<std::string>& warnings, std::unique_ptr<Wallet>& result) override { std::shared_ptr<CWallet> wallet; - WalletCreationStatus status = CreateWallet(*m_interfaces.chain, passphrase, wallet_creation_flags, name, error, warning, wallet); + WalletCreationStatus status = CreateWallet(*m_interfaces.chain, passphrase, wallet_creation_flags, name, error, warnings, wallet); result = MakeWallet(wallet); return status; } @@ -315,7 +312,7 @@ public: return MakeHandler( ::uiInterface.NotifyHeaderTip_connect([fn](bool initial_download, const CBlockIndex* block) { fn(initial_download, block->nHeight, block->GetBlockTime(), - GuessVerificationProgress(Params().TxData(), block)); + /* verification progress is unused when a header was received */ 0); })); } InitInterfaces m_interfaces; diff --git a/src/interfaces/node.h b/src/interfaces/node.h index 688ff434ba..4ee467014c 100644 --- a/src/interfaces/node.h +++ b/src/interfaces/node.h @@ -200,10 +200,10 @@ public: //! Attempts to load a wallet from file or directory. //! The loaded wallet is also notified to handlers previously registered //! with handleLoadWallet. - virtual std::unique_ptr<Wallet> loadWallet(const std::string& name, std::string& error, std::string& warning) = 0; + virtual std::unique_ptr<Wallet> loadWallet(const std::string& name, std::string& error, std::vector<std::string>& warnings) = 0; //! Create a wallet from file - virtual WalletCreationStatus createWallet(const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, std::string& error, std::string& warning, std::unique_ptr<Wallet>& result) = 0; + virtual WalletCreationStatus createWallet(const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, std::string& error, std::vector<std::string>& warnings, std::unique_ptr<Wallet>& result) = 0; //! Register handler for init messages. using InitMessageFn = std::function<void(const std::string& message)>; diff --git a/src/interfaces/wallet.cpp b/src/interfaces/wallet.cpp index 0c8d92eba5..9b0a8b64c9 100644 --- a/src/interfaces/wallet.cpp +++ b/src/interfaces/wallet.cpp @@ -5,10 +5,8 @@ #include <interfaces/wallet.h> #include <amount.h> -#include <consensus/validation.h> #include <interfaces/chain.h> #include <interfaces/handler.h> -#include <policy/feerate.h> #include <policy/fees.h> #include <primitives/transaction.h> #include <script/standard.h> @@ -23,7 +21,6 @@ #include <wallet/rpcwallet.h> #include <wallet/load.h> #include <wallet/wallet.h> -#include <wallet/walletutil.h> #include <memory> #include <string> @@ -218,19 +215,13 @@ public: } return tx; } - bool commitTransaction(CTransactionRef tx, + void commitTransaction(CTransactionRef tx, WalletValueMap value_map, - WalletOrderForm order_form, - std::string& reject_reason) override + WalletOrderForm order_form) override { auto locked_chain = m_wallet->chain().lock(); LOCK(m_wallet->cs_wallet); - CValidationState state; - if (!m_wallet->CommitTransaction(std::move(tx), std::move(value_map), std::move(order_form), state)) { - reject_reason = state.GetRejectReason(); - return false; - } - return true; + m_wallet->CommitTransaction(std::move(tx), std::move(value_map), std::move(order_form)); } bool transactionCanBeAbandoned(const uint256& txid) override { return m_wallet->TransactionCanBeAbandoned(txid); } bool abandonTransaction(const uint256& txid) override @@ -241,7 +232,7 @@ public: } bool transactionCanBeBumped(const uint256& txid) override { - return feebumper::TransactionCanBeBumped(m_wallet.get(), txid); + return feebumper::TransactionCanBeBumped(*m_wallet.get(), txid); } bool createBumpTransaction(const uint256& txid, const CCoinControl& coin_control, @@ -255,17 +246,17 @@ public: return feebumper::CreateTotalBumpTransaction(m_wallet.get(), txid, coin_control, total_fee, errors, old_fee, new_fee, mtx) == feebumper::Result::OK; } else { - return feebumper::CreateRateBumpTransaction(m_wallet.get(), txid, coin_control, errors, old_fee, new_fee, mtx) == + return feebumper::CreateRateBumpTransaction(*m_wallet.get(), txid, coin_control, errors, old_fee, new_fee, mtx) == feebumper::Result::OK; } } - bool signBumpTransaction(CMutableTransaction& mtx) override { return feebumper::SignTransaction(m_wallet.get(), mtx); } + bool signBumpTransaction(CMutableTransaction& mtx) override { return feebumper::SignTransaction(*m_wallet.get(), mtx); } bool commitBumpTransaction(const uint256& txid, CMutableTransaction&& mtx, std::vector<std::string>& errors, uint256& bumped_txid) override { - return feebumper::CommitTransaction(m_wallet.get(), txid, std::move(mtx), errors, bumped_txid) == + return feebumper::CommitTransaction(*m_wallet.get(), txid, std::move(mtx), errors, bumped_txid) == feebumper::Result::OK; } CTransactionRef getTx(const uint256& txid) override diff --git a/src/interfaces/wallet.h b/src/interfaces/wallet.h index 89e056b18b..a96b93b4c3 100644 --- a/src/interfaces/wallet.h +++ b/src/interfaces/wallet.h @@ -141,10 +141,9 @@ public: std::string& fail_reason) = 0; //! Commit transaction. - virtual bool commitTransaction(CTransactionRef tx, + virtual void commitTransaction(CTransactionRef tx, WalletValueMap value_map, - WalletOrderForm order_form, - std::string& reject_reason) = 0; + WalletOrderForm order_form) = 0; //! Return whether transaction can be abandoned. virtual bool transactionCanBeAbandoned(const uint256& txid) = 0; @@ -162,25 +162,6 @@ struct CExtKey { bool Derive(CExtKey& out, unsigned int nChild) const; CExtPubKey Neuter() const; void SetSeed(const unsigned char* seed, unsigned int nSeedLen); - template <typename Stream> - void Serialize(Stream& s) const - { - unsigned int len = BIP32_EXTKEY_SIZE; - ::WriteCompactSize(s, len); - unsigned char code[BIP32_EXTKEY_SIZE]; - Encode(code); - s.write((const char *)&code[0], len); - } - template <typename Stream> - void Unserialize(Stream& s) - { - unsigned int len = ::ReadCompactSize(s); - unsigned char code[BIP32_EXTKEY_SIZE]; - if (len != BIP32_EXTKEY_SIZE) - throw std::runtime_error("Invalid extended key size\n"); - s.read((char *)&code[0], len); - Decode(code); - } }; /** Initialize the elliptic curve support. May not be called twice without calling ECC_Stop first. */ diff --git a/src/key_io.cpp b/src/key_io.cpp index cd41a93549..363055d6b3 100644 --- a/src/key_io.cpp +++ b/src/key_io.cpp @@ -6,7 +6,6 @@ #include <base58.h> #include <bech32.h> -#include <script/script.h> #include <util/strencodings.h> #include <boost/variant/apply_visitor.hpp> diff --git a/src/logging.cpp b/src/logging.cpp index dc2d130a2a..60ab486198 100644 --- a/src/logging.cpp +++ b/src/logging.cpp @@ -224,10 +224,32 @@ std::string BCLog::Logger::LogTimestampStr(const std::string& str) return strStamped; } +namespace BCLog { + /** Belts and suspenders: make sure outgoing log messages don't contain + * potentially suspicious characters, such as terminal control codes. + * + * This escapes control characters except newline ('\n') in C syntax. + * It escapes instead of removes them to still allow for troubleshooting + * issues where they accidentally end up in strings. + */ + std::string LogEscapeMessage(const std::string& str) { + std::string ret; + for (char ch_in : str) { + uint8_t ch = (uint8_t)ch_in; + if ((ch >= 32 || ch == '\n') && ch != '\x7f') { + ret += ch_in; + } else { + ret += strprintf("\\x%02x", ch); + } + } + return ret; + } +} + void BCLog::Logger::LogPrintStr(const std::string& str) { std::lock_guard<std::mutex> scoped_lock(m_cs); - std::string str_prefixed = str; + std::string str_prefixed = LogEscapeMessage(str); if (m_log_threadnames && m_started_new_line) { str_prefixed.insert(0, "[" + util::ThreadGetInternalName() + "] "); diff --git a/src/miner.cpp b/src/miner.cpp index 015645c9c6..4f51be8a08 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -17,14 +17,12 @@ #include <policy/policy.h> #include <pow.h> #include <primitives/transaction.h> -#include <script/standard.h> #include <timedata.h> #include <util/moneystr.h> #include <util/system.h> #include <util/validation.h> #include <algorithm> -#include <queue> #include <utility> int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev) diff --git a/src/net.cpp b/src/net.cpp index 63b7833822..7ae88b47a0 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -13,11 +13,9 @@ #include <chainparams.h> #include <clientversion.h> #include <consensus/consensus.h> -#include <crypto/common.h> #include <crypto/sha256.h> #include <netbase.h> #include <net_permissions.h> -#include <primitives/transaction.h> #include <scheduler.h> #include <ui_interface.h> #include <util/strencodings.h> @@ -35,7 +33,6 @@ #ifdef USE_UPNP #include <miniupnpc/miniupnpc.h> -#include <miniupnpc/miniwget.h> #include <miniupnpc/upnpcommands.h> #include <miniupnpc/upnperrors.h> // The minimum supported miniUPnPc API version is set to 10. This keeps compatibility @@ -570,42 +567,28 @@ bool CNode::ReceiveMsgBytes(const char *pch, unsigned int nBytes, bool& complete nLastRecv = nTimeMicros / 1000000; nRecvBytes += nBytes; while (nBytes > 0) { - - // get current incomplete message, or create a new one - if (vRecvMsg.empty() || - vRecvMsg.back().complete()) - vRecvMsg.push_back(CNetMessage(Params().MessageStart(), SER_NETWORK, INIT_PROTO_VERSION)); - - CNetMessage& msg = vRecvMsg.back(); - // absorb network data - int handled; - if (!msg.in_data) - handled = msg.readHeader(pch, nBytes); - else - handled = msg.readData(pch, nBytes); - - if (handled < 0) - return false; - - if (msg.in_data && msg.hdr.nMessageSize > MAX_PROTOCOL_MESSAGE_LENGTH) { - LogPrint(BCLog::NET, "Oversized message from peer=%i, disconnecting\n", GetId()); - return false; - } + int handled = m_deserializer->Read(pch, nBytes); + if (handled < 0) return false; pch += handled; nBytes -= handled; - if (msg.complete()) { + if (m_deserializer->Complete()) { + // decompose a transport agnostic CNetMessage from the deserializer + CNetMessage msg = m_deserializer->GetMessage(Params().MessageStart(), nTimeMicros); + //store received bytes per message command //to prevent a memory DOS, only allow valid commands - mapMsgCmdSize::iterator i = mapRecvBytesPerMsgCmd.find(msg.hdr.pchCommand); + mapMsgCmdSize::iterator i = mapRecvBytesPerMsgCmd.find(msg.m_command); if (i == mapRecvBytesPerMsgCmd.end()) i = mapRecvBytesPerMsgCmd.find(NET_MESSAGE_COMMAND_OTHER); assert(i != mapRecvBytesPerMsgCmd.end()); - i->second += msg.hdr.nMessageSize + CMessageHeader::HEADER_SIZE; + i->second += msg.m_raw_message_size; + + // push the message to the process queue, + vRecvMsg.push_back(std::move(msg)); - msg.nTime = nTimeMicros; complete = true; } } @@ -639,8 +622,7 @@ int CNode::GetSendVersion() const return nSendVersion; } - -int CNetMessage::readHeader(const char *pch, unsigned int nBytes) +int V1TransportDeserializer::readHeader(const char *pch, unsigned int nBytes) { // copy data to temporary parsing buffer unsigned int nRemaining = 24 - nHdrPos; @@ -661,9 +643,10 @@ int CNetMessage::readHeader(const char *pch, unsigned int nBytes) return -1; } - // reject messages larger than MAX_SIZE - if (hdr.nMessageSize > MAX_SIZE) + // reject messages larger than MAX_SIZE or MAX_PROTOCOL_MESSAGE_LENGTH + if (hdr.nMessageSize > MAX_SIZE || hdr.nMessageSize > MAX_PROTOCOL_MESSAGE_LENGTH) { return -1; + } // switch state to reading message data in_data = true; @@ -671,7 +654,7 @@ int CNetMessage::readHeader(const char *pch, unsigned int nBytes) return nCopy; } -int CNetMessage::readData(const char *pch, unsigned int nBytes) +int V1TransportDeserializer::readData(const char *pch, unsigned int nBytes) { unsigned int nRemaining = hdr.nMessageSize - nDataPos; unsigned int nCopy = std::min(nRemaining, nBytes); @@ -688,14 +671,44 @@ int CNetMessage::readData(const char *pch, unsigned int nBytes) return nCopy; } -const uint256& CNetMessage::GetMessageHash() const +const uint256& V1TransportDeserializer::GetMessageHash() const { - assert(complete()); + assert(Complete()); if (data_hash.IsNull()) hasher.Finalize(data_hash.begin()); return data_hash; } +CNetMessage V1TransportDeserializer::GetMessage(const CMessageHeader::MessageStartChars& message_start, int64_t time) { + // decompose a single CNetMessage from the TransportDeserializer + CNetMessage msg(std::move(vRecv)); + + // store state about valid header, netmagic and checksum + msg.m_valid_header = hdr.IsValid(message_start); + msg.m_valid_netmagic = (memcmp(hdr.pchMessageStart, message_start, CMessageHeader::MESSAGE_START_SIZE) == 0); + uint256 hash = GetMessageHash(); + + // store command string, payload size + msg.m_command = hdr.GetCommand(); + msg.m_message_size = hdr.nMessageSize; + msg.m_raw_message_size = hdr.nMessageSize + CMessageHeader::HEADER_SIZE; + + msg.m_valid_checksum = (memcmp(hash.begin(), hdr.pchChecksum, CMessageHeader::CHECKSUM_SIZE) == 0); + if (!msg.m_valid_checksum) { + LogPrint(BCLog::NET, "CHECKSUM ERROR (%s, %u bytes), expected %s was %s\n", + SanitizeString(msg.m_command), msg.m_message_size, + HexStr(hash.begin(), hash.begin()+CMessageHeader::CHECKSUM_SIZE), + HexStr(hdr.pchChecksum, hdr.pchChecksum+CMessageHeader::CHECKSUM_SIZE)); + } + + // store receive time + msg.m_time = time; + + // reset the network deserializer (prepare for the next message) + Reset(); + return msg; +} + size_t CConnman::SocketSendData(CNode *pnode) const EXCLUSIVE_LOCKS_REQUIRED(pnode->cs_vSend) { auto it = pnode->vSendMsg.begin(); @@ -1347,9 +1360,9 @@ void CConnman::SocketHandler() size_t nSizeAdded = 0; auto it(pnode->vRecvMsg.begin()); for (; it != pnode->vRecvMsg.end(); ++it) { - if (!it->complete()) - break; - nSizeAdded += it->vRecv.size() + CMessageHeader::HEADER_SIZE; + // vRecvMsg contains only completed CNetMessage + // the single possible partially deserialized message are held by TransportDeserializer + nSizeAdded += it->m_raw_message_size; } { LOCK(pnode->cs_vProcessMsg); @@ -1364,7 +1377,7 @@ void CConnman::SocketHandler() { // socket closed gracefully if (!pnode->fDisconnect) { - LogPrint(BCLog::NET, "socket closed\n"); + LogPrint(BCLog::NET, "socket closed for peer=%d\n", pnode->GetId()); } pnode->CloseSocketDisconnect(); } @@ -1374,8 +1387,9 @@ void CConnman::SocketHandler() int nErr = WSAGetLastError(); if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS) { - if (!pnode->fDisconnect) - LogPrintf("socket recv error %s\n", NetworkErrorString(nErr)); + if (!pnode->fDisconnect) { + LogPrint(BCLog::NET, "socket recv error for peer=%d: %s\n", pnode->GetId(), NetworkErrorString(nErr)); + } pnode->CloseSocketDisconnect(); } } @@ -2678,6 +2692,8 @@ CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn } else { LogPrint(BCLog::NET, "Added connection peer=%d\n", id); } + + m_deserializer = MakeUnique<V1TransportDeserializer>(V1TransportDeserializer(Params().MessageStart(), SER_NETWORK, INIT_PROTO_VERSION)); } CNode::~CNode() @@ -609,56 +609,105 @@ public: - +/** Transport protocol agnostic message container. + * Ideally it should only contain receive time, payload, + * command and size. + */ class CNetMessage { +public: + CDataStream m_recv; // received message data + int64_t m_time = 0; // time (in microseconds) of message receipt. + bool m_valid_netmagic = false; + bool m_valid_header = false; + bool m_valid_checksum = false; + uint32_t m_message_size = 0; // size of the payload + uint32_t m_raw_message_size = 0; // used wire size of the message (including header/checksum) + std::string m_command; + + CNetMessage(CDataStream&& recv_in) : m_recv(std::move(recv_in)) {} + + void SetVersion(int nVersionIn) + { + m_recv.SetVersion(nVersionIn); + } +}; + +/** The TransportDeserializer takes care of holding and deserializing the + * network receive buffer. It can deserialize the network buffer into a + * transport protocol agnostic CNetMessage (command & payload) + */ +class TransportDeserializer { +public: + // returns true if the current deserialization is complete + virtual bool Complete() const = 0; + // set the serialization context version + virtual void SetVersion(int version) = 0; + // read and deserialize data + virtual int Read(const char *data, unsigned int bytes) = 0; + // decomposes a message from the context + virtual CNetMessage GetMessage(const CMessageHeader::MessageStartChars& message_start, int64_t time) = 0; + virtual ~TransportDeserializer() {} +}; + +class V1TransportDeserializer final : public TransportDeserializer +{ private: mutable CHash256 hasher; mutable uint256 data_hash; -public: bool in_data; // parsing header (false) or data (true) - CDataStream hdrbuf; // partially received header CMessageHeader hdr; // complete header - unsigned int nHdrPos; - CDataStream vRecv; // received message data + unsigned int nHdrPos; unsigned int nDataPos; - int64_t nTime; // time (in microseconds) of message receipt. + const uint256& GetMessageHash() const; + int readHeader(const char *pch, unsigned int nBytes); + int readData(const char *pch, unsigned int nBytes); - CNetMessage(const CMessageHeader::MessageStartChars& pchMessageStartIn, int nTypeIn, int nVersionIn) : hdrbuf(nTypeIn, nVersionIn), hdr(pchMessageStartIn), vRecv(nTypeIn, nVersionIn) { + void Reset() { + vRecv.clear(); + hdrbuf.clear(); hdrbuf.resize(24); in_data = false; nHdrPos = 0; nDataPos = 0; - nTime = 0; + data_hash.SetNull(); + hasher.Reset(); } - bool complete() const +public: + + V1TransportDeserializer(const CMessageHeader::MessageStartChars& pchMessageStartIn, int nTypeIn, int nVersionIn) : hdrbuf(nTypeIn, nVersionIn), hdr(pchMessageStartIn), vRecv(nTypeIn, nVersionIn) { + Reset(); + } + + bool Complete() const override { if (!in_data) return false; return (hdr.nMessageSize == nDataPos); } - - const uint256& GetMessageHash() const; - - void SetVersion(int nVersionIn) + void SetVersion(int nVersionIn) override { hdrbuf.SetVersion(nVersionIn); vRecv.SetVersion(nVersionIn); } - - int readHeader(const char *pch, unsigned int nBytes); - int readData(const char *pch, unsigned int nBytes); + int Read(const char *pch, unsigned int nBytes) override { + int ret = in_data ? readData(pch, nBytes) : readHeader(pch, nBytes); + if (ret < 0) Reset(); + return ret; + } + CNetMessage GetMessage(const CMessageHeader::MessageStartChars& message_start, int64_t time) override; }; - /** Information about a peer */ class CNode { friend class CConnman; public: + std::unique_ptr<TransportDeserializer> m_deserializer; + // socket std::atomic<ServiceFlags> nServices{NODE_NONE}; SOCKET hSocket GUARDED_BY(cs_hSocket); diff --git a/src/net_processing.cpp b/src/net_processing.cpp index b6839dcf21..fd31c962c2 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -7,7 +7,6 @@ #include <addrman.h> #include <banman.h> -#include <arith_uint256.h> #include <blockencodings.h> #include <chainparams.h> #include <consensus/validation.h> @@ -39,6 +38,8 @@ static constexpr int64_t ORPHAN_TX_EXPIRE_TIME = 20 * 60; /** Minimum time between orphan transactions expire time checks in seconds */ static constexpr int64_t ORPHAN_TX_EXPIRE_INTERVAL = 5 * 60; +/** How long to cache transactions in mapRelay for normal relay */ +static constexpr std::chrono::seconds RELAY_TX_CACHE_TIME{15 * 60}; /** Headers download timeout expressed in microseconds * Timeout = base + per_header * (expected number of headers) */ static constexpr int64_t HEADERS_DOWNLOAD_TIMEOUT_BASE = 15 * 60 * 1000000; // 15 minutes @@ -117,8 +118,8 @@ namespace { int nSyncStarted GUARDED_BY(cs_main) = 0; /** - * Sources of received blocks, saved to be able to send them reject - * messages or ban them when processing happens afterwards. + * Sources of received blocks, saved to be able punish them when processing + * happens afterwards. * Set mapBlockSource[hash].second to false if the node should not be * punished if the block is invalid. */ @@ -1234,11 +1235,12 @@ void PeerLogicValidation::BlockChecked(const CBlock& block, const CValidationSta const uint256 hash(block.GetHash()); std::map<uint256, std::pair<NodeId, bool>>::iterator it = mapBlockSource.find(hash); - if (state.IsInvalid()) { - // Don't send reject message with code 0 or an internal reject code. - if (it != mapBlockSource.end() && State(it->second.first) && state.GetRejectCode() > 0 && state.GetRejectCode() < REJECT_INTERNAL) { + // If the block failed validation, we know where it came from and we're still connected + // to that peer, maybe punish. + if (state.IsInvalid() && + it != mapBlockSource.end() && + State(it->second.first)) { MaybePunishNode(/*nodeid=*/ it->second.first, state, /*via_compact_block=*/ !it->second.second); - } } // Check that: // 1. The block is valid @@ -1513,6 +1515,10 @@ void static ProcessGetData(CNode* pfrom, const CChainParams& chainparams, CConnm // messages from this peer (likely resulting in our peer eventually // disconnecting us). if (pfrom->m_tx_relay != nullptr) { + // mempool entries added before this time have likely expired from mapRelay + const std::chrono::seconds longlived_mempool_time = GetTime<std::chrono::seconds>() - RELAY_TX_CACHE_TIME; + const std::chrono::seconds mempool_req = pfrom->m_tx_relay->m_last_mempool_req.load(); + LOCK(cs_main); while (it != pfrom->vRecvGetData.end() && (it->type == MSG_TX || it->type == MSG_WITNESS_TX)) { @@ -1532,11 +1538,15 @@ void static ProcessGetData(CNode* pfrom, const CChainParams& chainparams, CConnm if (mi != mapRelay.end()) { connman->PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::TX, *mi->second)); push = true; - } else if (pfrom->m_tx_relay->m_last_mempool_req.load().count()) { + } else { auto txinfo = mempool.info(inv.hash); // To protect privacy, do not answer getdata using the mempool when - // that TX couldn't have been INVed in reply to a MEMPOOL request. - if (txinfo.tx && txinfo.m_time <= pfrom->m_tx_relay->m_last_mempool_req.load()) { + // that TX couldn't have been INVed in reply to a MEMPOOL request, + // or when it's too recent to have expired from mapRelay. + if (txinfo.tx && ( + (mempool_req.count() && txinfo.m_time <= mempool_req) + || (txinfo.m_time <= longlived_mempool_time))) + { connman->PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::TX, *txinfo.tx)); push = true; } @@ -2860,11 +2870,12 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr // been run). This is handled below, so just treat this as // though the block was successfully read, and rely on the // handling in ProcessNewBlock to ensure the block index is - // updated, reject messages go out, etc. + // updated, etc. MarkBlockAsReceived(resp.blockhash); // it is now an empty pointer fBlockRead = true; - // mapBlockSource is only used for sending reject messages and DoS scores, - // so the race between here and cs_main in ProcessNewBlock is fine. + // mapBlockSource is used for potentially punishing peers and + // updating which peers send us compact blocks, so the race + // between here and cs_main in ProcessNewBlock is fine. // BIP 152 permits peers to relay compact blocks after validating // the header only; we should not punish peers if the block turns // out to be invalid. @@ -2936,8 +2947,9 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr // Also always process if we requested the block explicitly, as we may // need it even though it is not a candidate for a new best tip. forceProcessing |= MarkBlockAsReceived(hash); - // mapBlockSource is only used for sending reject messages and DoS scores, - // so the race between here and cs_main in ProcessNewBlock is fine. + // mapBlockSource is only used for punishing peers and setting + // which peers send us compact blocks, so the race between here and + // cs_main in ProcessNewBlock is fine. mapBlockSource.emplace(hash, std::make_pair(pfrom->GetId(), true)); } bool fNewBlock = false; @@ -3260,41 +3272,37 @@ bool PeerLogicValidation::ProcessMessages(CNode* pfrom, std::atomic<bool>& inter return false; // Just take one message msgs.splice(msgs.begin(), pfrom->vProcessMsg, pfrom->vProcessMsg.begin()); - pfrom->nProcessQueueSize -= msgs.front().vRecv.size() + CMessageHeader::HEADER_SIZE; + pfrom->nProcessQueueSize -= msgs.front().m_raw_message_size; pfrom->fPauseRecv = pfrom->nProcessQueueSize > connman->GetReceiveFloodSize(); fMoreWork = !pfrom->vProcessMsg.empty(); } CNetMessage& msg(msgs.front()); msg.SetVersion(pfrom->GetRecvVersion()); - // Scan for message start - if (memcmp(msg.hdr.pchMessageStart, chainparams.MessageStart(), CMessageHeader::MESSAGE_START_SIZE) != 0) { - LogPrint(BCLog::NET, "PROCESSMESSAGE: INVALID MESSAGESTART %s peer=%d\n", SanitizeString(msg.hdr.GetCommand()), pfrom->GetId()); + // Check network magic + if (!msg.m_valid_netmagic) { + LogPrint(BCLog::NET, "PROCESSMESSAGE: INVALID MESSAGESTART %s peer=%d\n", SanitizeString(msg.m_command), pfrom->GetId()); pfrom->fDisconnect = true; return false; } - // Read header - CMessageHeader& hdr = msg.hdr; - if (!hdr.IsValid(chainparams.MessageStart())) + // Check header + if (!msg.m_valid_header) { - LogPrint(BCLog::NET, "PROCESSMESSAGE: ERRORS IN HEADER %s peer=%d\n", SanitizeString(hdr.GetCommand()), pfrom->GetId()); + LogPrint(BCLog::NET, "PROCESSMESSAGE: ERRORS IN HEADER %s peer=%d\n", SanitizeString(msg.m_command), pfrom->GetId()); return fMoreWork; } - std::string strCommand = hdr.GetCommand(); + const std::string& strCommand = msg.m_command; // Message size - unsigned int nMessageSize = hdr.nMessageSize; + unsigned int nMessageSize = msg.m_message_size; // Checksum - CDataStream& vRecv = msg.vRecv; - const uint256& hash = msg.GetMessageHash(); - if (memcmp(hash.begin(), hdr.pchChecksum, CMessageHeader::CHECKSUM_SIZE) != 0) + CDataStream& vRecv = msg.m_recv; + if (!msg.m_valid_checksum) { - LogPrint(BCLog::NET, "%s(%s, %u bytes): CHECKSUM ERROR expected %s was %s\n", __func__, - SanitizeString(strCommand), nMessageSize, - HexStr(hash.begin(), hash.begin()+CMessageHeader::CHECKSUM_SIZE), - HexStr(hdr.pchChecksum, hdr.pchChecksum+CMessageHeader::CHECKSUM_SIZE)); + LogPrint(BCLog::NET, "%s(%s, %u bytes): CHECKSUM ERROR peer=%d\n", __func__, + SanitizeString(strCommand), nMessageSize, pfrom->GetId()); return fMoreWork; } @@ -3302,7 +3310,7 @@ bool PeerLogicValidation::ProcessMessages(CNode* pfrom, std::atomic<bool>& inter bool fRet = false; try { - fRet = ProcessMessage(pfrom, strCommand, vRecv, msg.nTime, chainparams, connman, interruptMsgProc); + fRet = ProcessMessage(pfrom, strCommand, vRecv, msg.m_time, chainparams, connman, interruptMsgProc); if (interruptMsgProc) return false; if (!pfrom->vRecvGetData.empty()) @@ -3874,7 +3882,7 @@ bool PeerLogicValidation::SendMessages(CNode* pto) auto ret = mapRelay.insert(std::make_pair(hash, std::move(txinfo.tx))); if (ret.second) { - vRelayExpiration.push_back(std::make_pair(nNow + 15 * 60 * 1000000, ret.first)); + vRelayExpiration.push_back(std::make_pair(nNow + std::chrono::microseconds{RELAY_TX_CACHE_TIME}.count(), ret.first)); } } if (vInv.size() == MAX_INV_SZ) { diff --git a/src/netaddress.h b/src/netaddress.h index 673eaf8d7b..fbb1553338 100644 --- a/src/netaddress.h +++ b/src/netaddress.h @@ -11,7 +11,6 @@ #include <compat.h> #include <serialize.h> -#include <span.h> #include <stdint.h> #include <string> diff --git a/src/node/coinstats.cpp b/src/node/coinstats.cpp index e1891b9898..57fa158ad2 100644 --- a/src/node/coinstats.cpp +++ b/src/node/coinstats.cpp @@ -5,9 +5,7 @@ #include <node/coinstats.h> -#include <amount.h> #include <coins.h> -#include <chain.h> #include <hash.h> #include <serialize.h> #include <validation.h> diff --git a/src/node/transaction.cpp b/src/node/transaction.cpp index 7e8291ddc8..7783671a6c 100644 --- a/src/node/transaction.cpp +++ b/src/node/transaction.cpp @@ -6,7 +6,6 @@ #include <consensus/validation.h> #include <net.h> #include <net_processing.h> -#include <txmempool.h> #include <util/validation.h> #include <validation.h> #include <validationinterface.h> diff --git a/src/node/transaction.h b/src/node/transaction.h index cf64fc28d9..a3e56544a7 100644 --- a/src/node/transaction.h +++ b/src/node/transaction.h @@ -7,7 +7,6 @@ #include <attributes.h> #include <primitives/transaction.h> -#include <uint256.h> #include <util/error.h> /** diff --git a/src/noui.cpp b/src/noui.cpp index c07939cc79..14d6183d24 100644 --- a/src/noui.cpp +++ b/src/noui.cpp @@ -8,8 +8,6 @@ #include <ui_interface.h> #include <util/system.h> -#include <cstdio> -#include <stdint.h> #include <string> #include <boost/signals2/connection.hpp> diff --git a/src/outputtype.cpp b/src/outputtype.cpp index bcaa05f4b6..5cc43898a7 100644 --- a/src/outputtype.cpp +++ b/src/outputtype.cpp @@ -10,6 +10,7 @@ #include <script/sign.h> #include <script/signingprovider.h> #include <script/standard.h> +#include <util/vector.h> #include <assert.h> #include <string> @@ -65,12 +66,13 @@ CTxDestination GetDestinationForKey(const CPubKey& key, OutputType type) std::vector<CTxDestination> GetAllDestinationsForKey(const CPubKey& key) { PKHash keyid(key); + CTxDestination p2pkh{keyid}; if (key.IsCompressed()) { CTxDestination segwit = WitnessV0KeyHash(keyid); CTxDestination p2sh = ScriptHash(GetScriptForDestination(segwit)); - return std::vector<CTxDestination>{std::move(keyid), std::move(p2sh), std::move(segwit)}; + return Vector(std::move(p2pkh), std::move(p2sh), std::move(segwit)); } else { - return std::vector<CTxDestination>{std::move(keyid)}; + return Vector(std::move(p2pkh)); } } diff --git a/src/policy/fees.cpp b/src/policy/fees.cpp index 5d538606c2..8154bf105e 100644 --- a/src/policy/fees.cpp +++ b/src/policy/fees.cpp @@ -6,7 +6,6 @@ #include <policy/fees.h> #include <clientversion.h> -#include <primitives/transaction.h> #include <streams.h> #include <txmempool.h> #include <util/system.h> diff --git a/src/prevector.h b/src/prevector.h index 9d576321b6..d307495fbe 100644 --- a/src/prevector.h +++ b/src/prevector.h @@ -12,7 +12,6 @@ #include <algorithm> #include <cstddef> -#include <iterator> #include <type_traits> #pragma pack(push, 1) diff --git a/src/primitives/block.cpp b/src/primitives/block.cpp index 60c7c2d160..0c84ed6da2 100644 --- a/src/primitives/block.cpp +++ b/src/primitives/block.cpp @@ -7,7 +7,6 @@ #include <hash.h> #include <tinyformat.h> -#include <crypto/common.h> uint256 CBlockHeader::GetHash() const { diff --git a/src/protocol.h b/src/protocol.h index e6b25ffa25..3032310fa1 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -15,7 +15,6 @@ #include <uint256.h> #include <version.h> -#include <atomic> #include <stdint.h> #include <string> diff --git a/src/psbt.cpp b/src/psbt.cpp index fe74002e82..c306079b1e 100644 --- a/src/psbt.cpp +++ b/src/psbt.cpp @@ -5,7 +5,6 @@ #include <psbt.h> #include <util/strencodings.h> -#include <numeric> PartiallySignedTransaction::PartiallySignedTransaction(const CMutableTransaction& tx) : tx(tx) { diff --git a/src/pubkey.h b/src/pubkey.h index 089324ffda..fd815a871b 100644 --- a/src/pubkey.h +++ b/src/pubkey.h @@ -222,31 +222,6 @@ struct CExtPubKey { void Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const; void Decode(const unsigned char code[BIP32_EXTKEY_SIZE]); bool Derive(CExtPubKey& out, unsigned int nChild) const; - - void Serialize(CSizeComputer& s) const - { - // Optimized implementation for ::GetSerializeSize that avoids copying. - s.seek(BIP32_EXTKEY_SIZE + 1); // add one byte for the size (compact int) - } - template <typename Stream> - void Serialize(Stream& s) const - { - unsigned int len = BIP32_EXTKEY_SIZE; - ::WriteCompactSize(s, len); - unsigned char code[BIP32_EXTKEY_SIZE]; - Encode(code); - s.write((const char *)&code[0], len); - } - template <typename Stream> - void Unserialize(Stream& s) - { - unsigned int len = ::ReadCompactSize(s); - unsigned char code[BIP32_EXTKEY_SIZE]; - if (len != BIP32_EXTKEY_SIZE) - throw std::runtime_error("Invalid extended key size\n"); - s.read((char *)&code[0], len); - Decode(code); - } }; /** Users of this module must hold an ECCVerifyHandle. The constructor and diff --git a/src/qt/README.md b/src/qt/README.md index 0eb18f7cd5..30c68db15b 100644 --- a/src/qt/README.md +++ b/src/qt/README.md @@ -50,7 +50,7 @@ Various dialogs, e.g. to open a URL. Inherit from [QDialog](https://doc.qt.io/qt ### paymentserver.(h/cpp) -Used to process BIP21 and BIP70 (see https://github.com/bitcoin/bitcoin/pull/11622) payment URI / requests. Also handles URI based application switching (e.g. when following a bitcoin:... link from a browser). +Used to process BIP21 payment URI requests. Also handles URI based application switching (e.g. when following a bitcoin:... link from a browser). ### walletview.(h/cpp) diff --git a/src/qt/bantablemodel.cpp b/src/qt/bantablemodel.cpp index efc726e09e..ae11b80347 100644 --- a/src/qt/bantablemodel.cpp +++ b/src/qt/bantablemodel.cpp @@ -7,8 +7,6 @@ #include <qt/clientmodel.h> #include <interfaces/node.h> -#include <sync.h> -#include <util/time.h> #include <algorithm> diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index 86f4dc91a1..02a2a01bdd 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -10,7 +10,6 @@ #include <qt/bitcoingui.h> #include <chainparams.h> -#include <fs.h> #include <qt/clientmodel.h> #include <qt/guiconstants.h> #include <qt/guiutil.h> @@ -338,10 +337,6 @@ void BitcoinApplication::initializeResult(bool success) window->setWalletController(m_wallet_controller); if (paymentServer) { paymentServer->setOptionsModel(optionsModel); -#ifdef ENABLE_BIP70 - PaymentServer::LoadRootCAs(); - connect(m_wallet_controller, &WalletController::coinsSent, paymentServer, &PaymentServer::fetchPaymentACK); -#endif } } #endif // ENABLE_WALLET @@ -397,14 +392,10 @@ WId BitcoinApplication::getMainWinId() const static void SetupUIArgs() { -#if defined(ENABLE_WALLET) && defined(ENABLE_BIP70) - gArgs.AddArg("-allowselfsignedrootcertificates", strprintf("Allow self signed root certificates (default: %u)", DEFAULT_SELFSIGNED_ROOTCERTS), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::GUI); -#endif gArgs.AddArg("-choosedatadir", strprintf("Choose data directory on startup (default: %u)", DEFAULT_CHOOSE_DATADIR), ArgsManager::ALLOW_ANY, OptionsCategory::GUI); gArgs.AddArg("-lang=<lang>", "Set language, for example \"de_DE\" (default: system locale)", ArgsManager::ALLOW_ANY, OptionsCategory::GUI); gArgs.AddArg("-min", "Start minimized", ArgsManager::ALLOW_ANY, OptionsCategory::GUI); gArgs.AddArg("-resetguisettings", "Reset all settings changed in the GUI", ArgsManager::ALLOW_ANY, OptionsCategory::GUI); - gArgs.AddArg("-rootcertificates=<file>", "Set SSL root certificates for payment request (default: -system-)", ArgsManager::ALLOW_ANY, OptionsCategory::GUI); gArgs.AddArg("-splash", strprintf("Show splash screen on startup (default: %u)", DEFAULT_SPLASHSCREEN), ArgsManager::ALLOW_ANY, OptionsCategory::GUI); gArgs.AddArg("-uiplatform", strprintf("Select platform to customize UI for (one of windows, macosx, other; default: %s)", BitcoinGUI::DEFAULT_UIPLATFORM), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::GUI); } diff --git a/src/qt/bitcoinamountfield.cpp b/src/qt/bitcoinamountfield.cpp index 9fa49b87fa..23df1c929a 100644 --- a/src/qt/bitcoinamountfield.cpp +++ b/src/qt/bitcoinamountfield.cpp @@ -102,7 +102,7 @@ public: CAmount val = value(&valid); currentUnit = unit; - + lineEdit()->setPlaceholderText(BitcoinUnits::format(currentUnit, m_min_amount, false, BitcoinUnits::separatorAlways)); if(valid) setValue(val); else diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 2878a8eb14..2aeba6d82c 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -199,12 +199,12 @@ BitcoinGUI::BitcoinGUI(interfaces::Node& node, const PlatformStyle *_platformSty openOptionsDialogWithTab(OptionsDialog::TAB_NETWORK); }); - modalOverlay = new ModalOverlay(this->centralWidget()); + modalOverlay = new ModalOverlay(enableWallet, this->centralWidget()); + connect(labelBlocksIcon, &GUIUtil::ClickableLabel::clicked, this, &BitcoinGUI::showModalOverlay); + connect(progressBar, &GUIUtil::ClickableProgressBar::clicked, this, &BitcoinGUI::showModalOverlay); #ifdef ENABLE_WALLET if(enableWallet) { connect(walletFrame, &WalletFrame::requestedSyncWarningInfo, this, &BitcoinGUI::showModalOverlay); - connect(labelBlocksIcon, &GUIUtil::ClickableLabel::clicked, this, &BitcoinGUI::showModalOverlay); - connect(progressBar, &GUIUtil::ClickableProgressBar::clicked, this, &BitcoinGUI::showModalOverlay); } #endif @@ -330,7 +330,7 @@ void BitcoinGUI::createActions() usedReceivingAddressesAction->setStatusTip(tr("Show the list of used receiving addresses and labels")); openAction = new QAction(tr("Open &URI..."), this); - openAction->setStatusTip(tr("Open a bitcoin: URI or payment request")); + openAction->setStatusTip(tr("Open a bitcoin: URI")); m_open_wallet_action = new QAction(tr("Open Wallet"), this); m_open_wallet_action->setEnabled(false); @@ -796,7 +796,7 @@ void BitcoinGUI::showDebugWindow() void BitcoinGUI::showDebugWindowActivateConsole() { - rpcConsole->setTabFocus(RPCConsole::TAB_CONSOLE); + rpcConsole->setTabFocus(RPCConsole::TabTypes::CONSOLE); showDebugWindow(); } diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 238be08480..5b216b2705 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -19,6 +19,7 @@ #include <stdint.h> #include <QDebug> +#include <QThread> #include <QTimer> static int64_t nLastHeaderTipUpdateNotification = 0; @@ -30,15 +31,26 @@ ClientModel::ClientModel(interfaces::Node& node, OptionsModel *_optionsModel, QO optionsModel(_optionsModel), peerTableModel(nullptr), banTableModel(nullptr), - pollTimer(nullptr) + m_thread(new QThread(this)) { cachedBestHeaderHeight = -1; cachedBestHeaderTime = -1; peerTableModel = new PeerTableModel(m_node, this); banTableModel = new BanTableModel(m_node, this); - pollTimer = new QTimer(this); - connect(pollTimer, &QTimer::timeout, this, &ClientModel::updateTimer); - pollTimer->start(MODEL_UPDATE_DELAY); + + QTimer* timer = new QTimer; + timer->setInterval(MODEL_UPDATE_DELAY); + connect(timer, &QTimer::timeout, [this] { + // no locking required at this point + // the following calls will acquire the required lock + Q_EMIT mempoolSizeChanged(m_node.getMempoolSize(), m_node.getMempoolDynamicUsage()); + Q_EMIT bytesChanged(m_node.getTotalBytesRecv(), m_node.getTotalBytesSent()); + }); + connect(m_thread, &QThread::finished, timer, &QObject::deleteLater); + connect(m_thread, &QThread::started, [timer] { timer->start(); }); + // move timer to thread so that polling doesn't disturb main event loop + timer->moveToThread(m_thread); + m_thread->start(); subscribeToCoreSignals(); } @@ -46,6 +58,9 @@ ClientModel::ClientModel(interfaces::Node& node, OptionsModel *_optionsModel, QO ClientModel::~ClientModel() { unsubscribeFromCoreSignals(); + + m_thread->quit(); + m_thread->wait(); } int ClientModel::getNumConnections(unsigned int flags) const @@ -90,14 +105,6 @@ int64_t ClientModel::getHeaderTipTime() const return cachedBestHeaderTime; } -void ClientModel::updateTimer() -{ - // no locking required at this point - // the following calls will acquire the required lock - Q_EMIT mempoolSizeChanged(m_node.getMempoolSize(), m_node.getMempoolDynamicUsage()); - Q_EMIT bytesChanged(m_node.getTotalBytesRecv(), m_node.getTotalBytesSent()); -} - void ClientModel::updateNumConnections(int numConnections) { Q_EMIT numConnectionsChanged(numConnections); diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h index 95f4521f06..d3a95d531e 100644 --- a/src/qt/clientmodel.h +++ b/src/qt/clientmodel.h @@ -90,7 +90,8 @@ private: PeerTableModel *peerTableModel; BanTableModel *banTableModel; - QTimer *pollTimer; + //! A thread to interact with m_node asynchronously + QThread* const m_thread; void subscribeToCoreSignals(); void unsubscribeFromCoreSignals(); @@ -110,7 +111,6 @@ Q_SIGNALS: void showProgress(const QString &title, int nProgress); public Q_SLOTS: - void updateTimer(); void updateNumConnections(int numConnections); void updateNetworkActive(bool networkActive); void updateAlert(); diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp index 03d18d2845..f928f1ca2a 100644 --- a/src/qt/coincontroldialog.cpp +++ b/src/qt/coincontroldialog.cpp @@ -19,7 +19,6 @@ #include <wallet/coincontrol.h> #include <interfaces/node.h> #include <key_io.h> -#include <policy/fees.h> #include <policy/policy.h> #include <wallet/wallet.h> diff --git a/src/qt/forms/openuridialog.ui b/src/qt/forms/openuridialog.ui index 0e1048bc07..2acec314fd 100644 --- a/src/qt/forms/openuridialog.ui +++ b/src/qt/forms/openuridialog.ui @@ -11,17 +11,10 @@ </rect> </property> <property name="windowTitle"> - <string>Open URI</string> + <string>Open bitcoin URI</string> </property> <layout class="QVBoxLayout" name="verticalLayout"> <item> - <widget class="QLabel" name="label_2"> - <property name="text"> - <string>Open payment request from URI or file</string> - </property> - </widget> - </item> - <item> <layout class="QHBoxLayout" name="horizontalLayout"> <item> <widget class="QLabel" name="label"> @@ -33,19 +26,6 @@ <item> <widget class="QValidatedLineEdit" name="uriEdit"/> </item> - <item> - <widget class="QPushButton" name="selectFileButton"> - <property name="toolTip"> - <string>Select payment request file</string> - </property> - <property name="text"> - <string notr="true">…</string> - </property> - <property name="autoDefault"> - <bool>false</bool> - </property> - </widget> - </item> </layout> </item> <item> diff --git a/src/qt/forms/sendcoinsentry.ui b/src/qt/forms/sendcoinsentry.ui index 3c699abc6a..843d909f68 100644 --- a/src/qt/forms/sendcoinsentry.ui +++ b/src/qt/forms/sendcoinsentry.ui @@ -17,9 +17,6 @@ <bool>false</bool> </property> <widget class="QFrame" name="SendCoins"> - <property name="toolTip"> - <string>This is a normal payment.</string> - </property> <property name="frameShape"> <enum>QFrame::NoFrame</enum> </property> @@ -165,7 +162,11 @@ <item row="2" column="1"> <layout class="QHBoxLayout" name="horizontalLayoutAmount" stretch="0,1,0"> <item> - <widget class="BitcoinAmountField" name="payAmount"/> + <widget class="BitcoinAmountField" name="payAmount"> + <property name="toolTip"> + <string>The amount to send in the selected unit</string> + </property> + </widget> </item> <item> <widget class="QCheckBox" name="checkboxSubtractFeeFromAmount"> diff --git a/src/qt/forms/signverifymessagedialog.ui b/src/qt/forms/signverifymessagedialog.ui index c9ddd757c1..202edf27d4 100644 --- a/src/qt/forms/signverifymessagedialog.ui +++ b/src/qt/forms/signverifymessagedialog.ui @@ -99,6 +99,9 @@ <property name="toolTip"> <string>Enter the message you want to sign here</string> </property> + <property name="placeholderText"> + <string>Enter the message you want to sign here</string> + </property> </widget> </item> <item> @@ -285,10 +288,24 @@ </layout> </item> <item> - <widget class="QPlainTextEdit" name="messageIn_VM"/> + <widget class="QPlainTextEdit" name="messageIn_VM"> + <property name="toolTip"> + <string>The signed message to verify</string> + </property> + <property name="placeholderText"> + <string>The signed message to verify</string> + </property> + </widget> </item> <item> - <widget class="QValidatedLineEdit" name="signatureIn_VM"/> + <widget class="QValidatedLineEdit" name="signatureIn_VM"> + <property name="toolTip"> + <string>The signature given when the message was signed</string> + </property> + <property name="placeholderText"> + <string>The signature given when the message was signed</string> + </property> + </widget> </item> <item> <layout class="QHBoxLayout" name="horizontalLayout_2_VM"> diff --git a/src/qt/modaloverlay.cpp b/src/qt/modaloverlay.cpp index 8ecc33da84..efdd494d9f 100644 --- a/src/qt/modaloverlay.cpp +++ b/src/qt/modaloverlay.cpp @@ -12,7 +12,7 @@ #include <QResizeEvent> #include <QPropertyAnimation> -ModalOverlay::ModalOverlay(QWidget *parent) : +ModalOverlay::ModalOverlay(bool enable_wallet, QWidget *parent) : QWidget(parent), ui(new Ui::ModalOverlay), bestHeaderHeight(0), @@ -29,6 +29,10 @@ userClosed(false) blockProcessTime.clear(); setVisible(false); + if (!enable_wallet) { + ui->infoText->setVisible(false); + ui->infoTextStrong->setText(tr("Bitcoin Core is currently syncing. It will download headers and blocks from peers and validate them until reaching the tip of the block chain.")); + } } ModalOverlay::~ModalOverlay() diff --git a/src/qt/modaloverlay.h b/src/qt/modaloverlay.h index cf8b53f2b3..c075a89f94 100644 --- a/src/qt/modaloverlay.h +++ b/src/qt/modaloverlay.h @@ -21,7 +21,7 @@ class ModalOverlay : public QWidget Q_OBJECT public: - explicit ModalOverlay(QWidget *parent); + explicit ModalOverlay(bool enable_wallet, QWidget *parent); ~ModalOverlay(); public Q_SLOTS: diff --git a/src/qt/openuridialog.cpp b/src/qt/openuridialog.cpp index 48db95679f..199804f84d 100644 --- a/src/qt/openuridialog.cpp +++ b/src/qt/openuridialog.cpp @@ -39,12 +39,3 @@ void OpenURIDialog::accept() ui->uriEdit->setValid(false); } } - -void OpenURIDialog::on_selectFileButton_clicked() -{ - QString filename = GUIUtil::getOpenFileName(this, tr("Select payment request file to open"), "", "", nullptr); - if(filename.isEmpty()) - return; - QUrl fileUri = QUrl::fromLocalFile(filename); - ui->uriEdit->setText("bitcoin:?r=" + QUrl::toPercentEncoding(fileUri.toString())); -} diff --git a/src/qt/openuridialog.h b/src/qt/openuridialog.h index e94593d5bb..8438f22bd7 100644 --- a/src/qt/openuridialog.h +++ b/src/qt/openuridialog.h @@ -24,9 +24,6 @@ public: protected Q_SLOTS: void accept(); -private Q_SLOTS: - void on_selectFileButton_clicked(); - private: Ui::OpenURIDialog *ui; }; diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index d047a82475..d74d0dbfeb 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -18,7 +18,7 @@ #include <netbase.h> #include <txdb.h> // for -dbcache defaults -#include <QNetworkProxy> +#include <QDebug> #include <QSettings> #include <QStringList> @@ -483,24 +483,6 @@ void OptionsModel::setDisplayUnit(const QVariant &value) } } -bool OptionsModel::getProxySettings(QNetworkProxy& proxy) const -{ - // Directly query current base proxy, because - // GUI settings can be overridden with -proxy. - proxyType curProxy; - if (m_node.getProxy(NET_IPV4, curProxy)) { - proxy.setType(QNetworkProxy::Socks5Proxy); - proxy.setHostName(QString::fromStdString(curProxy.proxy.ToStringIP())); - proxy.setPort(curProxy.proxy.GetPort()); - - return true; - } - else - proxy.setType(QNetworkProxy::NoProxy); - - return false; -} - void OptionsModel::setRestartRequired(bool fRequired) { QSettings settings; diff --git a/src/qt/optionsmodel.h b/src/qt/optionsmodel.h index b1231b7c7d..5791b47f28 100644 --- a/src/qt/optionsmodel.h +++ b/src/qt/optionsmodel.h @@ -13,10 +13,6 @@ namespace interfaces { class Node; } -QT_BEGIN_NAMESPACE -class QNetworkProxy; -QT_END_NAMESPACE - extern const char *DEFAULT_GUI_PROXY_HOST; static constexpr unsigned short DEFAULT_GUI_PROXY_PORT = 9050; @@ -73,7 +69,6 @@ public: bool getMinimizeOnClose() const { return fMinimizeOnClose; } int getDisplayUnit() const { return nDisplayUnit; } QString getThirdPartyTxUrls() const { return strThirdPartyTxUrls; } - bool getProxySettings(QNetworkProxy& proxy) const; bool getCoinControlFeatures() const { return fCoinControlFeatures; } const QString& getOverriddenByCommandLine() { return strOverriddenByCommandLine; } diff --git a/src/qt/paymentrequest.proto b/src/qt/paymentrequest.proto deleted file mode 100644 index d2721a34bd..0000000000 --- a/src/qt/paymentrequest.proto +++ /dev/null @@ -1,48 +0,0 @@ -// -// Simple Bitcoin Payment Protocol messages -// -// Use fields 100+ for extensions; -// to avoid conflicts, register extensions at: -// https://en.bitcoin.it/wiki/Payment_Request -// - -syntax = "proto2"; - -package payments; -option java_package = "org.bitcoin.protocols.payments"; -option java_outer_classname = "Protos"; - -// Generalized form of "send payment to this/these bitcoin addresses" -message Output { - optional uint64 amount = 1 [default = 0]; // amount is integer-number-of-satoshis - required bytes script = 2; // usually one of the standard Script forms -} -message PaymentDetails { - optional string network = 1 [default = "main"]; // "main" or "test" - repeated Output outputs = 2; // Where payment should be sent - required uint64 time = 3; // Timestamp; when payment request created - optional uint64 expires = 4; // Timestamp; when this request should be considered invalid - optional string memo = 5; // Human-readable description of request for the customer - optional string payment_url = 6; // URL to send Payment and get PaymentACK - optional bytes merchant_data = 7; // Arbitrary data to include in the Payment message -} -message PaymentRequest { - optional uint32 payment_details_version = 1 [default = 1]; - optional string pki_type = 2 [default = "none"]; // none / x509+sha256 / x509+sha1 - optional bytes pki_data = 3; // depends on pki_type - required bytes serialized_payment_details = 4; // PaymentDetails - optional bytes signature = 5; // pki-dependent signature -} -message X509Certificates { - repeated bytes certificate = 1; // DER-encoded X.509 certificate chain -} -message Payment { - optional bytes merchant_data = 1; // From PaymentDetails.merchant_data - repeated bytes transactions = 2; // Signed transactions that satisfy PaymentDetails.outputs - repeated Output refund_to = 3; // Where to send refunds, if a refund is necessary - optional string memo = 4; // Human-readable message for the merchant -} -message PaymentACK { - required Payment payment = 1; // Payment message that triggered this ACK - optional string memo = 2; // human-readable message for customer -} diff --git a/src/qt/paymentrequestplus.cpp b/src/qt/paymentrequestplus.cpp deleted file mode 100644 index b962ab1ef2..0000000000 --- a/src/qt/paymentrequestplus.cpp +++ /dev/null @@ -1,213 +0,0 @@ -// Copyright (c) 2011-2018 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -// -// Wraps dumb protocol buffer paymentRequest -// with some extra methods -// - -#include <qt/paymentrequestplus.h> - -#include <util/system.h> - -#include <stdexcept> - -#include <openssl/x509_vfy.h> - -#include <QDateTime> -#include <QDebug> -#include <QSslCertificate> - -class SSLVerifyError : public std::runtime_error -{ -public: - explicit SSLVerifyError(std::string err) : std::runtime_error(err) { } -}; - -bool PaymentRequestPlus::parse(const QByteArray& data) -{ - bool parseOK = paymentRequest.ParseFromArray(data.data(), data.size()); - if (!parseOK) { - qWarning() << "PaymentRequestPlus::parse: Error parsing payment request"; - return false; - } - if (paymentRequest.payment_details_version() > 1) { - qWarning() << "PaymentRequestPlus::parse: Received up-version payment details, version=" << paymentRequest.payment_details_version(); - return false; - } - - parseOK = details.ParseFromString(paymentRequest.serialized_payment_details()); - if (!parseOK) - { - qWarning() << "PaymentRequestPlus::parse: Error parsing payment details"; - paymentRequest.Clear(); - return false; - } - return true; -} - -bool PaymentRequestPlus::SerializeToString(std::string* output) const -{ - return paymentRequest.SerializeToString(output); -} - -bool PaymentRequestPlus::IsInitialized() const -{ - return paymentRequest.IsInitialized(); -} - -bool PaymentRequestPlus::getMerchant(X509_STORE* certStore, QString& merchant) const -{ - merchant.clear(); - - if (!IsInitialized()) - return false; - - // One day we'll support more PKI types, but just - // x509 for now: - const EVP_MD* digestAlgorithm = nullptr; - if (paymentRequest.pki_type() == "x509+sha256") { - digestAlgorithm = EVP_sha256(); - } - else if (paymentRequest.pki_type() == "x509+sha1") { - digestAlgorithm = EVP_sha1(); - } - else if (paymentRequest.pki_type() == "none") { - qWarning() << "PaymentRequestPlus::getMerchant: Payment request: pki_type == none"; - return false; - } - else { - qWarning() << "PaymentRequestPlus::getMerchant: Payment request: unknown pki_type " << QString::fromStdString(paymentRequest.pki_type()); - return false; - } - - payments::X509Certificates certChain; - if (!certChain.ParseFromString(paymentRequest.pki_data())) { - qWarning() << "PaymentRequestPlus::getMerchant: Payment request: error parsing pki_data"; - return false; - } - - std::vector<X509*> certs; - const QDateTime currentTime = QDateTime::currentDateTime(); - for (int i = 0; i < certChain.certificate_size(); i++) { - QByteArray certData(certChain.certificate(i).data(), certChain.certificate(i).size()); - QSslCertificate qCert(certData, QSsl::Der); - if (currentTime < qCert.effectiveDate() || currentTime > qCert.expiryDate()) { - qWarning() << "PaymentRequestPlus::getMerchant: Payment request: certificate expired or not yet active: " << qCert; - return false; - } - if (qCert.isBlacklisted()) { - qWarning() << "PaymentRequestPlus::getMerchant: Payment request: certificate blacklisted: " << qCert; - return false; - } - const unsigned char *data = (const unsigned char *)certChain.certificate(i).data(); - X509 *cert = d2i_X509(nullptr, &data, certChain.certificate(i).size()); - if (cert) - certs.push_back(cert); - } - if (certs.empty()) { - qWarning() << "PaymentRequestPlus::getMerchant: Payment request: empty certificate chain"; - return false; - } - - // The first cert is the signing cert, the rest are untrusted certs that chain - // to a valid root authority. OpenSSL needs them separately. - STACK_OF(X509) *chain = sk_X509_new_null(); - for (int i = certs.size() - 1; i > 0; i--) { - sk_X509_push(chain, certs[i]); - } - X509 *signing_cert = certs[0]; - - // Now create a "store context", which is a single use object for checking, - // load the signing cert into it and verify. - X509_STORE_CTX *store_ctx = X509_STORE_CTX_new(); - if (!store_ctx) { - qWarning() << "PaymentRequestPlus::getMerchant: Payment request: error creating X509_STORE_CTX"; - return false; - } - - char *website = nullptr; - bool fResult = true; - try - { - if (!X509_STORE_CTX_init(store_ctx, certStore, signing_cert, chain)) - { - int error = X509_STORE_CTX_get_error(store_ctx); - throw SSLVerifyError(X509_verify_cert_error_string(error)); - } - - // Now do the verification! - int result = X509_verify_cert(store_ctx); - if (result != 1) { - int error = X509_STORE_CTX_get_error(store_ctx); - // For testing payment requests, we allow self signed root certs! - if (!(error == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT && gArgs.GetBoolArg("-allowselfsignedrootcertificates", DEFAULT_SELFSIGNED_ROOTCERTS))) { - throw SSLVerifyError(X509_verify_cert_error_string(error)); - } else { - qDebug() << "PaymentRequestPlus::getMerchant: Allowing self signed root certificate, because -allowselfsignedrootcertificates is true."; - } - } - X509_NAME *certname = X509_get_subject_name(signing_cert); - - // Valid cert; check signature: - payments::PaymentRequest rcopy(paymentRequest); // Copy - rcopy.set_signature(std::string("")); - std::string data_to_verify; // Everything but the signature - rcopy.SerializeToString(&data_to_verify); - -#if HAVE_DECL_EVP_MD_CTX_NEW - EVP_MD_CTX *ctx = EVP_MD_CTX_new(); - if (!ctx) throw SSLVerifyError("Error allocating OpenSSL context."); -#else - EVP_MD_CTX _ctx; - EVP_MD_CTX *ctx; - ctx = &_ctx; -#endif - EVP_PKEY *pubkey = X509_get_pubkey(signing_cert); - EVP_MD_CTX_init(ctx); - if (!EVP_VerifyInit_ex(ctx, digestAlgorithm, nullptr) || - !EVP_VerifyUpdate(ctx, data_to_verify.data(), data_to_verify.size()) || - !EVP_VerifyFinal(ctx, (const unsigned char*)paymentRequest.signature().data(), (unsigned int)paymentRequest.signature().size(), pubkey)) { - throw SSLVerifyError("Bad signature, invalid payment request."); - } -#if HAVE_DECL_EVP_MD_CTX_NEW - EVP_MD_CTX_free(ctx); -#endif - - // OpenSSL API for getting human printable strings from certs is baroque. - int textlen = X509_NAME_get_text_by_NID(certname, NID_commonName, nullptr, 0); - website = new char[textlen + 1]; - if (X509_NAME_get_text_by_NID(certname, NID_commonName, website, textlen + 1) == textlen && textlen > 0) { - merchant = website; - } - else { - throw SSLVerifyError("Bad certificate, missing common name."); - } - // TODO: detect EV certificates and set merchant = business name instead of unfriendly NID_commonName ? - } - catch (const SSLVerifyError& err) { - fResult = false; - qWarning() << "PaymentRequestPlus::getMerchant: SSL error: " << err.what(); - } - - delete[] website; - X509_STORE_CTX_free(store_ctx); - for (unsigned int i = 0; i < certs.size(); i++) - X509_free(certs[i]); - - return fResult; -} - -QList<std::pair<CScript,CAmount> > PaymentRequestPlus::getPayTo() const -{ - QList<std::pair<CScript,CAmount> > result; - for (int i = 0; i < details.outputs_size(); i++) - { - const unsigned char* scriptStr = (const unsigned char*)details.outputs(i).script().data(); - CScript s(scriptStr, scriptStr+details.outputs(i).script().size()); - - result.append(std::make_pair(s, details.outputs(i).amount())); - } - return result; -} diff --git a/src/qt/paymentrequestplus.h b/src/qt/paymentrequestplus.h deleted file mode 100644 index 3014628807..0000000000 --- a/src/qt/paymentrequestplus.h +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) 2011-2018 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#ifndef BITCOIN_QT_PAYMENTREQUESTPLUS_H -#define BITCOIN_QT_PAYMENTREQUESTPLUS_H - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#include <qt/paymentrequest.pb.h> -#pragma GCC diagnostic pop - -#include <amount.h> -#include <script/script.h> - -#include <openssl/x509.h> - -#include <QByteArray> -#include <QList> -#include <QString> - -static const bool DEFAULT_SELFSIGNED_ROOTCERTS = false; - -// -// Wraps dumb protocol buffer paymentRequest -// with extra methods -// - -class PaymentRequestPlus -{ -public: - PaymentRequestPlus() { } - - bool parse(const QByteArray& data); - bool SerializeToString(std::string* output) const; - - bool IsInitialized() const; - // Returns true if merchant's identity is authenticated, and - // returns human-readable merchant identity in merchant - bool getMerchant(X509_STORE* certStore, QString& merchant) const; - - // Returns list of outputs, amount - QList<std::pair<CScript,CAmount> > getPayTo() const; - - const payments::PaymentDetails& getDetails() const { return details; } - -private: - payments::PaymentRequest paymentRequest; - payments::PaymentDetails details; -}; - -#endif // BITCOIN_QT_PAYMENTREQUESTPLUS_H diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp index 806cc3c41e..6ad219ca2d 100644 --- a/src/qt/paymentserver.cpp +++ b/src/qt/paymentserver.cpp @@ -23,8 +23,6 @@ #include <cstdlib> #include <memory> -#include <openssl/x509_vfy.h> - #include <QApplication> #include <QByteArray> #include <QDataStream> @@ -36,28 +34,11 @@ #include <QList> #include <QLocalServer> #include <QLocalSocket> -#include <QNetworkAccessManager> -#include <QNetworkProxy> -#include <QNetworkReply> -#include <QNetworkRequest> -#include <QSslCertificate> -#include <QSslConfiguration> -#include <QSslError> #include <QStringList> -#include <QTextDocument> #include <QUrlQuery> const int BITCOIN_IPC_CONNECT_TIMEOUT = 1000; // milliseconds const QString BITCOIN_IPC_PREFIX("bitcoin:"); -#ifdef ENABLE_BIP70 -// BIP70 payment protocol messages -const char* BIP70_MESSAGE_PAYMENTACK = "PaymentACK"; -const char* BIP70_MESSAGE_PAYMENTREQUEST = "PaymentRequest"; -// BIP71 payment protocol media types -const char* BIP71_MIMETYPE_PAYMENT = "application/bitcoin-payment"; -const char* BIP71_MIMETYPE_PAYMENTACK = "application/bitcoin-paymentack"; -const char* BIP71_MIMETYPE_PAYMENTREQUEST = "application/bitcoin-paymentrequest"; -#endif // // Create a name that is unique for: @@ -125,32 +106,6 @@ void PaymentServer::ipcParseCommandLine(interfaces::Node& node, int argc, char* } } } -#ifdef ENABLE_BIP70 - else if (QFile::exists(arg)) // Filename - { - if (savedPaymentRequests.contains(arg)) continue; - savedPaymentRequests.insert(arg); - - PaymentRequestPlus request; - if (readPaymentRequestFromFile(arg, request)) - { - if (request.getDetails().network() == "main") - { - node.selectParams(CBaseChainParams::MAIN); - } - else if (request.getDetails().network() == "test") - { - node.selectParams(CBaseChainParams::TESTNET); - } - } - } - else - { - // Printing to debug.log is about the best we can do here, the - // GUI hasn't started yet so we can't pop up a message box. - qWarning() << "PaymentServer::ipcSendCommandLine: Payment request file does not exist: " << arg; - } -#endif } } @@ -198,16 +153,7 @@ PaymentServer::PaymentServer(QObject* parent, bool startLocalServer) : saveURIs(true), uriServer(nullptr), optionsModel(nullptr) -#ifdef ENABLE_BIP70 - ,netManager(nullptr) -#endif { -#ifdef ENABLE_BIP70 - // Verify that the version of the library that we linked against is - // compatible with the version of the headers we compiled against. - GOOGLE_PROTOBUF_VERIFY_VERSION; -#endif - // Install global event filter to catch QFileOpenEvents // on Mac: sent when you click bitcoin: links // other OSes: helpful when dealing with payment request files @@ -230,24 +176,16 @@ PaymentServer::PaymentServer(QObject* parent, bool startLocalServer) : } else { connect(uriServer, &QLocalServer::newConnection, this, &PaymentServer::handleURIConnection); -#ifdef ENABLE_BIP70 - connect(this, &PaymentServer::receivedPaymentACK, this, &PaymentServer::handlePaymentACK); -#endif } } } PaymentServer::~PaymentServer() { -#ifdef ENABLE_BIP70 - google::protobuf::ShutdownProtobufLibrary(); -#endif } // -// OSX-specific way of handling bitcoin: URIs and PaymentRequest mime types. -// Also used by paymentservertests.cpp and when opening a payment request file -// via "Open URI..." menu entry. +// OSX-specific way of handling bitcoin: URIs // bool PaymentServer::eventFilter(QObject *object, QEvent *event) { @@ -266,10 +204,6 @@ bool PaymentServer::eventFilter(QObject *object, QEvent *event) void PaymentServer::uiReady() { -#ifdef ENABLE_BIP70 - initNetManager(); -#endif - saveURIs = false; for (const QString& s : savedPaymentRequests) { @@ -294,48 +228,19 @@ void PaymentServer::handleURIOrFile(const QString& s) else if (s.startsWith(BITCOIN_IPC_PREFIX, Qt::CaseInsensitive)) // bitcoin: URI { QUrlQuery uri((QUrl(s))); -#ifdef ENABLE_BIP70 - if (uri.hasQueryItem("r")) // payment request URI - { - Q_EMIT message(tr("URI handling"), - tr("You are using a BIP70 URL which will be unsupported in the future."), - CClientUIInterface::ICON_WARNING); - QByteArray temp; - temp.append(uri.queryItemValue("r")); - QString decoded = QUrl::fromPercentEncoding(temp); - QUrl fetchUrl(decoded, QUrl::StrictMode); - - if (fetchUrl.isValid()) - { - qDebug() << "PaymentServer::handleURIOrFile: fetchRequest(" << fetchUrl << ")"; - fetchRequest(fetchUrl); - } - else - { - qWarning() << "PaymentServer::handleURIOrFile: Invalid URL: " << fetchUrl; - Q_EMIT message(tr("URI handling"), - tr("Payment request fetch URL is invalid: %1").arg(fetchUrl.toString()), - CClientUIInterface::ICON_WARNING); - } - return; - } - else -#endif // normal URI { SendCoinsRecipient recipient; if (GUIUtil::parseBitcoinURI(s, &recipient)) { if (!IsValidDestinationString(recipient.address.toStdString())) { -#ifndef ENABLE_BIP70 if (uri.hasQueryItem("r")) { // payment request Q_EMIT message(tr("URI handling"), - tr("Cannot process payment request because BIP70 support was not compiled in.")+ + tr("Cannot process payment request because BIP70 is not supported.")+ tr("Due to widespread security flaws in BIP70 it's strongly recommended that any merchant instructions to switch wallets be ignored.")+ tr("If you are receiving this error you should request the merchant provide a BIP21 compatible URI."), CClientUIInterface::ICON_WARNING); } -#endif Q_EMIT message(tr("URI handling"), tr("Invalid payment address %1").arg(recipient.address), CClientUIInterface::MSG_ERROR); } @@ -353,26 +258,11 @@ void PaymentServer::handleURIOrFile(const QString& s) if (QFile::exists(s)) // payment request file { -#ifdef ENABLE_BIP70 - PaymentRequestPlus request; - SendCoinsRecipient recipient; - if (!readPaymentRequestFromFile(s, request)) - { - Q_EMIT message(tr("Payment request file handling"), - tr("Payment request file cannot be read! This can be caused by an invalid payment request file."), - CClientUIInterface::ICON_WARNING); - } - else if (processPaymentRequest(request, recipient)) - Q_EMIT receivedPaymentRequest(recipient); - - return; -#else Q_EMIT message(tr("Payment request file handling"), - tr("Cannot process payment request because BIP70 support was not compiled in.")+ + tr("Cannot process payment request because BIP70 is not supported.")+ tr("Due to widespread security flaws in BIP70 it's strongly recommended that any merchant instructions to switch wallets be ignored.")+ tr("If you are receiving this error you should request the merchant provide a BIP21 compatible URI."), CClientUIInterface::ICON_WARNING); -#endif } } @@ -400,440 +290,3 @@ void PaymentServer::setOptionsModel(OptionsModel *_optionsModel) { this->optionsModel = _optionsModel; } - -#ifdef ENABLE_BIP70 -struct X509StoreDeleter { - void operator()(X509_STORE* b) { - X509_STORE_free(b); - } -}; - -struct X509Deleter { - void operator()(X509* b) { X509_free(b); } -}; - -namespace // Anon namespace -{ - std::unique_ptr<X509_STORE, X509StoreDeleter> certStore; -} - -static void ReportInvalidCertificate(const QSslCertificate& cert) -{ - qDebug() << QString("%1: Payment server found an invalid certificate: ").arg(__func__) << cert.serialNumber() << cert.subjectInfo(QSslCertificate::CommonName) << cert.subjectInfo(QSslCertificate::DistinguishedNameQualifier) << cert.subjectInfo(QSslCertificate::OrganizationalUnitName); -} - -// -// Load OpenSSL's list of root certificate authorities -// -void PaymentServer::LoadRootCAs(X509_STORE* _store) -{ - // Unit tests mostly use this, to pass in fake root CAs: - if (_store) - { - certStore.reset(_store); - return; - } - - // Normal execution, use either -rootcertificates or system certs: - certStore.reset(X509_STORE_new()); - - // Note: use "-system-" default here so that users can pass -rootcertificates="" - // and get 'I don't like X.509 certificates, don't trust anybody' behavior: - QString certFile = QString::fromStdString(gArgs.GetArg("-rootcertificates", "-system-")); - - // Empty store - if (certFile.isEmpty()) { - qDebug() << QString("PaymentServer::%1: Payment request authentication via X.509 certificates disabled.").arg(__func__); - return; - } - - QList<QSslCertificate> certList; - - if (certFile != "-system-") { - qDebug() << QString("PaymentServer::%1: Using \"%2\" as trusted root certificate.").arg(__func__).arg(certFile); - - certList = QSslCertificate::fromPath(certFile); - // Use those certificates when fetching payment requests, too: - QSslConfiguration::defaultConfiguration().setCaCertificates(certList); - } else - certList = QSslConfiguration::systemCaCertificates(); - - int nRootCerts = 0; - const QDateTime currentTime = QDateTime::currentDateTime(); - - for (const QSslCertificate& cert : certList) { - // Don't log NULL certificates - if (cert.isNull()) - continue; - - // Not yet active/valid, or expired certificate - if (currentTime < cert.effectiveDate() || currentTime > cert.expiryDate()) { - ReportInvalidCertificate(cert); - continue; - } - - // Blacklisted certificate - if (cert.isBlacklisted()) { - ReportInvalidCertificate(cert); - continue; - } - - QByteArray certData = cert.toDer(); - const unsigned char *data = (const unsigned char *)certData.data(); - - std::unique_ptr<X509, X509Deleter> x509(d2i_X509(0, &data, certData.size())); - if (x509 && X509_STORE_add_cert(certStore.get(), x509.get())) - { - // Note: X509_STORE increases the reference count to the X509 object, - // we still have to release our reference to it. - ++nRootCerts; - } - else - { - ReportInvalidCertificate(cert); - continue; - } - } - qInfo() << "PaymentServer::LoadRootCAs: Loaded " << nRootCerts << " root certificates"; - - // Project for another day: - // Fetch certificate revocation lists, and add them to certStore. - // Issues to consider: - // performance (start a thread to fetch in background?) - // privacy (fetch through tor/proxy so IP address isn't revealed) - // would it be easier to just use a compiled-in blacklist? - // or use Qt's blacklist? - // "certificate stapling" with server-side caching is more efficient -} - -void PaymentServer::initNetManager() -{ - if (!optionsModel) - return; - delete netManager; - - // netManager is used to fetch paymentrequests given in bitcoin: URIs - netManager = new QNetworkAccessManager(this); - - QNetworkProxy proxy; - - // Query active SOCKS5 proxy - if (optionsModel->getProxySettings(proxy)) { - netManager->setProxy(proxy); - - qDebug() << "PaymentServer::initNetManager: Using SOCKS5 proxy" << proxy.hostName() << ":" << proxy.port(); - } - else - qDebug() << "PaymentServer::initNetManager: No active proxy server found."; - - connect(netManager, &QNetworkAccessManager::finished, this, &PaymentServer::netRequestFinished); - connect(netManager, &QNetworkAccessManager::sslErrors, this, &PaymentServer::reportSslErrors); -} - -// -// Warning: readPaymentRequestFromFile() is used in ipcSendCommandLine() -// so don't use "Q_EMIT message()", but "QMessageBox::"! -// -bool PaymentServer::readPaymentRequestFromFile(const QString& filename, PaymentRequestPlus& request) -{ - QFile f(filename); - if (!f.open(QIODevice::ReadOnly)) { - qWarning() << QString("PaymentServer::%1: Failed to open %2").arg(__func__).arg(filename); - return false; - } - - // BIP70 DoS protection - if (!verifySize(f.size())) { - return false; - } - - QByteArray data = f.readAll(); - - return request.parse(data); -} - -bool PaymentServer::processPaymentRequest(const PaymentRequestPlus& request, SendCoinsRecipient& recipient) -{ - if (!optionsModel) - return false; - - if (request.IsInitialized()) { - // Payment request network matches client network? - if (!verifyNetwork(optionsModel->node(), request.getDetails())) { - Q_EMIT message(tr("Payment request rejected"), tr("Payment request network doesn't match client network."), - CClientUIInterface::MSG_ERROR); - - return false; - } - - // Make sure any payment requests involved are still valid. - // This is re-checked just before sending coins in WalletModel::sendCoins(). - if (verifyExpired(request.getDetails())) { - Q_EMIT message(tr("Payment request rejected"), tr("Payment request expired."), - CClientUIInterface::MSG_ERROR); - - return false; - } - } else { - Q_EMIT message(tr("Payment request error"), tr("Payment request is not initialized."), - CClientUIInterface::MSG_ERROR); - - return false; - } - - recipient.paymentRequest = request; - recipient.message = GUIUtil::HtmlEscape(request.getDetails().memo()); - - request.getMerchant(certStore.get(), recipient.authenticatedMerchant); - - QList<std::pair<CScript, CAmount> > sendingTos = request.getPayTo(); - QStringList addresses; - - for (const std::pair<CScript, CAmount>& sendingTo : sendingTos) { - // Extract and check destination addresses - CTxDestination dest; - if (ExtractDestination(sendingTo.first, dest)) { - // Append destination address - addresses.append(QString::fromStdString(EncodeDestination(dest))); - } - else if (!recipient.authenticatedMerchant.isEmpty()) { - // Unauthenticated payment requests to custom bitcoin addresses are not supported - // (there is no good way to tell the user where they are paying in a way they'd - // have a chance of understanding). - Q_EMIT message(tr("Payment request rejected"), - tr("Unverified payment requests to custom payment scripts are unsupported."), - CClientUIInterface::MSG_ERROR); - return false; - } - - // Bitcoin amounts are stored as (optional) uint64 in the protobuf messages (see paymentrequest.proto), - // but CAmount is defined as int64_t. Because of that we need to verify that amounts are in a valid range - // and no overflow has happened. - if (!verifyAmount(sendingTo.second)) { - Q_EMIT message(tr("Payment request rejected"), tr("Invalid payment request."), CClientUIInterface::MSG_ERROR); - return false; - } - - // Extract and check amounts - CTxOut txOut(sendingTo.second, sendingTo.first); - if (IsDust(txOut, optionsModel->node().getDustRelayFee())) { - Q_EMIT message(tr("Payment request error"), tr("Requested payment amount of %1 is too small (considered dust).") - .arg(BitcoinUnits::formatWithUnit(optionsModel->getDisplayUnit(), sendingTo.second)), - CClientUIInterface::MSG_ERROR); - - return false; - } - - recipient.amount += sendingTo.second; - // Also verify that the final amount is still in a valid range after adding additional amounts. - if (!verifyAmount(recipient.amount)) { - Q_EMIT message(tr("Payment request rejected"), tr("Invalid payment request."), CClientUIInterface::MSG_ERROR); - return false; - } - } - // Store addresses and format them to fit nicely into the GUI - recipient.address = addresses.join("<br />"); - - if (!recipient.authenticatedMerchant.isEmpty()) { - qDebug() << "PaymentServer::processPaymentRequest: Secure payment request from " << recipient.authenticatedMerchant; - } - else { - qDebug() << "PaymentServer::processPaymentRequest: Insecure payment request to " << addresses.join(", "); - } - - return true; -} - -void PaymentServer::fetchRequest(const QUrl& url) -{ - QNetworkRequest netRequest; - netRequest.setAttribute(QNetworkRequest::User, BIP70_MESSAGE_PAYMENTREQUEST); - netRequest.setUrl(url); - netRequest.setRawHeader("User-Agent", CLIENT_NAME.c_str()); - netRequest.setRawHeader("Accept", BIP71_MIMETYPE_PAYMENTREQUEST); - netManager->get(netRequest); -} - -void PaymentServer::fetchPaymentACK(WalletModel* walletModel, const SendCoinsRecipient& recipient, QByteArray transaction) -{ - const payments::PaymentDetails& details = recipient.paymentRequest.getDetails(); - if (!details.has_payment_url()) - return; - - QNetworkRequest netRequest; - netRequest.setAttribute(QNetworkRequest::User, BIP70_MESSAGE_PAYMENTACK); - netRequest.setUrl(QString::fromStdString(details.payment_url())); - netRequest.setHeader(QNetworkRequest::ContentTypeHeader, BIP71_MIMETYPE_PAYMENT); - netRequest.setRawHeader("User-Agent", CLIENT_NAME.c_str()); - netRequest.setRawHeader("Accept", BIP71_MIMETYPE_PAYMENTACK); - - payments::Payment payment; - payment.set_merchant_data(details.merchant_data()); - payment.add_transactions(transaction.data(), transaction.size()); - - // Create a new refund address, or re-use: - CTxDestination dest; - const OutputType change_type = walletModel->wallet().getDefaultChangeType() != OutputType::CHANGE_AUTO ? walletModel->wallet().getDefaultChangeType() : walletModel->wallet().getDefaultAddressType(); - if (walletModel->wallet().getNewDestination(change_type, "", dest)) { - // BIP70 requests encode the scriptPubKey directly, so we are not restricted to address - // types supported by the receiver. As a result, we choose the address format we also - // use for change. Despite an actual payment and not change, this is a close match: - // it's the output type we use subject to privacy issues, but not restricted by what - // other software supports. - std::string label = tr("Refund from %1").arg(recipient.authenticatedMerchant).toStdString(); - walletModel->wallet().setAddressBook(dest, label, "refund"); - - CScript s = GetScriptForDestination(dest); - payments::Output* refund_to = payment.add_refund_to(); - refund_to->set_script(&s[0], s.size()); - } else { - // This should never happen, because sending coins should have - // just unlocked the wallet and refilled the keypool. - qWarning() << "PaymentServer::fetchPaymentACK: Error getting refund key, refund_to not set"; - } - - int length = payment.ByteSize(); - netRequest.setHeader(QNetworkRequest::ContentLengthHeader, length); - QByteArray serData(length, '\0'); - if (payment.SerializeToArray(serData.data(), length)) { - netManager->post(netRequest, serData); - } - else { - // This should never happen, either. - qWarning() << "PaymentServer::fetchPaymentACK: Error serializing payment message"; - } -} - -void PaymentServer::netRequestFinished(QNetworkReply* reply) -{ - reply->deleteLater(); - - // BIP70 DoS protection - if (!verifySize(reply->size())) { - Q_EMIT message(tr("Payment request rejected"), - tr("Payment request %1 is too large (%2 bytes, allowed %3 bytes).") - .arg(reply->request().url().toString()) - .arg(reply->size()) - .arg(BIP70_MAX_PAYMENTREQUEST_SIZE), - CClientUIInterface::MSG_ERROR); - return; - } - - if (reply->error() != QNetworkReply::NoError) { - QString msg = tr("Error communicating with %1: %2") - .arg(reply->request().url().toString()) - .arg(reply->errorString()); - - qWarning() << "PaymentServer::netRequestFinished: " << msg; - Q_EMIT message(tr("Payment request error"), msg, CClientUIInterface::MSG_ERROR); - return; - } - - QByteArray data = reply->readAll(); - - QString requestType = reply->request().attribute(QNetworkRequest::User).toString(); - if (requestType == BIP70_MESSAGE_PAYMENTREQUEST) - { - PaymentRequestPlus request; - SendCoinsRecipient recipient; - if (!request.parse(data)) - { - qWarning() << "PaymentServer::netRequestFinished: Error parsing payment request"; - Q_EMIT message(tr("Payment request error"), - tr("Payment request cannot be parsed!"), - CClientUIInterface::MSG_ERROR); - } - else if (processPaymentRequest(request, recipient)) - Q_EMIT receivedPaymentRequest(recipient); - - return; - } - else if (requestType == BIP70_MESSAGE_PAYMENTACK) - { - payments::PaymentACK paymentACK; - if (!paymentACK.ParseFromArray(data.data(), data.size())) - { - QString msg = tr("Bad response from server %1") - .arg(reply->request().url().toString()); - - qWarning() << "PaymentServer::netRequestFinished: " << msg; - Q_EMIT message(tr("Payment request error"), msg, CClientUIInterface::MSG_ERROR); - } - else - { - Q_EMIT receivedPaymentACK(GUIUtil::HtmlEscape(paymentACK.memo())); - } - } -} - -void PaymentServer::reportSslErrors(QNetworkReply* reply, const QList<QSslError> &errs) -{ - Q_UNUSED(reply); - - QString errString; - for (const QSslError& err : errs) { - qWarning() << "PaymentServer::reportSslErrors: " << err; - errString += err.errorString() + "\n"; - } - Q_EMIT message(tr("Network request error"), errString, CClientUIInterface::MSG_ERROR); -} - -void PaymentServer::handlePaymentACK(const QString& paymentACKMsg) -{ - // currently we don't further process or store the paymentACK message - Q_EMIT message(tr("Payment acknowledged"), paymentACKMsg, CClientUIInterface::ICON_INFORMATION | CClientUIInterface::MODAL); -} - -bool PaymentServer::verifyNetwork(interfaces::Node& node, const payments::PaymentDetails& requestDetails) -{ - bool fVerified = requestDetails.network() == node.getNetwork(); - if (!fVerified) { - qWarning() << QString("PaymentServer::%1: Payment request network \"%2\" doesn't match client network \"%3\".") - .arg(__func__) - .arg(QString::fromStdString(requestDetails.network())) - .arg(QString::fromStdString(node.getNetwork())); - } - return fVerified; -} - -bool PaymentServer::verifyExpired(const payments::PaymentDetails& requestDetails) -{ - bool fVerified = (requestDetails.has_expires() && (int64_t)requestDetails.expires() < GetTime()); - if (fVerified) { - const QString requestExpires = QString::fromStdString(FormatISO8601DateTime((int64_t)requestDetails.expires())); - qWarning() << QString("PaymentServer::%1: Payment request expired \"%2\".") - .arg(__func__) - .arg(requestExpires); - } - return fVerified; -} - -bool PaymentServer::verifySize(qint64 requestSize) -{ - bool fVerified = (requestSize <= BIP70_MAX_PAYMENTREQUEST_SIZE); - if (!fVerified) { - qWarning() << QString("PaymentServer::%1: Payment request too large (%2 bytes, allowed %3 bytes).") - .arg(__func__) - .arg(requestSize) - .arg(BIP70_MAX_PAYMENTREQUEST_SIZE); - } - return fVerified; -} - -bool PaymentServer::verifyAmount(const CAmount& requestAmount) -{ - bool fVerified = MoneyRange(requestAmount); - if (!fVerified) { - qWarning() << QString("PaymentServer::%1: Payment request amount out of allowed range (%2, allowed 0 - %3).") - .arg(__func__) - .arg(requestAmount) - .arg(MAX_MONEY); - } - return fVerified; -} - -X509_STORE* PaymentServer::getCertStore() -{ - return certStore.get(); -} -#endif diff --git a/src/qt/paymentserver.h b/src/qt/paymentserver.h index 30b5bc3b6d..8b2533508d 100644 --- a/src/qt/paymentserver.h +++ b/src/qt/paymentserver.h @@ -36,9 +36,6 @@ #include <config/bitcoin-config.h> #endif -#ifdef ENABLE_BIP70 -#include <qt/paymentrequestplus.h> -#endif #include <qt/walletmodel.h> #include <QObject> @@ -50,15 +47,9 @@ QT_BEGIN_NAMESPACE class QApplication; class QByteArray; class QLocalServer; -class QNetworkAccessManager; -class QNetworkReply; -class QSslError; class QUrl; QT_END_NAMESPACE -// BIP70 max payment request size in bytes (DoS protection) -static const qint64 BIP70_MAX_PAYMENTREQUEST_SIZE = 50000; - class PaymentServer : public QObject { Q_OBJECT @@ -82,27 +73,6 @@ public: // OptionsModel is used for getting proxy settings and display unit void setOptionsModel(OptionsModel *optionsModel); -#ifdef ENABLE_BIP70 - // Load root certificate authorities. Pass nullptr (default) - // to read from the file specified in the -rootcertificates setting, - // or, if that's not set, to use the system default root certificates. - // If you pass in a store, you should not X509_STORE_free it: it will be - // freed either at exit or when another set of CAs are loaded. - static void LoadRootCAs(X509_STORE* store = nullptr); - - // Return certificate store - static X509_STORE* getCertStore(); - - // Verify that the payment request network matches the client network - static bool verifyNetwork(interfaces::Node& node, const payments::PaymentDetails& requestDetails); - // Verify if the payment request is expired - static bool verifyExpired(const payments::PaymentDetails& requestDetails); - // Verify the payment request size is valid as per BIP70 - static bool verifySize(qint64 requestSize); - // Verify the payment request amount is valid - static bool verifyAmount(const CAmount& requestAmount); -#endif - Q_SIGNALS: // Fired when a valid payment request is received void receivedPaymentRequest(SendCoinsRecipient); @@ -110,11 +80,6 @@ Q_SIGNALS: // Fired when a message should be reported to the user void message(const QString &title, const QString &message, unsigned int style); -#ifdef ENABLE_BIP70 - // Fired when a valid PaymentACK is received - void receivedPaymentACK(const QString &paymentACKMsg); -#endif - public Q_SLOTS: // Signal this when the main window's UI is ready // to display payment requests to the user @@ -123,18 +88,8 @@ public Q_SLOTS: // Handle an incoming URI, URI with local file scheme or file void handleURIOrFile(const QString& s); -#ifdef ENABLE_BIP70 - // Submit Payment message to a merchant, get back PaymentACK: - void fetchPaymentACK(WalletModel* walletModel, const SendCoinsRecipient& recipient, QByteArray transaction); -#endif - private Q_SLOTS: void handleURIConnection(); -#ifdef ENABLE_BIP70 - void netRequestFinished(QNetworkReply*); - void reportSslErrors(QNetworkReply*, const QList<QSslError> &); - void handlePaymentACK(const QString& paymentACKMsg); -#endif protected: // Constructor registers this on the parent QApplication to @@ -145,16 +100,6 @@ private: bool saveURIs; // true during startup QLocalServer* uriServer; OptionsModel *optionsModel; - -#ifdef ENABLE_BIP70 - static bool readPaymentRequestFromFile(const QString& filename, PaymentRequestPlus& request); - bool processPaymentRequest(const PaymentRequestPlus& request, SendCoinsRecipient& recipient); - void fetchRequest(const QUrl& url); - - // Setup networking - void initNetManager(); - QNetworkAccessManager* netManager; // Used to fetch payment requests -#endif }; #endif // BITCOIN_QT_PAYMENTSERVER_H diff --git a/src/qt/peertablemodel.cpp b/src/qt/peertablemodel.cpp index 99a9a12fe2..af2a1bb0e5 100644 --- a/src/qt/peertablemodel.cpp +++ b/src/qt/peertablemodel.cpp @@ -9,7 +9,6 @@ #include <qt/guiutil.h> #include <interfaces/node.h> -#include <sync.h> #include <algorithm> diff --git a/src/qt/qrimagewidget.cpp b/src/qt/qrimagewidget.cpp index bf1baf5470..2332d52b9a 100644 --- a/src/qt/qrimagewidget.cpp +++ b/src/qt/qrimagewidget.cpp @@ -71,6 +71,7 @@ bool QRImageWidget::setQR(const QString& data, const QString& text) if (!text.isEmpty()) { QFont font = GUIUtil::fixedPitchFont(); + font.setStyleStrategy(QFont::NoAntialias); QRect paddedRect = qrAddrImage.rect(); // calculate ideal font size diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 4f6629bfe1..3dd64c5273 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -1268,22 +1268,24 @@ void RPCConsole::showOrHideBanTableIfRequired() void RPCConsole::setTabFocus(enum TabTypes tabType) { - ui->tabWidget->setCurrentIndex(tabType); + ui->tabWidget->setCurrentIndex(int(tabType)); } QString RPCConsole::tabTitle(TabTypes tab_type) const { - return ui->tabWidget->tabText(tab_type); + return ui->tabWidget->tabText(int(tab_type)); } QKeySequence RPCConsole::tabShortcut(TabTypes tab_type) const { switch (tab_type) { - case TAB_INFO: return QKeySequence(Qt::CTRL + Qt::Key_I); - case TAB_CONSOLE: return QKeySequence(Qt::CTRL + Qt::Key_T); - case TAB_GRAPH: return QKeySequence(Qt::CTRL + Qt::Key_N); - case TAB_PEERS: return QKeySequence(Qt::CTRL + Qt::Key_P); - } + case TabTypes::INFO: return QKeySequence(Qt::CTRL + Qt::Key_I); + case TabTypes::CONSOLE: return QKeySequence(Qt::CTRL + Qt::Key_T); + case TabTypes::GRAPH: return QKeySequence(Qt::CTRL + Qt::Key_N); + case TabTypes::PEERS: return QKeySequence(Qt::CTRL + Qt::Key_P); + } // no default case, so the compiler can warn about missing cases + + assert(false); } void RPCConsole::updateAlerts(const QString& warnings) diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h index 6b0f07baf1..f586d04022 100644 --- a/src/qt/rpcconsole.h +++ b/src/qt/rpcconsole.h @@ -58,14 +58,14 @@ public: CMD_ERROR }; - enum TabTypes { - TAB_INFO = 0, - TAB_CONSOLE = 1, - TAB_GRAPH = 2, - TAB_PEERS = 3 + enum class TabTypes { + INFO, + CONSOLE, + GRAPH, + PEERS }; - std::vector<TabTypes> tabs() const { return {TAB_INFO, TAB_CONSOLE, TAB_GRAPH, TAB_PEERS}; } + std::vector<TabTypes> tabs() const { return {TabTypes::INFO, TabTypes::CONSOLE, TabTypes::GRAPH, TabTypes::PEERS}; } QString tabTitle(TabTypes tab_type) const; QKeySequence tabShortcut(TabTypes tab_type) const; diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index 003a31b248..8edcca684d 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -291,9 +291,6 @@ void SendCoinsDialog::on_sendButton_clicked() QString recipientElement; -#ifdef ENABLE_BIP70 - if (!rcp.paymentRequest.IsInitialized()) // normal payment -#endif { if(rcp.label.length() > 0) // label with address { @@ -305,17 +302,6 @@ void SendCoinsDialog::on_sendButton_clicked() recipientElement.append(tr("%1 to %2").arg(amount, address)); } } -#ifdef ENABLE_BIP70 - else if(!rcp.authenticatedMerchant.isEmpty()) // authenticated payment request - { - recipientElement.append(tr("%1 to '%2'").arg(amount, rcp.authenticatedMerchant)); - } - else // unauthenticated payment request - { - recipientElement.append(tr("%1 to %2").arg(amount, address)); - } -#endif - formatted.append(recipientElement); } @@ -558,8 +544,7 @@ void SendCoinsDialog::processSendCoinsReturn(const WalletModel::SendCoinsReturn msgParams.second = CClientUIInterface::MSG_WARNING; // This comment is specific to SendCoinsDialog usage of WalletModel::SendCoinsReturn. - // WalletModel::TransactionCommitFailed is used only in WalletModel::sendCoins() - // all others are used only in WalletModel::prepareTransaction() + // All status values are used only in WalletModel::prepareTransaction() switch(sendCoinsReturn.status) { case WalletModel::InvalidAddress: @@ -581,10 +566,6 @@ void SendCoinsDialog::processSendCoinsReturn(const WalletModel::SendCoinsReturn msgParams.first = tr("Transaction creation failed!"); msgParams.second = CClientUIInterface::MSG_ERROR; break; - case WalletModel::TransactionCommitFailed: - msgParams.first = tr("The transaction was rejected with the following reason: %1").arg(sendCoinsReturn.reasonCommitFailed); - msgParams.second = CClientUIInterface::MSG_ERROR; - break; case WalletModel::AbsurdFee: msgParams.first = tr("A fee higher than %1 is considered an absurdly high fee.").arg(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), model->wallet().getDefaultMaxTxFee())); break; diff --git a/src/qt/sendcoinsentry.cpp b/src/qt/sendcoinsentry.cpp index 7324d759fb..be417655b4 100644 --- a/src/qt/sendcoinsentry.cpp +++ b/src/qt/sendcoinsentry.cpp @@ -137,12 +137,6 @@ bool SendCoinsEntry::validate(interfaces::Node& node) // Check input validity bool retval = true; -#ifdef ENABLE_BIP70 - // Skip checks for payment request - if (recipient.paymentRequest.IsInitialized()) - return retval; -#endif - if (!model->validateAddress(ui->payTo->text())) { ui->payTo->setValid(false); @@ -172,13 +166,6 @@ bool SendCoinsEntry::validate(interfaces::Node& node) SendCoinsRecipient SendCoinsEntry::getValue() { -#ifdef ENABLE_BIP70 - // Payment request - if (recipient.paymentRequest.IsInitialized()) - return recipient; -#endif - - // Normal payment recipient.address = ui->payTo->text(); recipient.label = ui->addAsLabel->text(); recipient.amount = ui->payAmount->value(); @@ -203,29 +190,6 @@ QWidget *SendCoinsEntry::setupTabChain(QWidget *prev) void SendCoinsEntry::setValue(const SendCoinsRecipient &value) { recipient = value; - -#ifdef ENABLE_BIP70 - if (recipient.paymentRequest.IsInitialized()) // payment request - { - if (recipient.authenticatedMerchant.isEmpty()) // unauthenticated - { - ui->payTo_is->setText(recipient.address); - ui->memoTextLabel_is->setText(recipient.message); - ui->payAmount_is->setValue(recipient.amount); - ui->payAmount_is->setReadOnly(true); - setCurrentWidget(ui->SendCoins_UnauthenticatedPaymentRequest); - } - else // authenticated - { - ui->payTo_s->setText(recipient.authenticatedMerchant); - ui->memoTextLabel_s->setText(recipient.message); - ui->payAmount_s->setValue(recipient.amount); - ui->payAmount_s->setReadOnly(true); - setCurrentWidget(ui->SendCoins_AuthenticatedPaymentRequest); - } - } - else // normal payment -#endif { // message ui->messageTextLabel->setText(recipient.message); diff --git a/src/qt/signverifymessagedialog.cpp b/src/qt/signverifymessagedialog.cpp index 71f5f2ae75..1d0e1323bc 100644 --- a/src/qt/signverifymessagedialog.cpp +++ b/src/qt/signverifymessagedialog.cpp @@ -14,7 +14,6 @@ #include <util/validation.h> // For strMessageMagic #include <wallet/wallet.h> -#include <string> #include <vector> #include <QClipboard> diff --git a/src/qt/splashscreen.cpp b/src/qt/splashscreen.cpp index 0e5abb89f3..26c9fe7ad4 100644 --- a/src/qt/splashscreen.cpp +++ b/src/qt/splashscreen.cpp @@ -17,7 +17,6 @@ #include <ui_interface.h> #include <util/system.h> #include <util/translation.h> -#include <version.h> #include <QApplication> #include <QCloseEvent> diff --git a/src/qt/test/compattests.cpp b/src/qt/test/compattests.cpp index 6750c543da..cf86a5bc1e 100644 --- a/src/qt/test/compattests.cpp +++ b/src/qt/test/compattests.cpp @@ -6,10 +6,6 @@ #include <config/bitcoin-config.h> #endif -#if defined(ENABLE_WALLET) && defined(ENABLE_BIP70) -#include <qt/paymentrequestplus.h> // this includes protobuf's port.h which defines its own bswap macos -#endif - #include <qt/test/compattests.h> #include <compat/byteswap.h> diff --git a/src/qt/test/paymentrequestdata.h b/src/qt/test/paymentrequestdata.h deleted file mode 100644 index 7f45d30973..0000000000 --- a/src/qt/test/paymentrequestdata.h +++ /dev/null @@ -1,465 +0,0 @@ -// Copyright (c) 2009-2018 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#ifndef BITCOIN_QT_TEST_PAYMENTREQUESTDATA_H -#define BITCOIN_QT_TEST_PAYMENTREQUESTDATA_H - -// -// Data for paymentservertests.cpp -// - -// Base64/DER-encoded fake certificate authority certificates. -// Convert pem to base64/der with: -// openssl x509 -in cert.pem -inform PEM -outform DER | openssl enc -base64 - -// Serial Number: 10302349811211485352 (0x8ef94c91b112c0a8) -// Issuer: CN=PaymentRequest Test CA -// Subject: CN=PaymentRequest Test CA -// Not Valid After : Dec 8 16:37:24 2022 GMT -// -const char* caCert1_BASE64 = -"\ -MIIB0DCCATmgAwIBAgIJAI75TJGxEsCoMA0GCSqGSIb3DQEBCwUAMCExHzAdBgNV\ -BAMTFlBheW1lbnRSZXF1ZXN0IFRlc3QgQ0EwHhcNMTIxMjEwMTYzNzI0WhcNMjIx\ -MjA4MTYzNzI0WjAhMR8wHQYDVQQDExZQYXltZW50UmVxdWVzdCBUZXN0IENBMIGf\ -MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCvua59nX9radoqDYyplcns5qdVDTN1\ -7tmcGixmMYOYU3UYMU55VSsJs0dWKnMm3COQDY+N63c0XSbRqarBcsLTkaNASuPX\ -FCv1VWuEKSyy5xe4zeoDU7CVSzlxtQD9wbZW/s3ISjgaXBpwn6eVmntb0JwYxxPc\ -M1u/hrMD8BDbSQIDAQABoxAwDjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUA\ -A4GBADSaRgK5xe47XxycXBhHhr0Wgl4pAsFsufqA9aB9r8KNEHJ0yUvvbD/jaJJM\ -RtQcf0AJ9olzUMY4syehxbzUJP6aeXhZEYiMvdvcv9D55clq6+WLLlNT3jBgAaVn\ -p3waRjPD4bUX3nv+ojz5s4puw7Qq5QUZlhGsMzPvwDGCmZkL\ -"; - -// Serial Number: f0:da:97:e4:38:d7:64:16 -// Issuer: CN=PaymentRequest Test CA -// Subject: CN=PaymentRequest Test CA -// Not Valid After : Jan 8 18:21:06 2025 GMT -// -const char* caCert2_BASE64 = -"\ -MIIC1TCCAb2gAwIBAgIJAPDal+Q412QWMA0GCSqGSIb3DQEBCwUAMCExHzAdBgNV\ -BAMMFlBheW1lbnRSZXF1ZXN0IFRlc3QgQ0EwHhcNMTUwMTExMTgyMTA2WhcNMjUw\ -MTA4MTgyMTA2WjAhMR8wHQYDVQQDDBZQYXltZW50UmVxdWVzdCBUZXN0IENBMIIB\ -IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1S9wVLfTplJuT/1OaaBgl/Mb\ -I392v8S9kHbzYz7B4OTMslaO7piz0v3SO3TKMh0dswjiRdHrIgpO7XdIUQiU/ugg\ -xDw0kuNehfz1ycaGedlFFtFHTNXqLyIUF3dlwHhQwaomM6RXoJmxLny5BhYHEcmk\ -yWwr3Cdjd9gAZpblugVJB9C1e40uyL8ao4PHdLzOqO27iSe6riP8SwwisJZEbMaz\ -AZpgNEEMbIXPJEFvm5HTRXSMtQCOTSZYMFF0M2yrtmlECnz7hWP19b9bcoDzZQB4\ -ylIsFG/7q2jV7MC/e2STZv+niJiHL08RUdoFpAgzaxMgqj63C7B55HgNDNHJYQID\ -AQABoxAwDjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBGejPxLxj9\ -+crv6gUeEBMZPiUx7pUgcI22Wm5yymP96B4fwI3Y0DBehq20d76vbWGPN17Z6pH3\ -ge7PVY1SYqXtS6hXTo4olCm/BZADli+2Bs2xCiaa+Ltve4ufVej+bKJXN/YnrhvO\ -Kq+klQkuuHywU+GJV/NQeBqToIrSOBgi477NgLFCCCmmx2QWsxHoCFGfuRCBVseT\ -z2k/tMuALCDXGeZBRPTsGHu1y4cj84swAeoDK5QSQcI+Ub7GKc+zkoj02sdDLiMo\ -3wokYPcIy47oclhmb4xubHc+y7nF610yZBoC/zgbhbawnZ65hDDWkdQ/SVAnWZD7\ -9PFfmNnYPTQH\ -"; - -// -// This payment request validates directly against the -// caCert1 certificate authority. -// -const char* paymentrequest1_cert1_BASE64 = -"\ -Egt4NTA5K3NoYTI1NhrxAwruAzCCAeowggFToAMCAQICAQEwDQYJKoZIhvcNAQEL\ -BQAwITEfMB0GA1UEAxMWUGF5bWVudFJlcXVlc3QgVGVzdCBDQTAeFw0xMjEyMTAx\ -NjM3MjRaFw0yMjEyMDgxNjM3MjRaMEMxGTAXBgNVBAMMEHRlc3RtZXJjaGFudC5v\ -cmcxJjAkBgNVBAoMHVBheW1lbnQgUmVxdWVzdCBUZXN0IE1lcmNoYW50MIGfMA0G\ -CSqGSIb3DQEBAQUAA4GNADCBiQKBgQDHkMy8W1u6HsWlSqdWTmMKf54gICxNfxbY\ -+rcMtAftr62hCYx2d2QiSRd1pCUzmo12IiSX3WxSHwaTnT3MFD6jRx6+zM6XdGar\ -I2zpYle11ANzu4gAthN17uRQHV2O5QxVtzNaMdKeJLXT2L9tfEdyL++9ZUqoQmdA\ -YG9ix330hQIDAQABoxAwDjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4GB\ -AIkyO99KC68bi9PFRyQQ7nvn5GlQEb3Ca1bRG5+AKN9N5vc8rZ9G2hejtM8wEXni\ -eGBP+chVMsbTPEHKLrwREn7IvcyCcbAStaklPC3w0B/2idQSHskb6P3X13OR2bTH\ -a2+6wuhsOZRUrVNr24rM95DKx/eCC6JN1VW+qRPU6fqzIjQSHwiw2wYSGXapFJVg\ -igPI+6XpExtNLO/i1WFV8ZmoiKwYsuHFiwUqC1VuaXRUZXN0T25lKoABS0j59iMU\ -Uc9MdIfwsO1BskIET0eJSGNZ7eXb9N62u+qf831PMpEHkmlGpk8rHy92nPcgua/U\ -Yt8oZMn3QaTZ5A6HjJbc3A73eLylp1a0SwCl+KDMEvDQhqMn1jAVu2v92AH3uB7n\ -SiWVbw0tX/68iSQEGGfh9n6ee/8Myb3ICdw=\ -"; - -// -// Signed, but expired, merchant cert in the request -// -const char* paymentrequest2_cert1_BASE64 = -"\ -Egt4NTA5K3NoYTI1NhrsAwrpAzCCAeUwggFOoAMCAQICAQMwDQYJKoZIhvcNAQEL\ -BQAwITEfMB0GA1UEAxMWUGF5bWVudFJlcXVlc3QgVGVzdCBDQTAeFw0xMzAyMjMy\ -MTI2NDNaFw0xMzAyMjQyMTI2NDNaMD4xHDAaBgNVBAMME2V4cGlyZWRtZXJjaGFu\ -dC5vcmcxHjAcBgNVBAoMFUV4cGlyZWQgVGVzdCBNZXJjaGFudDCBnzANBgkqhkiG\ -9w0BAQEFAAOBjQAwgYkCgYEAx5DMvFtbuh7FpUqnVk5jCn+eICAsTX8W2Pq3DLQH\ -7a+toQmMdndkIkkXdaQlM5qNdiIkl91sUh8Gk509zBQ+o0cevszOl3RmqyNs6WJX\ -tdQDc7uIALYTde7kUB1djuUMVbczWjHSniS109i/bXxHci/vvWVKqEJnQGBvYsd9\ -9IUCAwEAAaMQMA4wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOBgQAaU137\ -j53rvSjlmYZpZ4RWTP7EdD6fl5ZxBeXHytN6DQL33H0eD7OFHt+ofc7E6D7keubl\ -UfCu+jOvt/MvvPUmtCI9yXZ0dNC4sjyETv+wQpxO0UNZwOM4uegdCzlo6Bi3pD4/\ -KKLdMkWuUfuPBmoammny74lZaOVr5deKXztTuCI0Eh8IsNsGEhl2qRSVYIoDyPul\ -6RMbTSzv4tVhVfGZqIisGLLhxYsFKgtVbml0VGVzdFR3byqAAXHuo4nZEPniLpkd\ -y30TkwBxVgprWJ18a9z/7Py35Qss/JMbOXbnBhJtmJCdIowHRI0aa+zqt3KKKAXi\ -mm+V4seMgxTcxMS+eDDkiTcB/RtWWSyRcS2ANjFeY0T4SLMwiCL9qWPi03hr8j96\ -tejrSPOBNSJ3Mi/q5u2Yl4gJZY2b\ -"; - -// -// 10-long certificate chain, all intermediates valid -// -const char* paymentrequest3_cert1_BASE64 = -"\ -Egt4NTA5K3NoYTI1Nhq8JAr/AzCCAfswggFkoAMCAQICAQEwDQYJKoZIhvcNAQEL\ -BQAwPzEUMBIGA1UEAwwLdGVzdGNhOC5vcmcxJzAlBgNVBAoMHlBheW1lbnQgUmVx\ -dWVzdCBJbnRlcm1lZGlhdGUgODAeFw0xMzAyMjMyMjQyMzFaFw0yMzAyMjEyMjQy\ -MzFaMDYxGjAYBgNVBAMMEXRlc3RtZXJjaGFudDgub3JnMRgwFgYDVQQKDA9UZXN0\ -IE1lcmNoYW50IDgwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMMCHA3hiHbS\ -TKZ5K9jHRwE8NxkGp3IOx56PDB2diNkldG8XweTcRq7bBm7pdiBt4IVggtfs+6hE\ -hDYIOecyoAnVzPFTdvQ7KQdQ/fD9YLe6lk+o0edOqutPMyrxLFjSluXxEQyk7fdt\ -URloMMYfp3p1/hFCboA1rAsQ2RW38hR5AgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8w\ -DQYJKoZIhvcNAQELBQADgYEAPsdFatnc2RJSpvZsw+nCiPVsllycw5ELglq9vfJz\ -nJJucRxgzmqI2iuas1ugwbXn0BEIRLK7vMF/qBzQR6M/nTxttah+KEu+okjps9vJ\ -cIyhfTyGPC5xkHaHZ7sG+UHOFhPw0/kXn0x+pbVgBZ5315axqcp1R+DTSj/whMAr\ -n0AKiAQwggIEMIIBbaADAgECAgECMA0GCSqGSIb3DQEBCwUAMD8xFDASBgNVBAMM\ -C3Rlc3RjYTcub3JnMScwJQYDVQQKDB5QYXltZW50IFJlcXVlc3QgSW50ZXJtZWRp\ -YXRlIDcwHhcNMTMwMjIzMjI0MjMxWhcNMjMwMjIxMjI0MjMxWjA/MRQwEgYDVQQD\ -DAt0ZXN0Y2E4Lm9yZzEnMCUGA1UECgweUGF5bWVudCBSZXF1ZXN0IEludGVybWVk\ -aWF0ZSA4MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDexUFfxb1sThvabp7u\ -dZz59ciThGmmAW0nP4tjrgEACgvWIInr2dZpTHbiQNF34ycsk0le1JD93D7Qb8rd\ -25OrpaO8XS2Li2zjR9cleixXjSLwV/zv8zJ8yPl/27XL++PDTKBXVpJ8/Syp+9Ty\ -plV1BqDhqtIHb/QSHEkTQXjeYQIDAQABoxAwDjAMBgNVHRMEBTADAQH/MA0GCSqG\ -SIb3DQEBCwUAA4GBACMooQVbkbIZ2DaPwHDc4ULwguG3VI2Kzj50UdExmHtzm2S4\ -MQei+n+HEPjtJAx5OY520+10nfuP+12H2DRLQmWmdvDpeQ/Cv0yavlw4ZRejRFo7\ -KS83C0wo5rd+qTvvOmAN4UTArWkzYcEUulPdiXnRamb0WQHTeVdIbHVkMormCogE\ -MIICBDCCAW2gAwIBAgIBAjANBgkqhkiG9w0BAQsFADA/MRQwEgYDVQQDDAt0ZXN0\ -Y2E2Lm9yZzEnMCUGA1UECgweUGF5bWVudCBSZXF1ZXN0IEludGVybWVkaWF0ZSA2\ -MB4XDTEzMDIyMzIyNDIzMVoXDTIzMDIyMTIyNDIzMVowPzEUMBIGA1UEAwwLdGVz\ -dGNhNy5vcmcxJzAlBgNVBAoMHlBheW1lbnQgUmVxdWVzdCBJbnRlcm1lZGlhdGUg\ -NzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAtjBRazrkebXAhXsbjimrMIRm\ -W/f9SwAHwXfc042keNtl0t2z6XE6UPcR2v/KrssXuCZgodeYxz6IM6lWosCM1xot\ -C3ChKKFBfVO30reuKBRUxXfKAFqxaG0YOAEzdZkkY9AGhqWloeSmgxpIfhInU0EF\ -JjCwrJ6IkijBatGoAAECAwEAAaMQMA4wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0B\ -AQsFAAOBgQDBRTi1MolmOA0niHYX0A2lN5QWHkCfX0A7GwyoMA3dvM45m/NYd4WB\ -X+HwfnfYcI6X9jOgNo5OWmc4GGsld0HlxwMYEKISBS9PbSHPBrb3TBOlw5ztQpXZ\ -91+bOhLux52Fr03sK7v9qExmBM12M8UR2ltpzAMiUgLLMHyPfiWkvQqIBDCCAgQw\ -ggFtoAMCAQICAQIwDQYJKoZIhvcNAQELBQAwPzEUMBIGA1UEAwwLdGVzdGNhNS5v\ -cmcxJzAlBgNVBAoMHlBheW1lbnQgUmVxdWVzdCBJbnRlcm1lZGlhdGUgNTAeFw0x\ -MzAyMjMyMjQyMzBaFw0yMzAyMjEyMjQyMzBaMD8xFDASBgNVBAMMC3Rlc3RjYTYu\ -b3JnMScwJQYDVQQKDB5QYXltZW50IFJlcXVlc3QgSW50ZXJtZWRpYXRlIDYwgZ8w\ -DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANJSH3xivX1t9olIdHsznI1aE9SD7t9i\ -SZJsIB0otoETHZRVv9M9LvyzBNK98ZV+kTOlST7PJgC0d9BQM9sgYApSRq5oqKDM\ -9FXbOm/yaReAbU3mkFNFw5roTlJ5ThEy0yOGT/DS0YBRaGIvRPRj2DiqDVdCZZ+w\ -4jo1IYHkZt4FAgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQAD\ -gYEATm6+J1OmbrothO60xALKonWMBKr6hudb4amkFBqKbA9wMeM3jl+I/yKfz/Uf\ -xWuJ071IhiNv6Gxx5YwNvhUe1xMhUqHv0gpyK1Z47bD+kYS2se5sWNPNo3Y9qZDG\ -IXiGQxwHmrzaFk79Uy1xsmvsEz42w6hr25Yaw7HkIgrFveoKiAQwggIEMIIBbaAD\ -AgECAgECMA0GCSqGSIb3DQEBCwUAMD8xFDASBgNVBAMMC3Rlc3RjYTQub3JnMScw\ -JQYDVQQKDB5QYXltZW50IFJlcXVlc3QgSW50ZXJtZWRpYXRlIDQwHhcNMTMwMjIz\ -MjI0MjMwWhcNMjMwMjIxMjI0MjMwWjA/MRQwEgYDVQQDDAt0ZXN0Y2E1Lm9yZzEn\ -MCUGA1UECgweUGF5bWVudCBSZXF1ZXN0IEludGVybWVkaWF0ZSA1MIGfMA0GCSqG\ -SIb3DQEBAQUAA4GNADCBiQKBgQC7vVUFpxHzz2Tr/xij3k58s8d/BPA0R6D5RXTV\ -vmhAzc1Zuin4zUKRFs/aCj/0yED8Wu/COfNGF4tVlRNMdl9EcFsxa8XGEL4eAZa+\ -H/rOHH+7/1EINrrVWhZlUecyhilN8jmCZmqEM3ecuD0NAViqyMrgmaiFmsLoQZpE\ -GepDUQIDAQABoxAwDjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4GBAEdJ\ -Ss8jWiooja3WZzHXeF95QkBJNjIlpDLGcpl4opOYLSuEl9Uxp//LaQQiXuzpj4/I\ -pkWGQmMy5HOyH1lqDyiMgXpcG8PE0jEQAoEUGZ0QEqB1mZ6BCrYvmUuf/5aSVd8Y\ -6lKMR3WzFDYU9Zy0nzuHB/3nvp6MeDRQeRMtYvz4CogEMIICBDCCAW2gAwIBAgIB\ -AjANBgkqhkiG9w0BAQsFADA/MRQwEgYDVQQDDAt0ZXN0Y2EzLm9yZzEnMCUGA1UE\ -CgweUGF5bWVudCBSZXF1ZXN0IEludGVybWVkaWF0ZSAzMB4XDTEzMDIyMzIyNDIy\ -OVoXDTIzMDIyMTIyNDIyOVowPzEUMBIGA1UEAwwLdGVzdGNhNC5vcmcxJzAlBgNV\ -BAoMHlBheW1lbnQgUmVxdWVzdCBJbnRlcm1lZGlhdGUgNDCBnzANBgkqhkiG9w0B\ -AQEFAAOBjQAwgYkCgYEAxYYo3w2UXiYg6O8b4QgwN/vgreTkiW122Ep/z2TiDrhV\ -MhfOOiKdwYESPflfnXnVaQQzCGexYTQqsvqvzHSyna5hL0zPTRJxSKmTVrXRsWtp\ -dCRhjxCGipS3tlQBDi7vb+7SNRIBK4dBjjGzALNk7gMCpy+yM8f6I043jTlmGb0C\ -AwEAAaMQMA4wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOBgQDU+IQxt3Oh\ -KqaUYWC23+cB2gekvWqwMBnrCNrX/Dp+kjoJKUoR2Fs3qw53raHES4SIhpGT9l9l\ -rppNQgFe/JMHeYqOZMZO+6kuU0olJanBJ14tPIc7zlMTQ9OfmZ6v07IpyFbsQDtR\ -hpe80DpuvSFPfJ4fh0WrQf6kn3KDVpGDnAqIBDCCAgQwggFtoAMCAQICAQIwDQYJ\ -KoZIhvcNAQELBQAwPzEUMBIGA1UEAwwLdGVzdGNhMi5vcmcxJzAlBgNVBAoMHlBh\ -eW1lbnQgUmVxdWVzdCBJbnRlcm1lZGlhdGUgMjAeFw0xMzAyMjMyMjQyMjlaFw0y\ -MzAyMjEyMjQyMjlaMD8xFDASBgNVBAMMC3Rlc3RjYTMub3JnMScwJQYDVQQKDB5Q\ -YXltZW50IFJlcXVlc3QgSW50ZXJtZWRpYXRlIDMwgZ8wDQYJKoZIhvcNAQEBBQAD\ -gY0AMIGJAoGBANzgVP99Qg98e6NsKEz1v5KqRB7NTBRRsYnBvb/TSWipvMQaCYuE\ -yk1xG57x++QuASKeR3QHRQJOoAhQaj9JLUhSSv9GQ5PrFLLsOFv7L1tpzXHh2dOB\ -IW92X2yFRW2s39q+Q21yvN+N8uoKdqXhzRA+dDoXh3cavaVeHX1G+IrlAgMBAAGj\ -EDAOMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADgYEASTwg84cX+1UhOG9s\ -ejFV3m34QuI1hPZ+qhqVJlRYUtego8Wng1BburDSwqVAv4ch2wi3c2s4e8J7AXyL\ -tzSbSQG4RN0oZi0mR8EtTTN+Mix/hBIk79dMZg85+I29uFA6Zj2d9oAhQv2qkHhc\ -6tcaheNvkQRlCyH68k3iF1Fqf+4KiAQwggIEMIIBbaADAgECAgECMA0GCSqGSIb3\ -DQEBCwUAMD8xFDASBgNVBAMMC3Rlc3RjYTEub3JnMScwJQYDVQQKDB5QYXltZW50\ -IFJlcXVlc3QgSW50ZXJtZWRpYXRlIDEwHhcNMTMwMjIzMjI0MjI5WhcNMjMwMjIx\ -MjI0MjI5WjA/MRQwEgYDVQQDDAt0ZXN0Y2EyLm9yZzEnMCUGA1UECgweUGF5bWVu\ -dCBSZXF1ZXN0IEludGVybWVkaWF0ZSAyMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB\ -iQKBgQDaV8zhfyQuSf/f+fauMfgs3g/RnWy9yxxUkvQneQQPH3uZzCyk3A6q72ip\ -TtwNqiibG9455L9A7SaUjGtnpUz0NKT/VWUdqbfCl1PqXjEZbDobbAQ5hxLGOTyL\ -RQhLIcgeq2/BnmeCqHsC4md04nUp+nBo1HwKyygvK+9sMbCp/wIDAQABoxAwDjAM\ -BgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4GBACvYyE+PPmWFkbjyRu9LAt8D\ -crtyYYLRClKSg6tVvutwukLG2l//kDOohYkJtgTqr6LnCIIIwYdXN+4wxugmw4cn\ -PIZmP6kovxjhhVM95okilor1zniTAo3RN7JDIfTGNgxLdGu1btt7DOFL4zTbeSJM\ -b8M1JpPftehH+x/VLyuUCuoDMIIB5jCCAU+gAwIBAgIBBTANBgkqhkiG9w0BAQsF\ -ADAhMR8wHQYDVQQDExZQYXltZW50UmVxdWVzdCBUZXN0IENBMB4XDTEzMDIyMzIy\ -NDIyOFoXDTIzMDIyMTIyNDIyOFowPzEUMBIGA1UEAwwLdGVzdGNhMS5vcmcxJzAl\ -BgNVBAoMHlBheW1lbnQgUmVxdWVzdCBJbnRlcm1lZGlhdGUgMTCBnzANBgkqhkiG\ -9w0BAQEFAAOBjQAwgYkCgYEAo5Vy9H3nA/OOkF5Ap89yfVNSiTay/LYCaB0eALpc\ -U690U75O9Q3w2M+2AN8wpbbHsJHZMIjEeBRoQfjlYXW1ucQTxWKyT+liu0D25mGX\ -X27CBXBd4iXTxVII/iX+u3lcjORjoHOBy7QgeIDIIS9y0vYu8eArpjh7m4thrVgI\ -RtMCAwEAAaMQMA4wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOBgQB9LKcV\ -JK9sjASNzpQlpUp7nCiw5FSjVY+XMRIKK/kavzlKjZ+InsmmyRVGjDoZi9GrqG9P\ -VHgLBxi2VtVjmokZoNPqao3OfhqORAubC+JR/JLepM7aDaxDdTHVhSUk4lgNAvi2\ -6dGY7nZMsnHlPQ2tPp/HvRRiMq1oDjlylc8VTCI2Eh8IsNsGEhl2qRSVYIoDyPul\ -6RMbTSzv4tVhVfGZqIisGLLhxYsFKg1Vbml0VGVzdFRocmVlKoABn2HTsUQtMNI4\ -yNvkfkFNka3pRvTUTydJrvyfmEeLzImfM1BWddZjnywku9RToNFZZNgow5QnljmF\ -chhR/aHOuEMTxmc12K4rNlgYtHCsxLP9zd+6u0cva3TucZ6EzS8PKEib/+r12/52\ -664NuWA9WtsK7QCFrK2K95PnVCRmWl0=\ -"; - -// -// Long certificate chain, with an expired certificate in the middle -// -const char* paymentrequest4_cert1_BASE64 = -"\ -Egt4NTA5K3NoYTI1NhqeJAr/AzCCAfswggFkoAMCAQICAQEwDQYJKoZIhvcNAQEL\ -BQAwPzEUMBIGA1UEAwwLdGVzdGNhOC5vcmcxJzAlBgNVBAoMHlBheW1lbnQgUmVx\ -dWVzdCBJbnRlcm1lZGlhdGUgODAeFw0xMzAyMjMyMjQyMzFaFw0yMzAyMjEyMjQy\ -MzFaMDYxGjAYBgNVBAMMEXRlc3RtZXJjaGFudDgub3JnMRgwFgYDVQQKDA9UZXN0\ -IE1lcmNoYW50IDgwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMMCHA3hiHbS\ -TKZ5K9jHRwE8NxkGp3IOx56PDB2diNkldG8XweTcRq7bBm7pdiBt4IVggtfs+6hE\ -hDYIOecyoAnVzPFTdvQ7KQdQ/fD9YLe6lk+o0edOqutPMyrxLFjSluXxEQyk7fdt\ -URloMMYfp3p1/hFCboA1rAsQ2RW38hR5AgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8w\ -DQYJKoZIhvcNAQELBQADgYEAPsdFatnc2RJSpvZsw+nCiPVsllycw5ELglq9vfJz\ -nJJucRxgzmqI2iuas1ugwbXn0BEIRLK7vMF/qBzQR6M/nTxttah+KEu+okjps9vJ\ -cIyhfTyGPC5xkHaHZ7sG+UHOFhPw0/kXn0x+pbVgBZ5315axqcp1R+DTSj/whMAr\ -n0AKiAQwggIEMIIBbaADAgECAgECMA0GCSqGSIb3DQEBCwUAMD8xFDASBgNVBAMM\ -C3Rlc3RjYTcub3JnMScwJQYDVQQKDB5QYXltZW50IFJlcXVlc3QgSW50ZXJtZWRp\ -YXRlIDcwHhcNMTMwMjIzMjI0MjMxWhcNMjMwMjIxMjI0MjMxWjA/MRQwEgYDVQQD\ -DAt0ZXN0Y2E4Lm9yZzEnMCUGA1UECgweUGF5bWVudCBSZXF1ZXN0IEludGVybWVk\ -aWF0ZSA4MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDexUFfxb1sThvabp7u\ -dZz59ciThGmmAW0nP4tjrgEACgvWIInr2dZpTHbiQNF34ycsk0le1JD93D7Qb8rd\ -25OrpaO8XS2Li2zjR9cleixXjSLwV/zv8zJ8yPl/27XL++PDTKBXVpJ8/Syp+9Ty\ -plV1BqDhqtIHb/QSHEkTQXjeYQIDAQABoxAwDjAMBgNVHRMEBTADAQH/MA0GCSqG\ -SIb3DQEBCwUAA4GBACMooQVbkbIZ2DaPwHDc4ULwguG3VI2Kzj50UdExmHtzm2S4\ -MQei+n+HEPjtJAx5OY520+10nfuP+12H2DRLQmWmdvDpeQ/Cv0yavlw4ZRejRFo7\ -KS83C0wo5rd+qTvvOmAN4UTArWkzYcEUulPdiXnRamb0WQHTeVdIbHVkMormCogE\ -MIICBDCCAW2gAwIBAgIBAjANBgkqhkiG9w0BAQsFADA/MRQwEgYDVQQDDAt0ZXN0\ -Y2E2Lm9yZzEnMCUGA1UECgweUGF5bWVudCBSZXF1ZXN0IEludGVybWVkaWF0ZSA2\ -MB4XDTEzMDIyMzIyNDIzMVoXDTIzMDIyMTIyNDIzMVowPzEUMBIGA1UEAwwLdGVz\ -dGNhNy5vcmcxJzAlBgNVBAoMHlBheW1lbnQgUmVxdWVzdCBJbnRlcm1lZGlhdGUg\ -NzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAtjBRazrkebXAhXsbjimrMIRm\ -W/f9SwAHwXfc042keNtl0t2z6XE6UPcR2v/KrssXuCZgodeYxz6IM6lWosCM1xot\ -C3ChKKFBfVO30reuKBRUxXfKAFqxaG0YOAEzdZkkY9AGhqWloeSmgxpIfhInU0EF\ -JjCwrJ6IkijBatGoAAECAwEAAaMQMA4wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0B\ -AQsFAAOBgQDBRTi1MolmOA0niHYX0A2lN5QWHkCfX0A7GwyoMA3dvM45m/NYd4WB\ -X+HwfnfYcI6X9jOgNo5OWmc4GGsld0HlxwMYEKISBS9PbSHPBrb3TBOlw5ztQpXZ\ -91+bOhLux52Fr03sK7v9qExmBM12M8UR2ltpzAMiUgLLMHyPfiWkvQqIBDCCAgQw\ -ggFtoAMCAQICAQIwDQYJKoZIhvcNAQELBQAwPzEUMBIGA1UEAwwLdGVzdGNhNS5v\ -cmcxJzAlBgNVBAoMHlBheW1lbnQgUmVxdWVzdCBJbnRlcm1lZGlhdGUgNTAeFw0x\ -MzAyMjMyMjQyMzBaFw0yMzAyMjEyMjQyMzBaMD8xFDASBgNVBAMMC3Rlc3RjYTYu\ -b3JnMScwJQYDVQQKDB5QYXltZW50IFJlcXVlc3QgSW50ZXJtZWRpYXRlIDYwgZ8w\ -DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANJSH3xivX1t9olIdHsznI1aE9SD7t9i\ -SZJsIB0otoETHZRVv9M9LvyzBNK98ZV+kTOlST7PJgC0d9BQM9sgYApSRq5oqKDM\ -9FXbOm/yaReAbU3mkFNFw5roTlJ5ThEy0yOGT/DS0YBRaGIvRPRj2DiqDVdCZZ+w\ -4jo1IYHkZt4FAgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQAD\ -gYEATm6+J1OmbrothO60xALKonWMBKr6hudb4amkFBqKbA9wMeM3jl+I/yKfz/Uf\ -xWuJ071IhiNv6Gxx5YwNvhUe1xMhUqHv0gpyK1Z47bD+kYS2se5sWNPNo3Y9qZDG\ -IXiGQxwHmrzaFk79Uy1xsmvsEz42w6hr25Yaw7HkIgrFveoK6gMwggHmMIIBT6AD\ -AgECAgEGMA0GCSqGSIb3DQEBCwUAMCExHzAdBgNVBAMTFlBheW1lbnRSZXF1ZXN0\ -IFRlc3QgQ0EwHhcNMTMwMjIzMjI1OTUxWhcNMTMwMjI0MjI1OTUxWjA/MRQwEgYD\ -VQQDDAt0ZXN0Y2E1Lm9yZzEnMCUGA1UECgweUGF5bWVudCBSZXF1ZXN0IEludGVy\ -bWVkaWF0ZSA1MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC7vVUFpxHzz2Tr\ -/xij3k58s8d/BPA0R6D5RXTVvmhAzc1Zuin4zUKRFs/aCj/0yED8Wu/COfNGF4tV\ -lRNMdl9EcFsxa8XGEL4eAZa+H/rOHH+7/1EINrrVWhZlUecyhilN8jmCZmqEM3ec\ -uD0NAViqyMrgmaiFmsLoQZpEGepDUQIDAQABoxAwDjAMBgNVHRMEBTADAQH/MA0G\ -CSqGSIb3DQEBCwUAA4GBAEmcUEnhua/oiXy1fwScLgMqt+jk9mHRpE6SVsIop23Q\ -CY2JfpG6RxhMMzzzhGklEGN6cxG0HCi6B3HJx6PYrFEfTB0rW4K6m0Tvx3WpS9mN\ -uoEuJHLy18ausI/sYAPDHCL+SfBVcqorpaIG2sSpZouRBjRHAyqFAYlwlW87uq5n\ -CogEMIICBDCCAW2gAwIBAgIBAjANBgkqhkiG9w0BAQsFADA/MRQwEgYDVQQDDAt0\ -ZXN0Y2EzLm9yZzEnMCUGA1UECgweUGF5bWVudCBSZXF1ZXN0IEludGVybWVkaWF0\ -ZSAzMB4XDTEzMDIyMzIyNDIyOVoXDTIzMDIyMTIyNDIyOVowPzEUMBIGA1UEAwwL\ -dGVzdGNhNC5vcmcxJzAlBgNVBAoMHlBheW1lbnQgUmVxdWVzdCBJbnRlcm1lZGlh\ -dGUgNDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAxYYo3w2UXiYg6O8b4Qgw\ -N/vgreTkiW122Ep/z2TiDrhVMhfOOiKdwYESPflfnXnVaQQzCGexYTQqsvqvzHSy\ -na5hL0zPTRJxSKmTVrXRsWtpdCRhjxCGipS3tlQBDi7vb+7SNRIBK4dBjjGzALNk\ -7gMCpy+yM8f6I043jTlmGb0CAwEAAaMQMA4wDAYDVR0TBAUwAwEB/zANBgkqhkiG\ -9w0BAQsFAAOBgQDU+IQxt3OhKqaUYWC23+cB2gekvWqwMBnrCNrX/Dp+kjoJKUoR\ -2Fs3qw53raHES4SIhpGT9l9lrppNQgFe/JMHeYqOZMZO+6kuU0olJanBJ14tPIc7\ -zlMTQ9OfmZ6v07IpyFbsQDtRhpe80DpuvSFPfJ4fh0WrQf6kn3KDVpGDnAqIBDCC\ -AgQwggFtoAMCAQICAQIwDQYJKoZIhvcNAQELBQAwPzEUMBIGA1UEAwwLdGVzdGNh\ -Mi5vcmcxJzAlBgNVBAoMHlBheW1lbnQgUmVxdWVzdCBJbnRlcm1lZGlhdGUgMjAe\ -Fw0xMzAyMjMyMjQyMjlaFw0yMzAyMjEyMjQyMjlaMD8xFDASBgNVBAMMC3Rlc3Rj\ -YTMub3JnMScwJQYDVQQKDB5QYXltZW50IFJlcXVlc3QgSW50ZXJtZWRpYXRlIDMw\ -gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANzgVP99Qg98e6NsKEz1v5KqRB7N\ -TBRRsYnBvb/TSWipvMQaCYuEyk1xG57x++QuASKeR3QHRQJOoAhQaj9JLUhSSv9G\ -Q5PrFLLsOFv7L1tpzXHh2dOBIW92X2yFRW2s39q+Q21yvN+N8uoKdqXhzRA+dDoX\ -h3cavaVeHX1G+IrlAgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEL\ -BQADgYEASTwg84cX+1UhOG9sejFV3m34QuI1hPZ+qhqVJlRYUtego8Wng1BburDS\ -wqVAv4ch2wi3c2s4e8J7AXyLtzSbSQG4RN0oZi0mR8EtTTN+Mix/hBIk79dMZg85\ -+I29uFA6Zj2d9oAhQv2qkHhc6tcaheNvkQRlCyH68k3iF1Fqf+4KiAQwggIEMIIB\ -baADAgECAgECMA0GCSqGSIb3DQEBCwUAMD8xFDASBgNVBAMMC3Rlc3RjYTEub3Jn\ -MScwJQYDVQQKDB5QYXltZW50IFJlcXVlc3QgSW50ZXJtZWRpYXRlIDEwHhcNMTMw\ -MjIzMjI0MjI5WhcNMjMwMjIxMjI0MjI5WjA/MRQwEgYDVQQDDAt0ZXN0Y2EyLm9y\ -ZzEnMCUGA1UECgweUGF5bWVudCBSZXF1ZXN0IEludGVybWVkaWF0ZSAyMIGfMA0G\ -CSqGSIb3DQEBAQUAA4GNADCBiQKBgQDaV8zhfyQuSf/f+fauMfgs3g/RnWy9yxxU\ -kvQneQQPH3uZzCyk3A6q72ipTtwNqiibG9455L9A7SaUjGtnpUz0NKT/VWUdqbfC\ -l1PqXjEZbDobbAQ5hxLGOTyLRQhLIcgeq2/BnmeCqHsC4md04nUp+nBo1HwKyygv\ -K+9sMbCp/wIDAQABoxAwDjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4GB\ -ACvYyE+PPmWFkbjyRu9LAt8DcrtyYYLRClKSg6tVvutwukLG2l//kDOohYkJtgTq\ -r6LnCIIIwYdXN+4wxugmw4cnPIZmP6kovxjhhVM95okilor1zniTAo3RN7JDIfTG\ -NgxLdGu1btt7DOFL4zTbeSJMb8M1JpPftehH+x/VLyuUCuoDMIIB5jCCAU+gAwIB\ -AgIBBTANBgkqhkiG9w0BAQsFADAhMR8wHQYDVQQDExZQYXltZW50UmVxdWVzdCBU\ -ZXN0IENBMB4XDTEzMDIyMzIyNDIyOFoXDTIzMDIyMTIyNDIyOFowPzEUMBIGA1UE\ -AwwLdGVzdGNhMS5vcmcxJzAlBgNVBAoMHlBheW1lbnQgUmVxdWVzdCBJbnRlcm1l\ -ZGlhdGUgMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAo5Vy9H3nA/OOkF5A\ -p89yfVNSiTay/LYCaB0eALpcU690U75O9Q3w2M+2AN8wpbbHsJHZMIjEeBRoQfjl\ -YXW1ucQTxWKyT+liu0D25mGXX27CBXBd4iXTxVII/iX+u3lcjORjoHOBy7QgeIDI\ -IS9y0vYu8eArpjh7m4thrVgIRtMCAwEAAaMQMA4wDAYDVR0TBAUwAwEB/zANBgkq\ -hkiG9w0BAQsFAAOBgQB9LKcVJK9sjASNzpQlpUp7nCiw5FSjVY+XMRIKK/kavzlK\ -jZ+InsmmyRVGjDoZi9GrqG9PVHgLBxi2VtVjmokZoNPqao3OfhqORAubC+JR/JLe\ -pM7aDaxDdTHVhSUk4lgNAvi26dGY7nZMsnHlPQ2tPp/HvRRiMq1oDjlylc8VTCI1\ -Eh8IsNsGEhl2qRSVYIoDyPul6RMbTSzv4tVhVfGZqIisGLLhxYsFKgxVbml0VGVz\ -dEZvdXIqgAEBE1PP93Tkpif35F+dYmXn9kLA/1djcPjCs2o2rwRMM4Uk356O5dgu\ -HXQjsfdR58qZQS9CS5DAtRUf0R8+43/wijO/hb49VNaNXmY+/cPHMkahP2aV3tZi\ -FAyZblLik9A7ZvF+UsjeFQiHB5wzWQvbqk5wQ4yabHIXoYv/E0q+eQ==\ -"; - -// -// Validly signed, but by a CA not in our root CA list -// -const char* paymentrequest5_cert1_BASE64 = -"\ -Egt4NTA5K3NoYTI1NhrxAwruAzCCAeowggFToAMCAQICAQEwDQYJKoZIhvcNAQEL\ -BQAwITEfMB0GA1UEAxMWUGF5bWVudFJlcXVlc3QgVGVzdCBDQTAeFw0xMzA0MTkx\ -NzIwMDZaFw0yMzA0MTcxNzIwMDZaMEMxGTAXBgNVBAMMEHRlc3RtZXJjaGFudC5v\ -cmcxJjAkBgNVBAoMHVBheW1lbnQgUmVxdWVzdCBUZXN0IE1lcmNoYW50MIGfMA0G\ -CSqGSIb3DQEBAQUAA4GNADCBiQKBgQDhV6Yn47aEEmbl50YLvXoqGEJA51I/40wr\ -Z6VQGdXYaRqYktagrWDlgYY9h0JQ1bQhm8HgW7ju0R4NaDTXUqxg4HjprF0z3Mfm\ -/6mmebkLOOptfkVD7ceAteNI7cyuqWGIAZA7D9mV97mXoCAtTlBUycvkmoiClCCS\ -h0EpF/UTaQIDAQABoxAwDjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4GB\ -AGIRwW7I0QvLga+RnJoJSZNZQbtu4rQW3xmoz8WfZMBYXX3QBYg5ftycbdK+/IbP\ -qozfjGW2AS6DNArvpveSPDTK9+GJBNo1paiNtVqwXkC3Ddscv5AIms1eZGiIOQNC\ -mUvdLkpoXo48WAer3EGsZ3B15GyNEELc0q9W5yUebba1IjUSHwiw2wYSGXapFJVg\ -igPI+6XpExtNLO/i1WFV8ZmoiKwYuPvFiwUqDFVuaXRUZXN0Rml2ZSqAAXdsMgdG\ -ssymvca1S/1KeM3n8Ydi2fi1JUzAAr59xPvNJRUeqCLP9upHn5z7br3P12Oz9A20\ -5/4wL4ClPRPVnOHgij0bEg+y0tGESqmF1rfOfXDszlo2U92wCxS07kq79YAZJ1Zo\ -XYh860/Q4wvc7lfiTe+dXBzPKAKhMy91yETY\ -"; - -// -// Contains a testnet paytoaddress, so payment request network doesn't match client network -// -const char* paymentrequest1_cert2_BASE64 = -"\ -Egt4NTA5K3NoYTI1NhrQBArNBDCCAkkwggExoAMCAQICAQEwDQYJKoZIhvcNAQEL\ -BQAwITEfMB0GA1UEAwwWUGF5bWVudFJlcXVlc3QgVGVzdCBDQTAeFw0xNTAxMTEx\ -ODIxMDhaFw0yNTAxMDgxODIxMDhaMCExHzAdBgNVBAMMFlBheW1lbnRSZXF1ZXN0\ -IFRlc3QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMsZqzkzeBGo+i2N\ -mUak3Ciodr1V7S062VOy7N0OQYNDQHYkgDFAUET7cEb5VJaHPv5m3ppTBpU9xBcf\ -wbHHUt4VjA+mhRmYrl1khjvZM+X8kEqvWn20BtcM9R6r0yIYec8UERDDHBleL/P8\ -RkxEnVLjYTV9zigCXfMsgYb3EQShAgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8wDQYJ\ -KoZIhvcNAQELBQADggEBABUJpl3QCqsoDSxAsQdV6zKT4VGV76AzoGj7etQsQY+r\ -+S26VfWh/fMobEzuxFChr0USgLJ6FoK78hAtoZvt1lrye9yqFv/ig3WLWsJKWHHb\ -3RT6oR03CIwZXFSUasi08QDVLxafwsU5OMcPLucF3a1lRL1ccYrNgVCCx1+X7Bos\ -tIgDGRQQ4AyoHTcfVd2hEGeUv7k14mOxFsAp6851yosHq9Q2kwmdH+rHEJbjof87\ -yyKLagc4owyXBZYkQmkeHWCNqnuRmO5vUsfVb0UUrkD64o7Th/NjwooA7SCiUXl6\ -dfygT1b7ggpx7GC+sP2DsIM47IAZ55drjqX5u2f+Ba0iPQoEdGVzdBIhCIDWwowE\ -Ehl2qRQErGqUUwSsaMpDvWIaGnJGNQqi8oisGNeMy6UFKgxKdXN0IFRlc3Rpbmcq\ -gAFwThsozZxkZxzCn4R8WxNiLFV6m0ye9fEtSbolfaW+EjBMpO03lr/dwNnrclhg\ -ew+A05xfZztrAt16XKEY7qKJ/eY2nLd0fVAIu/nIt+7/VYVXT83zLrWc150aRS7W\ -AdJbL3JOJLs6Eyp5zrPbfI8faRttFAdONKDrJgIpuW1E3g==\ -"; - -// -// Expired payment request (expires is set to 1 = 1970-01-01 00:00:01) -// -const char* paymentrequest2_cert2_BASE64 = -"\ -Egt4NTA5K3NoYTI1NhrQBArNBDCCAkkwggExoAMCAQICAQEwDQYJKoZIhvcNAQEL\ -BQAwITEfMB0GA1UEAwwWUGF5bWVudFJlcXVlc3QgVGVzdCBDQTAeFw0xNTAxMTEx\ -ODIxMDhaFw0yNTAxMDgxODIxMDhaMCExHzAdBgNVBAMMFlBheW1lbnRSZXF1ZXN0\ -IFRlc3QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMsZqzkzeBGo+i2N\ -mUak3Ciodr1V7S062VOy7N0OQYNDQHYkgDFAUET7cEb5VJaHPv5m3ppTBpU9xBcf\ -wbHHUt4VjA+mhRmYrl1khjvZM+X8kEqvWn20BtcM9R6r0yIYec8UERDDHBleL/P8\ -RkxEnVLjYTV9zigCXfMsgYb3EQShAgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8wDQYJ\ -KoZIhvcNAQELBQADggEBABUJpl3QCqsoDSxAsQdV6zKT4VGV76AzoGj7etQsQY+r\ -+S26VfWh/fMobEzuxFChr0USgLJ6FoK78hAtoZvt1lrye9yqFv/ig3WLWsJKWHHb\ -3RT6oR03CIwZXFSUasi08QDVLxafwsU5OMcPLucF3a1lRL1ccYrNgVCCx1+X7Bos\ -tIgDGRQQ4AyoHTcfVd2hEGeUv7k14mOxFsAp6851yosHq9Q2kwmdH+rHEJbjof87\ -yyKLagc4owyXBZYkQmkeHWCNqnuRmO5vUsfVb0UUrkD64o7Th/NjwooA7SCiUXl6\ -dfygT1b7ggpx7GC+sP2DsIM47IAZ55drjqX5u2f+Ba0iQgoEdGVzdBIgCICt4gQS\ -GXapFASsapRTBKxoykO9YhoackY1CqLyiKwYiNLUpQUgASoQVGVzdGluZyB0ZXN0\ -bmV0ISqAATXq9A5nmJgtmee/bQTeHeif4w1YYFPBlKghwx6qbVgXTWnwBJtOQhhV\ -sZdzbTl95ENR7/Y7VJupW9kDWobCK7zUUhLAzUlwmLlcx6itHw8LTUF5HK+AwsZm\ -Zs85lISGvOS0NZW/ENa6l+oQRnL87oqVZr/EDGiuqjz6T0ThQi0l\ -"; - -// -// Unexpired payment request (expires is set to 0x7FFFFFFFFFFFFFFF = max. int64_t) -// -const char* paymentrequest3_cert2_BASE64 = -"\ -Egt4NTA5K3NoYTI1NhrQBArNBDCCAkkwggExoAMCAQICAQEwDQYJKoZIhvcNAQEL\ -BQAwITEfMB0GA1UEAwwWUGF5bWVudFJlcXVlc3QgVGVzdCBDQTAeFw0xNTAxMTEx\ -ODIxMDhaFw0yNTAxMDgxODIxMDhaMCExHzAdBgNVBAMMFlBheW1lbnRSZXF1ZXN0\ -IFRlc3QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMsZqzkzeBGo+i2N\ -mUak3Ciodr1V7S062VOy7N0OQYNDQHYkgDFAUET7cEb5VJaHPv5m3ppTBpU9xBcf\ -wbHHUt4VjA+mhRmYrl1khjvZM+X8kEqvWn20BtcM9R6r0yIYec8UERDDHBleL/P8\ -RkxEnVLjYTV9zigCXfMsgYb3EQShAgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8wDQYJ\ -KoZIhvcNAQELBQADggEBABUJpl3QCqsoDSxAsQdV6zKT4VGV76AzoGj7etQsQY+r\ -+S26VfWh/fMobEzuxFChr0USgLJ6FoK78hAtoZvt1lrye9yqFv/ig3WLWsJKWHHb\ -3RT6oR03CIwZXFSUasi08QDVLxafwsU5OMcPLucF3a1lRL1ccYrNgVCCx1+X7Bos\ -tIgDGRQQ4AyoHTcfVd2hEGeUv7k14mOxFsAp6851yosHq9Q2kwmdH+rHEJbjof87\ -yyKLagc4owyXBZYkQmkeHWCNqnuRmO5vUsfVb0UUrkD64o7Th/NjwooA7SCiUXl6\ -dfygT1b7ggpx7GC+sP2DsIM47IAZ55drjqX5u2f+Ba0iSgoEdGVzdBIgCICt4gQS\ -GXapFASsapRTBKxoykO9YhoackY1CqLyiKwYyNfZpQUg//////////9/KhBUZXN0\ -aW5nIHRlc3RuZXQhKoABNwi8WnMW4aMvbmvorTiiWJLFhofLFnsoWCJnj3rWLnLh\ -n3w6q/fZ26p50ERL/noxdTUfeFsKnlECkUu/fOcOrqyYDiwvxI0SZ034DleVyFU1\ -Z3T+X0zcL8oe7bX01Yf+s2V+5JXQXarKnKBrZCGgv2ARjFNSZe7E7vGg5K4Q6Q8=\ -"; - -// -// Unexpired payment request (expires is set to 0x8000000000000000 > max. int64_t, allowed uint64) -// -const char* paymentrequest4_cert2_BASE64 = -"\ -Egt4NTA5K3NoYTI1NhrQBArNBDCCAkkwggExoAMCAQICAQEwDQYJKoZIhvcNAQEL\ -BQAwITEfMB0GA1UEAwwWUGF5bWVudFJlcXVlc3QgVGVzdCBDQTAeFw0xNTAxMTEx\ -ODIxMDhaFw0yNTAxMDgxODIxMDhaMCExHzAdBgNVBAMMFlBheW1lbnRSZXF1ZXN0\ -IFRlc3QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMsZqzkzeBGo+i2N\ -mUak3Ciodr1V7S062VOy7N0OQYNDQHYkgDFAUET7cEb5VJaHPv5m3ppTBpU9xBcf\ -wbHHUt4VjA+mhRmYrl1khjvZM+X8kEqvWn20BtcM9R6r0yIYec8UERDDHBleL/P8\ -RkxEnVLjYTV9zigCXfMsgYb3EQShAgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8wDQYJ\ -KoZIhvcNAQELBQADggEBABUJpl3QCqsoDSxAsQdV6zKT4VGV76AzoGj7etQsQY+r\ -+S26VfWh/fMobEzuxFChr0USgLJ6FoK78hAtoZvt1lrye9yqFv/ig3WLWsJKWHHb\ -3RT6oR03CIwZXFSUasi08QDVLxafwsU5OMcPLucF3a1lRL1ccYrNgVCCx1+X7Bos\ -tIgDGRQQ4AyoHTcfVd2hEGeUv7k14mOxFsAp6851yosHq9Q2kwmdH+rHEJbjof87\ -yyKLagc4owyXBZYkQmkeHWCNqnuRmO5vUsfVb0UUrkD64o7Th/NjwooA7SCiUXl6\ -dfygT1b7ggpx7GC+sP2DsIM47IAZ55drjqX5u2f+Ba0iSwoEdGVzdBIgCICt4gQS\ -GXapFASsapRTBKxoykO9YhoackY1CqLyiKwYt+HZpQUggICAgICAgICAASoQVGVz\ -dGluZyB0ZXN0bmV0ISqAAXSQG8+GFA18VaKarlYrOz293rNMIub0swKGcQm8jAGX\ -HSLaRgHfUDeEPr4hydy4dtfu59KNwe2xsHOHu/SpO4L8SrA4Dm9A7SlNBVWdcLbw\ -d2hj739GDLz0b5KuJ2SG6VknMRQM976w/m2qlq0ccVGaaZ2zMIGfpzL3p6adwx/5\ -"; - -// -// Payment request with amount overflow (amount is set to 21000001 BTC) -// -const char* paymentrequest5_cert2_BASE64 = -"\ -Egt4NTA5K3NoYTI1NhrQBArNBDCCAkkwggExoAMCAQICAQEwDQYJKoZIhvcNAQEL\ -BQAwITEfMB0GA1UEAwwWUGF5bWVudFJlcXVlc3QgVGVzdCBDQTAeFw0xNTAxMTEx\ -ODIxMDhaFw0yNTAxMDgxODIxMDhaMCExHzAdBgNVBAMMFlBheW1lbnRSZXF1ZXN0\ -IFRlc3QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMsZqzkzeBGo+i2N\ -mUak3Ciodr1V7S062VOy7N0OQYNDQHYkgDFAUET7cEb5VJaHPv5m3ppTBpU9xBcf\ -wbHHUt4VjA+mhRmYrl1khjvZM+X8kEqvWn20BtcM9R6r0yIYec8UERDDHBleL/P8\ -RkxEnVLjYTV9zigCXfMsgYb3EQShAgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8wDQYJ\ -KoZIhvcNAQELBQADggEBABUJpl3QCqsoDSxAsQdV6zKT4VGV76AzoGj7etQsQY+r\ -+S26VfWh/fMobEzuxFChr0USgLJ6FoK78hAtoZvt1lrye9yqFv/ig3WLWsJKWHHb\ -3RT6oR03CIwZXFSUasi08QDVLxafwsU5OMcPLucF3a1lRL1ccYrNgVCCx1+X7Bos\ -tIgDGRQQ4AyoHTcfVd2hEGeUv7k14mOxFsAp6851yosHq9Q2kwmdH+rHEJbjof87\ -yyKLagc4owyXBZYkQmkeHWCNqnuRmO5vUsfVb0UUrkD64o7Th/NjwooA7SCiUXl6\ -dfygT1b7ggpx7GC+sP2DsIM47IAZ55drjqX5u2f+Ba0iTAoEdGVzdBIkCIDC9P+F\ -vt0DEhl2qRQErGqUUwSsaMpDvWIaGnJGNQqi8oisGLzcrKYFKhhUZXN0aW5nIGFt\ -b3VudCBvdmVyZmxvdyEqgAG8S7WEDUC6tCL6q2CTBjop/AitgEy31RL9IqYruytR\ -iEBFUrBDJZU+UEezGwr7/zoECjo5ZY3PmtZcM2sILNjyweJF6XVzGqTxUw6pN6sW\ -XR2T3Gy2LzRvhVA25QgGqpz0/juS2BtmNbsZPkN9gMMwKimgzc+PuCzmEKwPK9cQ\ -YQ==\ -"; - -#endif // BITCOIN_QT_TEST_PAYMENTREQUESTDATA_H diff --git a/src/qt/test/paymentservertests.cpp b/src/qt/test/paymentservertests.cpp deleted file mode 100644 index eca468a6ab..0000000000 --- a/src/qt/test/paymentservertests.cpp +++ /dev/null @@ -1,216 +0,0 @@ -// Copyright (c) 2009-2018 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include <qt/test/paymentservertests.h> - -#include <qt/optionsmodel.h> -#include <qt/test/paymentrequestdata.h> - -#include <amount.h> -#include <chainparams.h> -#include <interfaces/node.h> -#include <random.h> -#include <script/script.h> -#include <script/standard.h> -#include <test/setup_common.h> -#include <util/strencodings.h> - -#include <openssl/ssl.h> -#include <openssl/x509.h> -#include <openssl/x509_vfy.h> - -#include <QFileOpenEvent> -#include <QTemporaryFile> - -X509 *parse_b64der_cert(const char* cert_data) -{ - std::vector<unsigned char> data = DecodeBase64(cert_data); - assert(data.size() > 0); - const unsigned char* dptr = data.data(); - X509 *cert = d2i_X509(nullptr, &dptr, data.size()); - assert(cert); - return cert; -} - -// -// Test payment request handling -// - -static SendCoinsRecipient handleRequest(PaymentServer* server, std::vector<unsigned char>& data) -{ - RecipientCatcher sigCatcher; - QObject::connect(server, &PaymentServer::receivedPaymentRequest, - &sigCatcher, &RecipientCatcher::getRecipient); - - // Write data to a temp file: - QTemporaryFile f; - f.open(); - f.write((const char*)data.data(), data.size()); - f.close(); - - // Create a QObject, install event filter from PaymentServer - // and send a file open event to the object - QObject object; - object.installEventFilter(server); - QFileOpenEvent event(f.fileName()); - // If sending the event fails, this will cause sigCatcher to be empty, - // which will lead to a test failure anyway. - QCoreApplication::sendEvent(&object, &event); - - QObject::disconnect(server, &PaymentServer::receivedPaymentRequest, - &sigCatcher, &RecipientCatcher::getRecipient); - - // Return results from sigCatcher - return sigCatcher.recipient; -} - -void PaymentServerTests::paymentServerTests() -{ - SSL_library_init(); - BasicTestingSetup testing_setup(CBaseChainParams::MAIN); - auto node = interfaces::MakeNode(); - OptionsModel optionsModel(*node); - PaymentServer* server = new PaymentServer(nullptr, false); - X509_STORE* caStore = X509_STORE_new(); - X509_STORE_add_cert(caStore, parse_b64der_cert(caCert1_BASE64)); - PaymentServer::LoadRootCAs(caStore); - server->setOptionsModel(&optionsModel); - server->uiReady(); - - std::vector<unsigned char> data; - SendCoinsRecipient r; - QString merchant; - - // Now feed PaymentRequests to server, and observe signals it produces - - // This payment request validates directly against the - // caCert1 certificate authority: - data = DecodeBase64(paymentrequest1_cert1_BASE64); - r = handleRequest(server, data); - r.paymentRequest.getMerchant(caStore, merchant); - QCOMPARE(merchant, QString("testmerchant.org")); - - // Signed, but expired, merchant cert in the request: - data = DecodeBase64(paymentrequest2_cert1_BASE64); - r = handleRequest(server, data); - r.paymentRequest.getMerchant(caStore, merchant); - QCOMPARE(merchant, QString("")); - - // 10-long certificate chain, all intermediates valid: - data = DecodeBase64(paymentrequest3_cert1_BASE64); - r = handleRequest(server, data); - r.paymentRequest.getMerchant(caStore, merchant); - QCOMPARE(merchant, QString("testmerchant8.org")); - - // Long certificate chain, with an expired certificate in the middle: - data = DecodeBase64(paymentrequest4_cert1_BASE64); - r = handleRequest(server, data); - r.paymentRequest.getMerchant(caStore, merchant); - QCOMPARE(merchant, QString("")); - - // Validly signed, but by a CA not in our root CA list: - data = DecodeBase64(paymentrequest5_cert1_BASE64); - r = handleRequest(server, data); - r.paymentRequest.getMerchant(caStore, merchant); - QCOMPARE(merchant, QString("")); - - // Try again with no root CA's, verifiedMerchant should be empty: - caStore = X509_STORE_new(); - PaymentServer::LoadRootCAs(caStore); - data = DecodeBase64(paymentrequest1_cert1_BASE64); - r = handleRequest(server, data); - r.paymentRequest.getMerchant(caStore, merchant); - QCOMPARE(merchant, QString("")); - - // Load second root certificate - caStore = X509_STORE_new(); - X509_STORE_add_cert(caStore, parse_b64der_cert(caCert2_BASE64)); - PaymentServer::LoadRootCAs(caStore); - - QByteArray byteArray; - - // For the tests below we just need the payment request data from - // paymentrequestdata.h parsed + stored in r.paymentRequest. - // - // These tests require us to bypass the following normal client execution flow - // shown below to be able to explicitly just trigger a certain condition! - // - // handleRequest() - // -> PaymentServer::eventFilter() - // -> PaymentServer::handleURIOrFile() - // -> PaymentServer::readPaymentRequestFromFile() - // -> PaymentServer::processPaymentRequest() - - // Contains a testnet paytoaddress, so payment request network doesn't match client network: - data = DecodeBase64(paymentrequest1_cert2_BASE64); - byteArray = QByteArray((const char*)data.data(), data.size()); - r.paymentRequest.parse(byteArray); - // Ensure the request is initialized, because network "main" is default, even for - // uninitialized payment requests and that will fail our test here. - QVERIFY(r.paymentRequest.IsInitialized()); - QCOMPARE(PaymentServer::verifyNetwork(*node, r.paymentRequest.getDetails()), false); - - // Expired payment request (expires is set to 1 = 1970-01-01 00:00:01): - data = DecodeBase64(paymentrequest2_cert2_BASE64); - byteArray = QByteArray((const char*)data.data(), data.size()); - r.paymentRequest.parse(byteArray); - // Ensure the request is initialized - QVERIFY(r.paymentRequest.IsInitialized()); - // compares 1 < GetTime() == false (treated as expired payment request) - QCOMPARE(PaymentServer::verifyExpired(r.paymentRequest.getDetails()), true); - - // Unexpired payment request (expires is set to 0x7FFFFFFFFFFFFFFF = max. int64_t): - // 9223372036854775807 (uint64), 9223372036854775807 (int64_t) and -1 (int32_t) - // -1 is 1969-12-31 23:59:59 (for a 32 bit time values) - data = DecodeBase64(paymentrequest3_cert2_BASE64); - byteArray = QByteArray((const char*)data.data(), data.size()); - r.paymentRequest.parse(byteArray); - // Ensure the request is initialized - QVERIFY(r.paymentRequest.IsInitialized()); - // compares 9223372036854775807 < GetTime() == false (treated as unexpired payment request) - QCOMPARE(PaymentServer::verifyExpired(r.paymentRequest.getDetails()), false); - - // Unexpired payment request (expires is set to 0x8000000000000000 > max. int64_t, allowed uint64): - // 9223372036854775808 (uint64), -9223372036854775808 (int64_t) and 0 (int32_t) - // 0 is 1970-01-01 00:00:00 (for a 32 bit time values) - data = DecodeBase64(paymentrequest4_cert2_BASE64); - byteArray = QByteArray((const char*)data.data(), data.size()); - r.paymentRequest.parse(byteArray); - // Ensure the request is initialized - QVERIFY(r.paymentRequest.IsInitialized()); - // compares -9223372036854775808 < GetTime() == true (treated as expired payment request) - QCOMPARE(PaymentServer::verifyExpired(r.paymentRequest.getDetails()), true); - - // Test BIP70 DoS protection: - auto randdata = FastRandomContext().randbytes(BIP70_MAX_PAYMENTREQUEST_SIZE + 1); - - // Write data to a temp file: - QTemporaryFile tempFile; - tempFile.open(); - tempFile.write((const char*)randdata.data(), randdata.size()); - tempFile.close(); - // compares 50001 <= BIP70_MAX_PAYMENTREQUEST_SIZE == false - QCOMPARE(PaymentServer::verifySize(tempFile.size()), false); - - // Payment request with amount overflow (amount is set to 21000001 BTC): - data = DecodeBase64(paymentrequest5_cert2_BASE64); - byteArray = QByteArray((const char*)data.data(), data.size()); - r.paymentRequest.parse(byteArray); - // Ensure the request is initialized - QVERIFY(r.paymentRequest.IsInitialized()); - // Extract address and amount from the request - QList<std::pair<CScript, CAmount> > sendingTos = r.paymentRequest.getPayTo(); - for (const std::pair<CScript, CAmount>& sendingTo : sendingTos) { - CTxDestination dest; - if (ExtractDestination(sendingTo.first, dest)) - QCOMPARE(PaymentServer::verifyAmount(sendingTo.second), false); - } - - delete server; -} - -void RecipientCatcher::getRecipient(const SendCoinsRecipient& r) -{ - recipient = r; -} diff --git a/src/qt/test/paymentservertests.h b/src/qt/test/paymentservertests.h deleted file mode 100644 index 7ef7a0a641..0000000000 --- a/src/qt/test/paymentservertests.h +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) 2009-2018 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#ifndef BITCOIN_QT_TEST_PAYMENTSERVERTESTS_H -#define BITCOIN_QT_TEST_PAYMENTSERVERTESTS_H - -#include <qt/paymentserver.h> - -#include <QObject> -#include <QTest> - -class PaymentServerTests : public QObject -{ - Q_OBJECT - -private Q_SLOTS: - void paymentServerTests(); -}; - -// Dummy class to receive paymentserver signals. -// If SendCoinsRecipient was a proper QObject, then -// we could use QSignalSpy... but it's not. -class RecipientCatcher : public QObject -{ - Q_OBJECT - -public Q_SLOTS: - void getRecipient(const SendCoinsRecipient& r); - -public: - SendCoinsRecipient recipient; -}; - -#endif // BITCOIN_QT_TEST_PAYMENTSERVERTESTS_H diff --git a/src/qt/test/test_main.cpp b/src/qt/test/test_main.cpp index c39266a397..f272627f96 100644 --- a/src/qt/test/test_main.cpp +++ b/src/qt/test/test_main.cpp @@ -16,9 +16,6 @@ #ifdef ENABLE_WALLET #include <qt/test/addressbooktests.h> -#ifdef ENABLE_BIP70 -#include <qt/test/paymentservertests.h> -#endif // ENABLE_BIP70 #include <qt/test/wallettests.h> #endif // ENABLE_WALLET @@ -79,12 +76,6 @@ int main(int argc, char *argv[]) if (QTest::qExec(&test1) != 0) { fInvalid = true; } -#if defined(ENABLE_WALLET) && defined(ENABLE_BIP70) - PaymentServerTests test2; - if (QTest::qExec(&test2) != 0) { - fInvalid = true; - } -#endif RPCNestedTests test3; if (QTest::qExec(&test3) != 0) { fInvalid = true; diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index 648fdb7673..318b0756c7 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -18,7 +18,6 @@ #include <key_io.h> #include <validation.h> #include <script/script.h> -#include <timedata.h> #include <util/system.h> #include <policy/policy.h> #include <wallet/ismine.h> @@ -49,7 +48,6 @@ QString TransactionDesc::FormatTxStatus(const interfaces::WalletTx& wtx, const i } } -#ifndef ENABLE_BIP70 // Takes an encoded PaymentRequest as a string and tries to find the Common Name of the X.509 certificate // used to sign the PaymentRequest. bool GetPaymentRequestMerchant(const std::string& pr, QString& merchant) @@ -77,7 +75,6 @@ bool GetPaymentRequestMerchant(const std::string& pr, QString& merchant) } return false; } -#endif QString TransactionDesc::toHTML(interfaces::Node& node, interfaces::Wallet& wallet, TransactionRecord *rec, int unit) { @@ -295,19 +292,11 @@ QString TransactionDesc::toHTML(interfaces::Node& node, interfaces::Wallet& wall if (r.first == "PaymentRequest") { QString merchant; -#ifdef ENABLE_BIP70 - PaymentRequestPlus req; - req.parse(QByteArray::fromRawData(r.second.data(), r.second.size())); - if (!req.getMerchant(PaymentServer::getCertStore(), merchant)) { - merchant.clear(); - } -#else if (!GetPaymentRequestMerchant(r.second, merchant)) { merchant.clear(); } else { merchant += tr(" (Certificate was not verified)"); } -#endif if (!merchant.isNull()) { strHTML += "<b>" + tr("Merchant") + ":</b> " + GUIUtil::HtmlEscape(merchant) + "<br>"; } diff --git a/src/qt/utilitydialog.cpp b/src/qt/utilitydialog.cpp index 6509a701f3..095c98d26f 100644 --- a/src/qt/utilitydialog.cpp +++ b/src/qt/utilitydialog.cpp @@ -11,9 +11,6 @@ #include <qt/forms/ui_helpmessagedialog.h> #include <qt/bitcoingui.h> -#ifdef ENABLE_BIP70 -#include <qt/paymentrequestplus.h> -#endif #include <clientversion.h> #include <init.h> diff --git a/src/qt/walletcontroller.cpp b/src/qt/walletcontroller.cpp index fa6f9f3f16..4c253f8ddd 100644 --- a/src/qt/walletcontroller.cpp +++ b/src/qt/walletcontroller.cpp @@ -12,6 +12,7 @@ #include <interfaces/handler.h> #include <interfaces/node.h> +#include <util/string.h> #include <algorithm> @@ -108,6 +109,12 @@ WalletModel* WalletController::getOrCreateWallet(std::unique_ptr<interfaces::Wal wallet_model->setParent(this); m_wallets.push_back(wallet_model); + // WalletModel::startPollBalance needs to be called in a thread managed by + // Qt because of startTimer. Considering the current thread can be a RPC + // thread, better delegate the calling to Qt with Qt::AutoConnection. + const bool called = QMetaObject::invokeMethod(wallet_model, "startPollBalance"); + assert(called); + connect(wallet_model, &WalletModel::unload, [this, wallet_model] { // Defer removeAndDeleteWallet when no modal widget is active. // TODO: remove this workaround by removing usage of QDiallog::exec. @@ -226,7 +233,7 @@ void CreateWalletActivity::finish() if (!m_error_message.empty()) { QMessageBox::critical(m_parent_widget, tr("Create wallet failed"), QString::fromStdString(m_error_message)); } else if (!m_warning_message.empty()) { - QMessageBox::warning(m_parent_widget, tr("Create wallet warning"), QString::fromStdString(m_warning_message)); + QMessageBox::warning(m_parent_widget, tr("Create wallet warning"), QString::fromStdString(Join(m_warning_message, "\n"))); } if (m_wallet_model) Q_EMIT created(m_wallet_model); @@ -267,7 +274,7 @@ void OpenWalletActivity::finish() if (!m_error_message.empty()) { QMessageBox::critical(m_parent_widget, tr("Open wallet failed"), QString::fromStdString(m_error_message)); } else if (!m_warning_message.empty()) { - QMessageBox::warning(m_parent_widget, tr("Open wallet warning"), QString::fromStdString(m_warning_message)); + QMessageBox::warning(m_parent_widget, tr("Open wallet warning"), QString::fromStdString(Join(m_warning_message, "\n"))); } if (m_wallet_model) Q_EMIT opened(m_wallet_model); diff --git a/src/qt/walletcontroller.h b/src/qt/walletcontroller.h index fb37b7292c..e50dd5c7eb 100644 --- a/src/qt/walletcontroller.h +++ b/src/qt/walletcontroller.h @@ -100,7 +100,7 @@ protected: QProgressDialog* m_progress_dialog{nullptr}; WalletModel* m_wallet_model{nullptr}; std::string m_error_message; - std::string m_warning_message; + std::vector<std::string> m_warning_message; }; diff --git a/src/qt/walletframe.cpp b/src/qt/walletframe.cpp index 94413547d4..d7f0617315 100644 --- a/src/qt/walletframe.cpp +++ b/src/qt/walletframe.cpp @@ -9,7 +9,6 @@ #include <qt/walletview.h> #include <cassert> -#include <cstdio> #include <QHBoxLayout> #include <QLabel> diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index 49a13330ec..33801d3907 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -44,11 +44,6 @@ WalletModel::WalletModel(std::unique_ptr<interfaces::Wallet> wallet, interfaces: transactionTableModel = new TransactionTableModel(platformStyle, this); recentRequestsTableModel = new RecentRequestsTableModel(this); - // This timer will be fired repeatedly to update the balance - pollTimer = new QTimer(this); - connect(pollTimer, &QTimer::timeout, this, &WalletModel::pollBalanceChanged); - pollTimer->start(MODEL_UPDATE_DELAY); - subscribeToCoreSignals(); } @@ -57,6 +52,14 @@ WalletModel::~WalletModel() unsubscribeFromCoreSignals(); } +void WalletModel::startPollBalance() +{ + // This timer will be fired repeatedly to update the balance + QTimer* timer = new QTimer(this); + connect(timer, &QTimer::timeout, this, &WalletModel::pollBalanceChanged); + timer->start(MODEL_UPDATE_DELAY); +} + void WalletModel::updateStatus() { EncryptionStatus newEncryptionStatus = getEncryptionStatus(); @@ -143,31 +146,6 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact { if (rcp.fSubtractFeeFromAmount) fSubtractFeeFromAmount = true; - -#ifdef ENABLE_BIP70 - if (rcp.paymentRequest.IsInitialized()) - { // PaymentRequest... - CAmount subtotal = 0; - const payments::PaymentDetails& details = rcp.paymentRequest.getDetails(); - for (int i = 0; i < details.outputs_size(); i++) - { - const payments::Output& out = details.outputs(i); - if (out.amount() <= 0) continue; - subtotal += out.amount(); - const unsigned char* scriptStr = (const unsigned char*)out.script().data(); - CScript scriptPubKey(scriptStr, scriptStr+out.script().size()); - CAmount nAmount = out.amount(); - CRecipient recipient = {scriptPubKey, nAmount, rcp.fSubtractFeeFromAmount}; - vecSend.push_back(recipient); - } - if (subtotal <= 0) - { - return InvalidAmount; - } - total += subtotal; - } - else -#endif { // User-entered bitcoin address / amount: if(!validateAddress(rcp.address)) { @@ -240,29 +218,12 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &tran std::vector<std::pair<std::string, std::string>> vOrderForm; for (const SendCoinsRecipient &rcp : transaction.getRecipients()) { -#ifdef ENABLE_BIP70 - if (rcp.paymentRequest.IsInitialized()) - { - // Make sure any payment requests involved are still valid. - if (PaymentServer::verifyExpired(rcp.paymentRequest.getDetails())) { - return PaymentRequestExpired; - } - - // Store PaymentRequests in wtx.vOrderForm in wallet. - std::string value; - rcp.paymentRequest.SerializeToString(&value); - vOrderForm.emplace_back("PaymentRequest", std::move(value)); - } - else -#endif if (!rcp.message.isEmpty()) // Message from normal bitcoin:URI (bitcoin:123...?message=example) vOrderForm.emplace_back("Message", rcp.message.toStdString()); } auto& newTx = transaction.getWtx(); - std::string rejectReason; - if (!wallet().commitTransaction(newTx, {} /* mapValue */, std::move(vOrderForm), rejectReason)) - return SendCoinsReturn(TransactionCommitFailed, QString::fromStdString(rejectReason)); + wallet().commitTransaction(newTx, {} /* mapValue */, std::move(vOrderForm)); CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION); ssTx << *newTx; @@ -273,10 +234,6 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &tran // and emit coinsSent signal for each recipient for (const SendCoinsRecipient &rcp : transaction.getRecipients()) { - // Don't touch the address book when we have a payment request -#ifdef ENABLE_BIP70 - if (!rcp.paymentRequest.IsInitialized()) -#endif { std::string strAddress = rcp.address.toStdString(); CTxDestination dest = DecodeDestination(strAddress); diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h index 54428aec08..d21dec118a 100644 --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -5,24 +5,20 @@ #ifndef BITCOIN_QT_WALLETMODEL_H #define BITCOIN_QT_WALLETMODEL_H +#if defined(HAVE_CONFIG_H) +#include <config/bitcoin-config.h> +#endif + #include <amount.h> #include <key.h> #include <serialize.h> #include <script/standard.h> -#if defined(HAVE_CONFIG_H) -#include <config/bitcoin-config.h> -#endif - -#ifdef ENABLE_BIP70 -#include <qt/paymentrequestplus.h> -#endif #include <qt/walletmodeltransaction.h> #include <interfaces/wallet.h> #include <support/allocators/secure.h> -#include <map> #include <vector> #include <QObject> @@ -68,15 +64,9 @@ public: CAmount amount; // If from a payment request, this is used for storing the memo QString message; - -#ifdef ENABLE_BIP70 - // If from a payment request, paymentRequest.IsInitialized() will be true - PaymentRequestPlus paymentRequest; -#else // If building with BIP70 is disabled, keep the payment request around as // serialized string to ensure load/store is lossless std::string sPaymentRequest; -#endif // Empty if no authentication or invalid signature/cert/etc. QString authenticatedMerchant; @@ -92,11 +82,6 @@ public: std::string sAddress = address.toStdString(); std::string sLabel = label.toStdString(); std::string sMessage = message.toStdString(); -#ifdef ENABLE_BIP70 - std::string sPaymentRequest; - if (!ser_action.ForRead() && paymentRequest.IsInitialized()) - paymentRequest.SerializeToString(&sPaymentRequest); -#endif std::string sAuthenticatedMerchant = authenticatedMerchant.toStdString(); READWRITE(this->nVersion); @@ -112,10 +97,6 @@ public: address = QString::fromStdString(sAddress); label = QString::fromStdString(sLabel); message = QString::fromStdString(sMessage); -#ifdef ENABLE_BIP70 - if (!sPaymentRequest.empty()) - paymentRequest.parse(QByteArray::fromRawData(sPaymentRequest.data(), sPaymentRequest.size())); -#endif authenticatedMerchant = QString::fromStdString(sAuthenticatedMerchant); } } @@ -139,7 +120,6 @@ public: AmountWithFeeExceedsBalance, DuplicateAddress, TransactionCreationFailed, // Error returned when wallet is still locked - TransactionCommitFailed, AbsurdFee, PaymentRequestExpired }; @@ -255,8 +235,6 @@ private: EncryptionStatus cachedEncryptionStatus; int cachedNumBlocks; - QTimer *pollTimer; - void subscribeToCoreSignals(); void unsubscribeFromCoreSignals(); void checkBalanceChanged(const interfaces::WalletBalances& new_balances); @@ -292,6 +270,9 @@ Q_SIGNALS: void canGetAddressesChanged(); public Q_SLOTS: + /* Starts a timer to periodically update the balance */ + void startPollBalance(); + /* Wallet status might have changed */ void updateStatus(); /* New transaction, or transaction changed status */ diff --git a/src/qt/walletmodeltransaction.cpp b/src/qt/walletmodeltransaction.cpp index d00ccf70d9..eba95bd27c 100644 --- a/src/qt/walletmodeltransaction.cpp +++ b/src/qt/walletmodeltransaction.cpp @@ -48,25 +48,6 @@ void WalletModelTransaction::reassignAmounts(int nChangePosRet) for (QList<SendCoinsRecipient>::iterator it = recipients.begin(); it != recipients.end(); ++it) { SendCoinsRecipient& rcp = (*it); - -#ifdef ENABLE_BIP70 - if (rcp.paymentRequest.IsInitialized()) - { - CAmount subtotal = 0; - const payments::PaymentDetails& details = rcp.paymentRequest.getDetails(); - for (int j = 0; j < details.outputs_size(); j++) - { - const payments::Output& out = details.outputs(j); - if (out.amount() <= 0) continue; - if (i == nChangePosRet) - i++; - subtotal += walletTransaction->vout[i].nValue; - i++; - } - rcp.amount = subtotal; - } - else // normal recipient (no payment request) -#endif { if (i == nChangePosRet) i++; diff --git a/src/qt/walletmodeltransaction.h b/src/qt/walletmodeltransaction.h index a41d8f2457..242ba13897 100644 --- a/src/qt/walletmodeltransaction.h +++ b/src/qt/walletmodeltransaction.h @@ -7,7 +7,6 @@ #include <qt/walletmodel.h> -#include <memory> #include <amount.h> #include <QObject> diff --git a/src/qt/winshutdownmonitor.cpp b/src/qt/winshutdownmonitor.cpp index b177b22b3f..c6eb133cbd 100644 --- a/src/qt/winshutdownmonitor.cpp +++ b/src/qt/winshutdownmonitor.cpp @@ -6,14 +6,11 @@ #if defined(Q_OS_WIN) #include <shutdown.h> -#include <util/system.h> #include <windows.h> #include <QDebug> -#include <openssl/rand.h> - // If we don't want a message to be processed by Qt, return true and set result to // the value that the window procedure should return. Otherwise return false. bool WinShutdownMonitor::nativeEventFilter(const QByteArray &eventType, void *pMessage, long *pnResult) @@ -22,16 +19,6 @@ bool WinShutdownMonitor::nativeEventFilter(const QByteArray &eventType, void *pM MSG *pMsg = static_cast<MSG *>(pMessage); - // Seed OpenSSL PRNG with Windows event data (e.g. mouse movements and other user interactions) - if (RAND_event(pMsg->message, pMsg->wParam, pMsg->lParam) == 0) { - // Warn only once as this is performance-critical - static bool warned = false; - if (!warned) { - LogPrintf("%s: OpenSSL RAND_event() failed to seed OpenSSL PRNG with enough data.\n", __func__); - warned = true; - } - } - switch(pMsg->message) { case WM_QUERYENDSESSION: diff --git a/src/random.cpp b/src/random.cpp index 675b177af3..48d20d7d72 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -16,7 +16,6 @@ #include <util/time.h> // for GetTime() #include <stdlib.h> -#include <chrono> #include <thread> #include <support/allocators/secure.h> @@ -41,7 +40,6 @@ #include <sys/sysctl.h> #endif -#include <mutex> #if defined(__x86_64__) || defined(__amd64__) || defined(__i386__) #include <cpuid.h> @@ -113,7 +111,7 @@ static void InitHardwareRand() static void ReportHardwareRand() { - // This must be done in a separate function, as HWRandInit() may be indirectly called + // This must be done in a separate function, as InitHardwareRand() may be indirectly called // from global constructors, before logging is initialized. if (g_rdseed_supported) { LogPrintf("Using RdSeed as additional entropy source\n"); @@ -596,10 +594,6 @@ static void SeedSleep(CSHA512& hasher, RNGState& rng) static void SeedStartup(CSHA512& hasher, RNGState& rng) noexcept { -#ifdef WIN32 - RAND_screen(); -#endif - // Gather 256 bits of hardware randomness, if available SeedHardwareSlow(hasher); diff --git a/src/rest.cpp b/src/rest.cpp index 2c4d475542..228c122de3 100644 --- a/src/rest.cpp +++ b/src/rest.cpp @@ -3,7 +3,6 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include <attributes.h> #include <chain.h> #include <chainparams.h> #include <core_io.h> diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 3463145f75..fac6bcd60d 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -10,11 +10,11 @@ #include <chain.h> #include <chainparams.h> #include <coins.h> -#include <node/coinstats.h> #include <consensus/validation.h> #include <core_io.h> #include <hash.h> #include <index/blockfilterindex.h> +#include <node/coinstats.h> #include <policy/feerate.h> #include <policy/policy.h> #include <policy/rbf.h> @@ -32,10 +32,8 @@ #include <util/validation.h> #include <validation.h> #include <validationinterface.h> -#include <versionbitsinfo.h> #include <warnings.h> -#include <assert.h> #include <stdint.h> #include <univalue.h> diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index c2714f9c83..32e18312e1 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -4,7 +4,6 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <rpc/client.h> -#include <rpc/protocol.h> #include <util/system.h> #include <set> diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 1516007201..d73dd6e52d 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -3,16 +3,16 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include <crypto/ripemd160.h> -#include <key_io.h> #include <httpserver.h> +#include <key_io.h> #include <outputtype.h> #include <rpc/blockchain.h> #include <rpc/server.h> #include <rpc/util.h> #include <script/descriptor.h> -#include <util/system.h> +#include <util/check.h> #include <util/strencodings.h> +#include <util/system.h> #include <util/validation.h> #include <stdint.h> @@ -541,6 +541,7 @@ static UniValue echo(const JSONRPCRequest& request) throw std::runtime_error( RPCHelpMan{"echo|echojson ...", "\nSimply echo back the input arguments. This command is for testing.\n" + "\nIt will return an internal bug report when exactly 100 arguments are passed.\n" "\nThe difference between echo and echojson is that echojson has argument conversion enabled in the client-side table in " "bitcoin-cli and the GUI. There is no server-side difference.", {}, @@ -549,6 +550,8 @@ static UniValue echo(const JSONRPCRequest& request) }.ToString() ); + CHECK_NONFATAL(request.params.size() != 100); + return request.params; } diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index 7c4b3d0cc6..7b1507e4dc 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -11,7 +11,6 @@ #include <net_processing.h> #include <net_permissions.h> #include <netbase.h> -#include <policy/policy.h> #include <policy/settings.h> #include <rpc/protocol.h> #include <rpc/util.h> diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index f548d356cf..cdcf0c9971 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -5,7 +5,6 @@ #include <chain.h> #include <coins.h> -#include <compat/byteswap.h> #include <consensus/validation.h> #include <core_io.h> #include <index/txindex.h> @@ -23,7 +22,6 @@ #include <rpc/server.h> #include <rpc/util.h> #include <script/script.h> -#include <script/script_error.h> #include <script/sign.h> #include <script/signingprovider.h> #include <script/standard.h> @@ -610,7 +608,7 @@ static UniValue combinerawtransaction(const JSONRPCRequest& request) "\"hex\" (string) The hex-encoded raw transaction with signature(s)\n" }, RPCExamples{ - HelpExampleCli("combinerawtransaction", "[\"myhex1\", \"myhex2\", \"myhex3\"]") + HelpExampleCli("combinerawtransaction", R"('["myhex1", "myhex2", "myhex3"]')") }, }.Check(request); @@ -858,7 +856,7 @@ static UniValue testmempoolaccept(const JSONRPCRequest& request) "Sign the transaction, and get back the hex\n" + HelpExampleCli("signrawtransactionwithwallet", "\"myhex\"") + "\nTest acceptance of the transaction (signed hex)\n" - + HelpExampleCli("testmempoolaccept", "[\"signedhex\"]") + + + HelpExampleCli("testmempoolaccept", R"('["signedhex"]')") + "\nAs a JSON-RPC call\n" + HelpExampleRpc("testmempoolaccept", "[\"signedhex\"]") }, @@ -906,7 +904,7 @@ static UniValue testmempoolaccept(const JSONRPCRequest& request) result_0.pushKV("allowed", test_accept_res); if (!test_accept_res) { if (state.IsInvalid()) { - result_0.pushKV("reject-reason", strprintf("%i: %s", state.GetRejectCode(), state.GetRejectReason())); + result_0.pushKV("reject-reason", strprintf("%s", state.GetRejectReason())); } else if (missing_inputs) { result_0.pushKV("reject-reason", "missing-inputs"); } else { @@ -1226,7 +1224,7 @@ UniValue combinepsbt(const JSONRPCRequest& request) " \"psbt\" (string) The base64-encoded partially signed transaction\n" }, RPCExamples{ - HelpExampleCli("combinepsbt", "[\"mybase64_1\", \"mybase64_2\", \"mybase64_3\"]") + HelpExampleCli("combinepsbt", R"('["mybase64_1", "mybase64_2", "mybase64_3"]')") }, }.Check(request); diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 3e5bb85c1c..91d3e1fca4 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -5,8 +5,6 @@ #include <rpc/server.h> -#include <fs.h> -#include <key_io.h> #include <rpc/util.h> #include <shutdown.h> #include <sync.h> diff --git a/src/rpc/server.h b/src/rpc/server.h index b060db5bf9..be9c03bf6b 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -8,9 +8,7 @@ #include <amount.h> #include <rpc/request.h> -#include <uint256.h> -#include <list> #include <map> #include <stdint.h> #include <string> diff --git a/src/rpc/util.h b/src/rpc/util.h index 72fc7b6286..ec36956c95 100644 --- a/src/rpc/util.h +++ b/src/rpc/util.h @@ -7,14 +7,15 @@ #include <node/transaction.h> #include <outputtype.h> -#include <pubkey.h> #include <protocol.h> +#include <pubkey.h> #include <rpc/protocol.h> #include <rpc/request.h> #include <script/script.h> #include <script/sign.h> #include <script/standard.h> #include <univalue.h> +#include <util/check.h> #include <string> #include <vector> @@ -146,7 +147,7 @@ struct RPCArg { m_oneline_description{oneline_description}, m_type_str{type_str} { - assert(type != Type::ARR && type != Type::OBJ); + CHECK_NONFATAL(type != Type::ARR && type != Type::OBJ); } RPCArg( @@ -165,7 +166,7 @@ struct RPCArg { m_oneline_description{oneline_description}, m_type_str{type_str} { - assert(type == Type::ARR || type == Type::OBJ); + CHECK_NONFATAL(type == Type::ARR || type == Type::OBJ); } bool IsOptional() const; @@ -194,14 +195,14 @@ struct RPCResult { explicit RPCResult(std::string result) : m_cond{}, m_result{std::move(result)} { - assert(!m_result.empty()); + CHECK_NONFATAL(!m_result.empty()); } RPCResult(std::string cond, std::string result) : m_cond{std::move(cond)}, m_result{std::move(result)} { - assert(!m_cond.empty()); - assert(!m_result.empty()); + CHECK_NONFATAL(!m_cond.empty()); + CHECK_NONFATAL(!m_result.empty()); } }; diff --git a/src/script/descriptor.cpp b/src/script/descriptor.cpp index ed1bd4cda9..536807e1d8 100644 --- a/src/script/descriptor.cpp +++ b/src/script/descriptor.cpp @@ -14,6 +14,7 @@ #include <util/spanparsing.h> #include <util/system.h> #include <util/strencodings.h> +#include <util/vector.h> #include <memory> #include <string> @@ -501,22 +502,13 @@ public: } }; -/** Construct a vector with one element, which is moved into it. */ -template<typename T> -std::vector<T> Singleton(T elem) -{ - std::vector<T> ret; - ret.emplace_back(std::move(elem)); - return ret; -} - /** A parsed addr(A) descriptor. */ class AddressDescriptor final : public DescriptorImpl { const CTxDestination m_destination; protected: std::string ToStringExtra() const override { return EncodeDestination(m_destination); } - std::vector<CScript> MakeScripts(const std::vector<CPubKey>&, const CScript*, FlatSigningProvider&) const override { return Singleton(GetScriptForDestination(m_destination)); } + std::vector<CScript> MakeScripts(const std::vector<CPubKey>&, const CScript*, FlatSigningProvider&) const override { return Vector(GetScriptForDestination(m_destination)); } public: AddressDescriptor(CTxDestination destination) : DescriptorImpl({}, {}, "addr"), m_destination(std::move(destination)) {} bool IsSolvable() const final { return false; } @@ -528,7 +520,7 @@ class RawDescriptor final : public DescriptorImpl const CScript m_script; protected: std::string ToStringExtra() const override { return HexStr(m_script.begin(), m_script.end()); } - std::vector<CScript> MakeScripts(const std::vector<CPubKey>&, const CScript*, FlatSigningProvider&) const override { return Singleton(m_script); } + std::vector<CScript> MakeScripts(const std::vector<CPubKey>&, const CScript*, FlatSigningProvider&) const override { return Vector(m_script); } public: RawDescriptor(CScript script) : DescriptorImpl({}, {}, "raw"), m_script(std::move(script)) {} bool IsSolvable() const final { return false; } @@ -538,9 +530,9 @@ public: class PKDescriptor final : public DescriptorImpl { protected: - std::vector<CScript> MakeScripts(const std::vector<CPubKey>& keys, const CScript*, FlatSigningProvider&) const override { return Singleton(GetScriptForRawPubKey(keys[0])); } + std::vector<CScript> MakeScripts(const std::vector<CPubKey>& keys, const CScript*, FlatSigningProvider&) const override { return Vector(GetScriptForRawPubKey(keys[0])); } public: - PKDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Singleton(std::move(prov)), {}, "pk") {} + PKDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Vector(std::move(prov)), {}, "pk") {} }; /** A parsed pkh(P) descriptor. */ @@ -551,10 +543,10 @@ protected: { CKeyID id = keys[0].GetID(); out.pubkeys.emplace(id, keys[0]); - return Singleton(GetScriptForDestination(PKHash(id))); + return Vector(GetScriptForDestination(PKHash(id))); } public: - PKHDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Singleton(std::move(prov)), {}, "pkh") {} + PKHDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Vector(std::move(prov)), {}, "pkh") {} }; /** A parsed wpkh(P) descriptor. */ @@ -565,10 +557,10 @@ protected: { CKeyID id = keys[0].GetID(); out.pubkeys.emplace(id, keys[0]); - return Singleton(GetScriptForDestination(WitnessV0KeyHash(id))); + return Vector(GetScriptForDestination(WitnessV0KeyHash(id))); } public: - WPKHDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Singleton(std::move(prov)), {}, "wpkh") {} + WPKHDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Vector(std::move(prov)), {}, "wpkh") {} }; /** A parsed combo(P) descriptor. */ @@ -591,7 +583,7 @@ protected: return ret; } public: - ComboDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Singleton(std::move(prov)), {}, "combo") {} + ComboDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Vector(std::move(prov)), {}, "combo") {} }; /** A parsed multi(...) or sortedmulti(...) descriptor */ @@ -605,9 +597,9 @@ protected: if (m_sorted) { std::vector<CPubKey> sorted_keys(keys); std::sort(sorted_keys.begin(), sorted_keys.end()); - return Singleton(GetScriptForMultisig(m_threshold, sorted_keys)); + return Vector(GetScriptForMultisig(m_threshold, sorted_keys)); } - return Singleton(GetScriptForMultisig(m_threshold, keys)); + return Vector(GetScriptForMultisig(m_threshold, keys)); } public: MultisigDescriptor(int threshold, std::vector<std::unique_ptr<PubkeyProvider>> providers, bool sorted = false) : DescriptorImpl(std::move(providers), {}, sorted ? "sortedmulti" : "multi"), m_threshold(threshold), m_sorted(sorted) {} @@ -617,7 +609,7 @@ public: class SHDescriptor final : public DescriptorImpl { protected: - std::vector<CScript> MakeScripts(const std::vector<CPubKey>&, const CScript* script, FlatSigningProvider&) const override { return Singleton(GetScriptForDestination(ScriptHash(*script))); } + std::vector<CScript> MakeScripts(const std::vector<CPubKey>&, const CScript* script, FlatSigningProvider&) const override { return Vector(GetScriptForDestination(ScriptHash(*script))); } public: SHDescriptor(std::unique_ptr<DescriptorImpl> desc) : DescriptorImpl({}, std::move(desc), "sh") {} }; @@ -626,7 +618,7 @@ public: class WSHDescriptor final : public DescriptorImpl { protected: - std::vector<CScript> MakeScripts(const std::vector<CPubKey>&, const CScript* script, FlatSigningProvider&) const override { return Singleton(GetScriptForDestination(WitnessV0ScriptHash(*script))); } + std::vector<CScript> MakeScripts(const std::vector<CPubKey>&, const CScript* script, FlatSigningProvider&) const override { return Vector(GetScriptForDestination(WitnessV0ScriptHash(*script))); } public: WSHDescriptor(std::unique_ptr<DescriptorImpl> desc) : DescriptorImpl({}, std::move(desc), "wsh") {} }; diff --git a/src/script/descriptor.h b/src/script/descriptor.h index 0195ca0939..5a1b55259a 100644 --- a/src/script/descriptor.h +++ b/src/script/descriptor.h @@ -11,22 +11,24 @@ #include <vector> -// Descriptors are strings that describe a set of scriptPubKeys, together with -// all information necessary to solve them. By combining all information into -// one, they avoid the need to separately import keys and scripts. -// -// Descriptors may be ranged, which occurs when the public keys inside are -// specified in the form of HD chains (xpubs). -// -// Descriptors always represent public information - public keys and scripts - -// but in cases where private keys need to be conveyed along with a descriptor, -// they can be included inside by changing public keys to private keys (WIF -// format), and changing xpubs by xprvs. -// -// Reference documentation about the descriptor language can be found in -// doc/descriptors.md. - -/** Interface for parsed descriptor objects. */ + +/** \brief Interface for parsed descriptor objects. + * + * Descriptors are strings that describe a set of scriptPubKeys, together with + * all information necessary to solve them. By combining all information into + * one, they avoid the need to separately import keys and scripts. + * + * Descriptors may be ranged, which occurs when the public keys inside are + * specified in the form of HD chains (xpubs). + * + * Descriptors always represent public information - public keys and scripts - + * but in cases where private keys need to be conveyed along with a descriptor, + * they can be included inside by changing public keys to private keys (WIF + * format), and changing xpubs by xprvs. + * + * Reference documentation about the descriptor language can be found in + * doc/descriptors.md. + */ struct Descriptor { virtual ~Descriptor() = default; @@ -45,51 +47,51 @@ struct Descriptor { /** Expand a descriptor at a specified position. * - * pos: the position at which to expand the descriptor. If IsRange() is false, this is ignored. - * provider: the provider to query for private keys in case of hardened derivation. - * output_scripts: the expanded scriptPubKeys will be put here. - * out: scripts and public keys necessary for solving the expanded scriptPubKeys will be put here (may be equal to provider). - * cache: vector which will be overwritten with cache data necessary to evaluate the descriptor at this point without access to private keys. + * @param[in] pos: The position at which to expand the descriptor. If IsRange() is false, this is ignored. + * @param[in] provider: The provider to query for private keys in case of hardened derivation. + * @param[out] output_scripts: The expanded scriptPubKeys. + * @param[out] out: Scripts and public keys necessary for solving the expanded scriptPubKeys (may be equal to `provider`). + * @param[out] cache: Cache data necessary to evaluate the descriptor at this point without access to private keys. */ virtual bool Expand(int pos, const SigningProvider& provider, std::vector<CScript>& output_scripts, FlatSigningProvider& out, std::vector<unsigned char>* cache = nullptr) const = 0; /** Expand a descriptor at a specified position using cached expansion data. * - * pos: the position at which to expand the descriptor. If IsRange() is false, this is ignored. - * cache: vector from which cached expansion data will be read. - * output_scripts: the expanded scriptPubKeys will be put here. - * out: scripts and public keys necessary for solving the expanded scriptPubKeys will be put here (may be equal to provider). + * @param[in] pos: The position at which to expand the descriptor. If IsRange() is false, this is ignored. + * @param[in] cache: Cached expansion data. + * @param[out] output_scripts: The expanded scriptPubKeys. + * @param[out] out: Scripts and public keys necessary for solving the expanded scriptPubKeys (may be equal to `provider`). */ virtual bool ExpandFromCache(int pos, const std::vector<unsigned char>& cache, std::vector<CScript>& output_scripts, FlatSigningProvider& out) const = 0; /** Expand the private key for a descriptor at a specified position, if possible. * - * pos: the position at which to expand the descriptor. If IsRange() is false, this is ignored. - * provider: the provider to query for the private keys. - * out: any private keys available for the specified pos will be placed here. + * @param[in] pos: The position at which to expand the descriptor. If IsRange() is false, this is ignored. + * @param[in] provider: The provider to query for the private keys. + * @param[out] out: Any private keys available for the specified `pos`. */ virtual void ExpandPrivate(int pos, const SigningProvider& provider, FlatSigningProvider& out) const = 0; }; -/** Parse a descriptor string. Included private keys are put in out. +/** Parse a `descriptor` string. Included private keys are put in `out`. * - * If the descriptor has a checksum, it must be valid. If require_checksum + * If the descriptor has a checksum, it must be valid. If `require_checksum` * is set, the checksum is mandatory - otherwise it is optional. * * If a parse error occurs, or the checksum is missing/invalid, or anything - * else is wrong, nullptr is returned. + * else is wrong, `nullptr` is returned. */ std::unique_ptr<Descriptor> Parse(const std::string& descriptor, FlatSigningProvider& out, std::string& error, bool require_checksum = false); -/** Get the checksum for a descriptor. +/** Get the checksum for a `descriptor`. * - * If it already has one, and it is correct, return the checksum in the input. - * If it already has one that is wrong, return "". - * If it does not already have one, return the checksum that would need to be added. + * - If it already has one, and it is correct, return the checksum in the input. + * - If it already has one that is wrong, return "". + * - If it does not already have one, return the checksum that would need to be added. */ std::string GetDescriptorChecksum(const std::string& descriptor); -/** Find a descriptor for the specified script, using information from provider where possible. +/** Find a descriptor for the specified `script`, using information from `provider` where possible. * * A non-ranged descriptor which only generates the specified script will be returned in all * circumstances. @@ -98,9 +100,9 @@ std::string GetDescriptorChecksum(const std::string& descriptor); * descriptor. * * - If all information for solving `script` is present in `provider`, a descriptor will be returned - * which is `IsSolvable()` and encapsulates said information. + * which is IsSolvable() and encapsulates said information. * - Failing that, if `script` corresponds to a known address type, an "addr()" descriptor will be - * returned (which is not `IsSolvable()`). + * returned (which is not IsSolvable()). * - Failing that, a "raw()" descriptor is returned. */ std::unique_ptr<Descriptor> InferDescriptor(const CScript& script, const SigningProvider& provider); diff --git a/src/script/interpreter.h b/src/script/interpreter.h index 276ff9a58a..d63d8b85b7 100644 --- a/src/script/interpreter.h +++ b/src/script/interpreter.h @@ -11,7 +11,6 @@ #include <vector> #include <stdint.h> -#include <string> class CPubKey; class CScript; diff --git a/src/script/keyorigin.h b/src/script/keyorigin.h index 610f233500..467605ce46 100644 --- a/src/script/keyorigin.h +++ b/src/script/keyorigin.h @@ -6,7 +6,6 @@ #define BITCOIN_SCRIPT_KEYORIGIN_H #include <serialize.h> -#include <streams.h> #include <vector> struct KeyOriginInfo diff --git a/src/script/sign.h b/src/script/sign.h index 0e751afd3b..9d0a5b4d70 100644 --- a/src/script/sign.h +++ b/src/script/sign.h @@ -6,7 +6,6 @@ #ifndef BITCOIN_SCRIPT_SIGN_H #define BITCOIN_SCRIPT_SIGN_H -#include <boost/optional.hpp> #include <hash.h> #include <pubkey.h> #include <script/interpreter.h> diff --git a/src/script/standard.h b/src/script/standard.h index e45e2d92cc..6db28dbc2d 100644 --- a/src/script/standard.h +++ b/src/script/standard.h @@ -11,7 +11,6 @@ #include <boost/variant.hpp> -#include <stdint.h> static const bool DEFAULT_ACCEPT_DATACARRIER = true; diff --git a/src/serialize.h b/src/serialize.h index a38d76fc18..ef270dbbe3 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -9,7 +9,6 @@ #include <compat/endian.h> #include <algorithm> -#include <assert.h> #include <ios> #include <limits> #include <map> diff --git a/src/streams.h b/src/streams.h index 517eefc932..b598dc1aeb 100644 --- a/src/streams.h +++ b/src/streams.h @@ -13,8 +13,6 @@ #include <assert.h> #include <ios> #include <limits> -#include <map> -#include <set> #include <stdint.h> #include <stdio.h> #include <string> diff --git a/src/sync.cpp b/src/sync.cpp index 20258d8e9a..653800ae4e 100644 --- a/src/sync.cpp +++ b/src/sync.cpp @@ -13,10 +13,8 @@ #include <util/strencodings.h> #include <util/threadnames.h> -#include <stdio.h> #include <map> -#include <memory> #include <set> #ifdef DEBUG_LOCKCONTENTION diff --git a/src/test/bip32_tests.cpp b/src/test/bip32_tests.cpp index 662878750e..e46cf624cf 100644 --- a/src/test/bip32_tests.cpp +++ b/src/test/bip32_tests.cpp @@ -8,7 +8,6 @@ #include <key.h> #include <key_io.h> #include <streams.h> -#include <util/system.h> #include <util/strencodings.h> #include <test/setup_common.h> @@ -119,22 +118,6 @@ static void RunTest(const TestVector &test) { } key = keyNew; pubkey = pubkeyNew; - - CDataStream ssPub(SER_DISK, CLIENT_VERSION); - ssPub << pubkeyNew; - BOOST_CHECK(ssPub.size() == 75); - - CDataStream ssPriv(SER_DISK, CLIENT_VERSION); - ssPriv << keyNew; - BOOST_CHECK(ssPriv.size() == 75); - - CExtPubKey pubCheck; - CExtKey privCheck; - ssPub >> pubCheck; - ssPriv >> privCheck; - - BOOST_CHECK(pubCheck == pubkeyNew); - BOOST_CHECK(privCheck == keyNew); } } diff --git a/src/test/blockfilter_index_tests.cpp b/src/test/blockfilter_index_tests.cpp index cf87aa9303..ba293b7836 100644 --- a/src/test/blockfilter_index_tests.cpp +++ b/src/test/blockfilter_index_tests.cpp @@ -167,17 +167,23 @@ BOOST_FIXTURE_TEST_CASE(blockfilter_index_initial_sync, TestChain100Setup) LOCK(cs_main); tip = ::ChainActive().Tip(); } - CScript coinbase_script_pub_key = GetScriptForDestination(PKHash(coinbaseKey.GetPubKey())); + CKey coinbase_key_A, coinbase_key_B; + coinbase_key_A.MakeNewKey(true); + coinbase_key_B.MakeNewKey(true); + CScript coinbase_script_pub_key_A = GetScriptForDestination(PKHash(coinbase_key_A.GetPubKey())); + CScript coinbase_script_pub_key_B = GetScriptForDestination(PKHash(coinbase_key_B.GetPubKey())); std::vector<std::shared_ptr<CBlock>> chainA, chainB; - BOOST_REQUIRE(BuildChain(tip, coinbase_script_pub_key, 10, chainA)); - BOOST_REQUIRE(BuildChain(tip, coinbase_script_pub_key, 10, chainB)); + BOOST_REQUIRE(BuildChain(tip, coinbase_script_pub_key_A, 10, chainA)); + BOOST_REQUIRE(BuildChain(tip, coinbase_script_pub_key_B, 10, chainB)); // Check that new blocks on chain A get indexed. uint256 chainA_last_header = last_header; for (size_t i = 0; i < 2; i++) { const auto& block = chainA[i]; BOOST_REQUIRE(ProcessNewBlock(Params(), block, true, nullptr)); - + } + for (size_t i = 0; i < 2; i++) { + const auto& block = chainA[i]; const CBlockIndex* block_index; { LOCK(cs_main); @@ -193,7 +199,9 @@ BOOST_FIXTURE_TEST_CASE(blockfilter_index_initial_sync, TestChain100Setup) for (size_t i = 0; i < 3; i++) { const auto& block = chainB[i]; BOOST_REQUIRE(ProcessNewBlock(Params(), block, true, nullptr)); - + } + for (size_t i = 0; i < 3; i++) { + const auto& block = chainB[i]; const CBlockIndex* block_index; { LOCK(cs_main); @@ -221,7 +229,7 @@ BOOST_FIXTURE_TEST_CASE(blockfilter_index_initial_sync, TestChain100Setup) // Reorg back to chain A. for (size_t i = 2; i < 4; i++) { const auto& block = chainA[i]; - BOOST_REQUIRE(ProcessNewBlock(Params(), block, true, nullptr)); + BOOST_REQUIRE(ProcessNewBlock(Params(), block, true, nullptr)); } // Check that chain A and B blocks can be retrieved. diff --git a/src/test/compress_tests.cpp b/src/test/compress_tests.cpp index 6cef8cd8a8..c6a08b293f 100644 --- a/src/test/compress_tests.cpp +++ b/src/test/compress_tests.cpp @@ -3,8 +3,8 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <compressor.h> -#include <util/system.h> #include <test/setup_common.h> +#include <script/standard.h> #include <stdint.h> @@ -62,4 +62,76 @@ BOOST_AUTO_TEST_CASE(compress_amounts) BOOST_CHECK(TestDecode(i)); } +BOOST_AUTO_TEST_CASE(compress_script_to_ckey_id) +{ + // case CKeyID + CKey key; + key.MakeNewKey(true); + CPubKey pubkey = key.GetPubKey(); + + CScript script = CScript() << OP_DUP << OP_HASH160 << ToByteVector(pubkey.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG; + BOOST_CHECK_EQUAL(script.size(), 25); + + std::vector<unsigned char> out; + bool done = CompressScript(script, out); + BOOST_CHECK_EQUAL(done, true); + + // Check compressed script + BOOST_CHECK_EQUAL(out.size(), 21); + BOOST_CHECK_EQUAL(out[0], 0x00); + BOOST_CHECK_EQUAL(memcmp(&out[1], &script[3], 20), 0); // compare the 20 relevant chars of the CKeyId in the script +} + +BOOST_AUTO_TEST_CASE(compress_script_to_cscript_id) +{ + // case CScriptID + CScript script, redeemScript; + script << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL; + BOOST_CHECK_EQUAL(script.size(), 23); + + std::vector<unsigned char> out; + bool done = CompressScript(script, out); + BOOST_CHECK_EQUAL(done, true); + + // Check compressed script + BOOST_CHECK_EQUAL(out.size(), 21); + BOOST_CHECK_EQUAL(out[0], 0x01); + BOOST_CHECK_EQUAL(memcmp(&out[1], &script[2], 20), 0); // compare the 20 relevant chars of the CScriptId in the script +} + +BOOST_AUTO_TEST_CASE(compress_script_to_compressed_pubkey_id) +{ + CKey key; + key.MakeNewKey(true); // case compressed PubKeyID + + CScript script = CScript() << ToByteVector(key.GetPubKey()) << OP_CHECKSIG; // COMPRESSED_PUBLIC_KEY_SIZE (33) + BOOST_CHECK_EQUAL(script.size(), 35); + + std::vector<unsigned char> out; + bool done = CompressScript(script, out); + BOOST_CHECK_EQUAL(done, true); + + // Check compressed script + BOOST_CHECK_EQUAL(out.size(), 33); + BOOST_CHECK_EQUAL(memcmp(&out[0], &script[1], 1), 0); + BOOST_CHECK_EQUAL(memcmp(&out[1], &script[2], 32), 0); // compare the 32 chars of the compressed CPubKey +} + +BOOST_AUTO_TEST_CASE(compress_script_to_uncompressed_pubkey_id) +{ + CKey key; + key.MakeNewKey(false); // case uncompressed PubKeyID + CScript script = CScript() << ToByteVector(key.GetPubKey()) << OP_CHECKSIG; // PUBLIC_KEY_SIZE (65) + BOOST_CHECK_EQUAL(script.size(), 67); // 1 char code + 65 char pubkey + OP_CHECKSIG + + std::vector<unsigned char> out; + bool done = CompressScript(script, out); + BOOST_CHECK_EQUAL(done, true); + + // Check compressed script + BOOST_CHECK_EQUAL(out.size(), 33); + BOOST_CHECK_EQUAL(memcmp(&out[1], &script[2], 32), 0); // first 32 chars of CPubKey are copied into out[1:] + BOOST_CHECK_EQUAL(out[0], 0x04 | (script[65] & 0x01)); // least significant bit (lsb) of last char of pubkey is mapped into out[0] +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/dbwrapper_tests.cpp b/src/test/dbwrapper_tests.cpp index efcadd51fc..2ffe4dccdb 100644 --- a/src/test/dbwrapper_tests.cpp +++ b/src/test/dbwrapper_tests.cpp @@ -42,6 +42,86 @@ BOOST_AUTO_TEST_CASE(dbwrapper) } } +BOOST_AUTO_TEST_CASE(dbwrapper_basic_data) +{ + // Perform tests both obfuscated and non-obfuscated. + for (bool obfuscate : {false, true}) { + fs::path ph = GetDataDir() / (obfuscate ? "dbwrapper_1_obfuscate_true" : "dbwrapper_1_obfuscate_false"); + CDBWrapper dbw(ph, (1 << 20), false, true, obfuscate); + + uint256 res; + uint32_t res_uint_32; + bool res_bool; + + // Ensure that we're doing real obfuscation when obfuscate=true + BOOST_CHECK(obfuscate != is_null_key(dbwrapper_private::GetObfuscateKey(dbw))); + + //Simulate block raw data - "b + block hash" + std::string key_block = "b" + InsecureRand256().ToString(); + + uint256 in_block = InsecureRand256(); + BOOST_CHECK(dbw.Write(key_block, in_block)); + BOOST_CHECK(dbw.Read(key_block, res)); + BOOST_CHECK_EQUAL(res.ToString(), in_block.ToString()); + + //Simulate file raw data - "f + file_number" + std::string key_file = strprintf("f%04x", InsecureRand32()); + + uint256 in_file_info = InsecureRand256(); + BOOST_CHECK(dbw.Write(key_file, in_file_info)); + BOOST_CHECK(dbw.Read(key_file, res)); + BOOST_CHECK_EQUAL(res.ToString(), in_file_info.ToString()); + + //Simulate transaction raw data - "t + transaction hash" + std::string key_transaction = "t" + InsecureRand256().ToString(); + + uint256 in_transaction = InsecureRand256(); + BOOST_CHECK(dbw.Write(key_transaction, in_transaction)); + BOOST_CHECK(dbw.Read(key_transaction, res)); + BOOST_CHECK_EQUAL(res.ToString(), in_transaction.ToString()); + + //Simulate UTXO raw data - "c + transaction hash" + std::string key_utxo = "c" + InsecureRand256().ToString(); + + uint256 in_utxo = InsecureRand256(); + BOOST_CHECK(dbw.Write(key_utxo, in_utxo)); + BOOST_CHECK(dbw.Read(key_utxo, res)); + BOOST_CHECK_EQUAL(res.ToString(), in_utxo.ToString()); + + //Simulate last block file number - "l" + char key_last_blockfile_number = 'l'; + uint32_t lastblockfilenumber = InsecureRand32(); + BOOST_CHECK(dbw.Write(key_last_blockfile_number, lastblockfilenumber)); + BOOST_CHECK(dbw.Read(key_last_blockfile_number, res_uint_32)); + BOOST_CHECK_EQUAL(lastblockfilenumber, res_uint_32); + + //Simulate Is Reindexing - "R" + char key_IsReindexing = 'R'; + bool isInReindexing = InsecureRandBool(); + BOOST_CHECK(dbw.Write(key_IsReindexing, isInReindexing)); + BOOST_CHECK(dbw.Read(key_IsReindexing, res_bool)); + BOOST_CHECK_EQUAL(isInReindexing, res_bool); + + //Simulate last block hash up to which UXTO covers - 'B' + char key_lastblockhash_uxto = 'B'; + uint256 lastblock_hash = InsecureRand256(); + BOOST_CHECK(dbw.Write(key_lastblockhash_uxto, lastblock_hash)); + BOOST_CHECK(dbw.Read(key_lastblockhash_uxto, res)); + BOOST_CHECK_EQUAL(lastblock_hash, res); + + //Simulate file raw data - "F + filename_number + filename" + std::string file_option_tag = "F"; + uint8_t filename_length = InsecureRandBits(8); + std::string filename = "randomfilename"; + std::string key_file_option = strprintf("%s%01x%s", file_option_tag,filename_length,filename); + + bool in_file_bool = InsecureRandBool(); + BOOST_CHECK(dbw.Write(key_file_option, in_file_bool)); + BOOST_CHECK(dbw.Read(key_file_option, res_bool)); + BOOST_CHECK_EQUAL(res_bool, in_file_bool); + } +} + // Test batch operations BOOST_AUTO_TEST_CASE(dbwrapper_batch) { diff --git a/src/test/fs_tests.cpp b/src/test/fs_tests.cpp index 6d5a6641f0..b504a3cbb1 100644 --- a/src/test/fs_tests.cpp +++ b/src/test/fs_tests.cpp @@ -15,7 +15,7 @@ BOOST_AUTO_TEST_CASE(fsbridge_fstream) fs::path tmpfolder = GetDataDir(); // tmpfile1 should be the same as tmpfile2 fs::path tmpfile1 = tmpfolder / "fs_tests_₿_🏃"; - fs::path tmpfile2 = tmpfolder / L"fs_tests_₿_🏃"; + fs::path tmpfile2 = tmpfolder / "fs_tests_₿_🏃"; { fsbridge::ofstream file(tmpfile1); file << "bitcoin"; diff --git a/src/test/fuzz/FuzzedDataProvider.h b/src/test/fuzz/FuzzedDataProvider.h new file mode 100644 index 0000000000..1b5b4bb012 --- /dev/null +++ b/src/test/fuzz/FuzzedDataProvider.h @@ -0,0 +1,245 @@ +//===- FuzzedDataProvider.h - Utility header for fuzz targets ---*- C++ -* ===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// A single header library providing an utility class to break up an array of +// bytes. Whenever run on the same input, provides the same output, as long as +// its methods are called in the same order, with the same arguments. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FUZZER_FUZZED_DATA_PROVIDER_H_ +#define LLVM_FUZZER_FUZZED_DATA_PROVIDER_H_ + +#include <limits.h> +#include <stddef.h> +#include <stdint.h> + +#include <algorithm> +#include <cstring> +#include <initializer_list> +#include <string> +#include <type_traits> +#include <utility> +#include <vector> + +class FuzzedDataProvider { +public: + // |data| is an array of length |size| that the FuzzedDataProvider wraps to + // provide more granular access. |data| must outlive the FuzzedDataProvider. + FuzzedDataProvider(const uint8_t *data, size_t size) + : data_ptr_(data), remaining_bytes_(size) {} + ~FuzzedDataProvider() = default; + + // Returns a std::vector containing |num_bytes| of input data. If fewer than + // |num_bytes| of data remain, returns a shorter std::vector containing all + // of the data that's left. Can be used with any byte sized type, such as + // char, unsigned char, uint8_t, etc. + template <typename T> std::vector<T> ConsumeBytes(size_t num_bytes) { + num_bytes = std::min(num_bytes, remaining_bytes_); + return ConsumeBytes<T>(num_bytes, num_bytes); + } + + // Similar to |ConsumeBytes|, but also appends the terminator value at the end + // of the resulting vector. Useful, when a mutable null-terminated C-string is + // needed, for example. But that is a rare case. Better avoid it, if possible, + // and prefer using |ConsumeBytes| or |ConsumeBytesAsString| methods. + template <typename T> + std::vector<T> ConsumeBytesWithTerminator(size_t num_bytes, + T terminator = 0) { + num_bytes = std::min(num_bytes, remaining_bytes_); + std::vector<T> result = ConsumeBytes<T>(num_bytes + 1, num_bytes); + result.back() = terminator; + return result; + } + + // Returns a std::string containing |num_bytes| of input data. Using this and + // |.c_str()| on the resulting string is the best way to get an immutable + // null-terminated C string. If fewer than |num_bytes| of data remain, returns + // a shorter std::string containing all of the data that's left. + std::string ConsumeBytesAsString(size_t num_bytes) { + static_assert(sizeof(std::string::value_type) == sizeof(uint8_t), + "ConsumeBytesAsString cannot convert the data to a string."); + + num_bytes = std::min(num_bytes, remaining_bytes_); + std::string result( + reinterpret_cast<const std::string::value_type *>(data_ptr_), + num_bytes); + Advance(num_bytes); + return result; + } + + // Returns a number in the range [min, max] by consuming bytes from the + // input data. The value might not be uniformly distributed in the given + // range. If there's no input data left, always returns |min|. |min| must + // be less than or equal to |max|. + template <typename T> T ConsumeIntegralInRange(T min, T max) { + static_assert(std::is_integral<T>::value, "An integral type is required."); + static_assert(sizeof(T) <= sizeof(uint64_t), "Unsupported integral type."); + + if (min > max) + abort(); + + // Use the biggest type possible to hold the range and the result. + uint64_t range = static_cast<uint64_t>(max) - min; + uint64_t result = 0; + size_t offset = 0; + + while (offset < sizeof(T) * CHAR_BIT && (range >> offset) > 0 && + remaining_bytes_ != 0) { + // Pull bytes off the end of the seed data. Experimentally, this seems to + // allow the fuzzer to more easily explore the input space. This makes + // sense, since it works by modifying inputs that caused new code to run, + // and this data is often used to encode length of data read by + // |ConsumeBytes|. Separating out read lengths makes it easier modify the + // contents of the data that is actually read. + --remaining_bytes_; + result = (result << CHAR_BIT) | data_ptr_[remaining_bytes_]; + offset += CHAR_BIT; + } + + // Avoid division by 0, in case |range + 1| results in overflow. + if (range != std::numeric_limits<decltype(range)>::max()) + result = result % (range + 1); + + return static_cast<T>(min + result); + } + + // Returns a std::string of length from 0 to |max_length|. When it runs out of + // input data, returns what remains of the input. Designed to be more stable + // with respect to a fuzzer inserting characters than just picking a random + // length and then consuming that many bytes with |ConsumeBytes|. + std::string ConsumeRandomLengthString(size_t max_length) { + // Reads bytes from the start of |data_ptr_|. Maps "\\" to "\", and maps "\" + // followed by anything else to the end of the string. As a result of this + // logic, a fuzzer can insert characters into the string, and the string + // will be lengthened to include those new characters, resulting in a more + // stable fuzzer than picking the length of a string independently from + // picking its contents. + std::string result; + + // Reserve the anticipated capaticity to prevent several reallocations. + result.reserve(std::min(max_length, remaining_bytes_)); + for (size_t i = 0; i < max_length && remaining_bytes_ != 0; ++i) { + char next = ConvertUnsignedToSigned<char>(data_ptr_[0]); + Advance(1); + if (next == '\\' && remaining_bytes_ != 0) { + next = ConvertUnsignedToSigned<char>(data_ptr_[0]); + Advance(1); + if (next != '\\') + break; + } + result += next; + } + + result.shrink_to_fit(); + return result; + } + + // Returns a std::vector containing all remaining bytes of the input data. + template <typename T> std::vector<T> ConsumeRemainingBytes() { + return ConsumeBytes<T>(remaining_bytes_); + } + + // Prefer using |ConsumeRemainingBytes| unless you actually need a std::string + // object. + // Returns a std::vector containing all remaining bytes of the input data. + std::string ConsumeRemainingBytesAsString() { + return ConsumeBytesAsString(remaining_bytes_); + } + + // Returns a number in the range [Type's min, Type's max]. The value might + // not be uniformly distributed in the given range. If there's no input data + // left, always returns |min|. + template <typename T> T ConsumeIntegral() { + return ConsumeIntegralInRange(std::numeric_limits<T>::min(), + std::numeric_limits<T>::max()); + } + + // Reads one byte and returns a bool, or false when no data remains. + bool ConsumeBool() { return 1 & ConsumeIntegral<uint8_t>(); } + + // Returns a copy of a value selected from a fixed-size |array|. + template <typename T, size_t size> + T PickValueInArray(const T (&array)[size]) { + static_assert(size > 0, "The array must be non empty."); + return array[ConsumeIntegralInRange<size_t>(0, size - 1)]; + } + + template <typename T> + T PickValueInArray(std::initializer_list<const T> list) { + // static_assert(list.size() > 0, "The array must be non empty."); + return *(list.begin() + ConsumeIntegralInRange<size_t>(0, list.size() - 1)); + } + + // Return an enum value. The enum must start at 0 and be contiguous. It must + // also contain |kMaxValue| aliased to its largest (inclusive) value. Such as: + // enum class Foo { SomeValue, OtherValue, kMaxValue = OtherValue }; + template <typename T> T ConsumeEnum() { + static_assert(std::is_enum<T>::value, "|T| must be an enum type."); + return static_cast<T>(ConsumeIntegralInRange<uint32_t>( + 0, static_cast<uint32_t>(T::kMaxValue))); + } + + // Reports the remaining bytes available for fuzzed input. + size_t remaining_bytes() { return remaining_bytes_; } + +private: + FuzzedDataProvider(const FuzzedDataProvider &) = delete; + FuzzedDataProvider &operator=(const FuzzedDataProvider &) = delete; + + void Advance(size_t num_bytes) { + if (num_bytes > remaining_bytes_) + abort(); + + data_ptr_ += num_bytes; + remaining_bytes_ -= num_bytes; + } + + template <typename T> + std::vector<T> ConsumeBytes(size_t size, size_t num_bytes_to_consume) { + static_assert(sizeof(T) == sizeof(uint8_t), "Incompatible data type."); + + // The point of using the size-based constructor below is to increase the + // odds of having a vector object with capacity being equal to the length. + // That part is always implementation specific, but at least both libc++ and + // libstdc++ allocate the requested number of bytes in that constructor, + // which seems to be a natural choice for other implementations as well. + // To increase the odds even more, we also call |shrink_to_fit| below. + std::vector<T> result(size); + std::memcpy(result.data(), data_ptr_, num_bytes_to_consume); + Advance(num_bytes_to_consume); + + // Even though |shrink_to_fit| is also implementation specific, we expect it + // to provide an additional assurance in case vector's constructor allocated + // a buffer which is larger than the actual amount of data we put inside it. + result.shrink_to_fit(); + return result; + } + + template <typename TS, typename TU> TS ConvertUnsignedToSigned(TU value) { + static_assert(sizeof(TS) == sizeof(TU), "Incompatible data types."); + static_assert(!std::numeric_limits<TU>::is_signed, + "Source type must be unsigned."); + + // TODO(Dor1s): change to `if constexpr` once C++17 becomes mainstream. + if (std::numeric_limits<TS>::is_modulo) + return static_cast<TS>(value); + + // Avoid using implementation-defined unsigned to signer conversions. + // To learn more, see https://stackoverflow.com/questions/13150449. + if (value <= std::numeric_limits<TS>::max()) + return static_cast<TS>(value); + else { + constexpr auto TS_min = std::numeric_limits<TS>::min(); + return TS_min + static_cast<char>(value - TS_min); + } + } + + const uint8_t *data_ptr_; + size_t remaining_bytes_; +}; + +#endif // LLVM_FUZZER_FUZZED_DATA_PROVIDER_H_ diff --git a/src/test/fuzz/descriptor_parse.cpp b/src/test/fuzz/descriptor_parse.cpp new file mode 100644 index 0000000000..c4c25854fd --- /dev/null +++ b/src/test/fuzz/descriptor_parse.cpp @@ -0,0 +1,22 @@ +// Copyright (c) 2009-2019 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include <chainparams.h> +#include <script/descriptor.h> +#include <test/fuzz/fuzz.h> + +void initialize() +{ + SelectParams(CBaseChainParams::REGTEST); +} + +void test_one_input(const std::vector<uint8_t>& buffer) +{ + const std::string descriptor(buffer.begin(), buffer.end()); + FlatSigningProvider signing_provider; + std::string error; + for (const bool require_checksum : {true, false}) { + Parse(descriptor, signing_provider, error, require_checksum); + } +} diff --git a/src/test/fuzz/deserialize.cpp b/src/test/fuzz/deserialize.cpp index 3a6876ad39..bcd8691359 100644 --- a/src/test/fuzz/deserialize.cpp +++ b/src/test/fuzz/deserialize.cpp @@ -12,6 +12,7 @@ #include <net.h> #include <primitives/block.h> #include <protocol.h> +#include <pubkey.h> #include <streams.h> #include <undo.h> #include <version.h> @@ -23,6 +24,12 @@ #include <test/fuzz/fuzz.h> +void initialize() +{ + // Fuzzers using pubkey must hold an ECCVerifyHandle. + static const auto verify_handle = MakeUnique<ECCVerifyHandle>(); +} + void test_one_input(const std::vector<uint8_t>& buffer) { CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION); diff --git a/src/test/fuzz/eval_script.cpp b/src/test/fuzz/eval_script.cpp new file mode 100644 index 0000000000..9444cd489e --- /dev/null +++ b/src/test/fuzz/eval_script.cpp @@ -0,0 +1,30 @@ +// Copyright (c) 2009-2019 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include <script/interpreter.h> +#include <test/fuzz/FuzzedDataProvider.h> +#include <test/fuzz/fuzz.h> + +#include <limits> + +void test_one_input(const std::vector<uint8_t>& buffer) +{ + FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); + const unsigned int flags = fuzzed_data_provider.ConsumeIntegral<unsigned int>(); + const std::vector<uint8_t> script_bytes = [&] { + if (fuzzed_data_provider.remaining_bytes() != 0) { + return fuzzed_data_provider.ConsumeRemainingBytes<uint8_t>(); + } else { + // Avoid UBSan warning: + // test/fuzz/FuzzedDataProvider.h:212:17: runtime error: null pointer passed as argument 1, which is declared to never be null + // /usr/include/string.h:43:28: note: nonnull attribute specified here + return std::vector<uint8_t>(); + } + }(); + const CScript script(script_bytes.begin(), script_bytes.end()); + for (const auto sig_version : {SigVersion::BASE, SigVersion::WITNESS_V0}) { + std::vector<std::vector<unsigned char>> stack; + (void)EvalScript(stack, script, flags, BaseSignatureChecker(), sig_version, nullptr); + } +} diff --git a/src/test/fuzz/fuzz.cpp b/src/test/fuzz/fuzz.cpp index cfa160dde2..da4e623e98 100644 --- a/src/test/fuzz/fuzz.cpp +++ b/src/test/fuzz/fuzz.cpp @@ -4,11 +4,9 @@ #include <test/fuzz/fuzz.h> +#include <cstdint> #include <unistd.h> - -#include <pubkey.h> -#include <util/memory.h> - +#include <vector> static bool read_stdin(std::vector<uint8_t>& data) { @@ -22,9 +20,9 @@ static bool read_stdin(std::vector<uint8_t>& data) return length == 0; } -static void initialize() +// Default initialization: Override using a non-weak initialize(). +__attribute__((weak)) void initialize() { - const static auto verify_handle = MakeUnique<ECCVerifyHandle>(); } // This function is used by libFuzzer @@ -42,13 +40,9 @@ extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) return 0; } -// Disabled under WIN32 due to clash with Cygwin's WinMain. -#ifndef WIN32 // Declare main(...) "weak" to allow for libFuzzer linking. libFuzzer provides // the main(...) function. -__attribute__((weak)) -#endif -int main(int argc, char **argv) +__attribute__((weak)) int main(int argc, char** argv) { initialize(); #ifdef __AFL_INIT diff --git a/src/test/fuzz/fuzz.h b/src/test/fuzz/fuzz.h index 573bd572db..3be202b16e 100644 --- a/src/test/fuzz/fuzz.h +++ b/src/test/fuzz/fuzz.h @@ -8,7 +8,7 @@ #include <stdint.h> #include <vector> - +void initialize(); void test_one_input(const std::vector<uint8_t>& buffer); #endif // BITCOIN_TEST_FUZZ_FUZZ_H diff --git a/src/test/fuzz/script.cpp b/src/test/fuzz/script.cpp new file mode 100644 index 0000000000..0469e87de6 --- /dev/null +++ b/src/test/fuzz/script.cpp @@ -0,0 +1,64 @@ +// Copyright (c) 2019 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include <chainparams.h> +#include <compressor.h> +#include <core_io.h> +#include <core_memusage.h> +#include <policy/policy.h> +#include <pubkey.h> +#include <script/descriptor.h> +#include <script/script.h> +#include <script/sign.h> +#include <script/signingprovider.h> +#include <script/standard.h> +#include <streams.h> +#include <test/fuzz/fuzz.h> +#include <util/memory.h> + +void initialize() +{ + // Fuzzers using pubkey must hold an ECCVerifyHandle. + static const auto verify_handle = MakeUnique<ECCVerifyHandle>(); +} + +void test_one_input(const std::vector<uint8_t>& buffer) +{ + const CScript script(buffer.begin(), buffer.end()); + + std::vector<unsigned char> compressed; + (void)CompressScript(script, compressed); + + CTxDestination address; + (void)ExtractDestination(script, address); + + txnouttype type_ret; + std::vector<CTxDestination> addresses; + int required_ret; + (void)ExtractDestinations(script, type_ret, addresses, required_ret); + + (void)GetScriptForWitness(script); + + const FlatSigningProvider signing_provider; + (void)InferDescriptor(script, signing_provider); + + (void)IsSegWitOutput(signing_provider, script); + + (void)IsSolvable(signing_provider, script); + + txnouttype which_type; + (void)IsStandard(script, which_type); + + (void)RecursiveDynamicUsage(script); + + std::vector<std::vector<unsigned char>> solutions; + (void)Solver(script, solutions); + + (void)script.HasValidOps(); + (void)script.IsPayToScriptHash(); + (void)script.IsPayToWitnessScriptHash(); + (void)script.IsPushOnly(); + (void)script.IsUnspendable(); + (void)script.GetSigOpCount(/* fAccurate= */ false); +} diff --git a/src/test/fuzz/spanparsing.cpp b/src/test/fuzz/spanparsing.cpp new file mode 100644 index 0000000000..8e5e7dad11 --- /dev/null +++ b/src/test/fuzz/spanparsing.cpp @@ -0,0 +1,30 @@ +// Copyright (c) 2019 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include <test/fuzz/FuzzedDataProvider.h> +#include <test/fuzz/fuzz.h> +#include <util/spanparsing.h> + +void test_one_input(const std::vector<uint8_t>& buffer) +{ + FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); + const size_t query_size = fuzzed_data_provider.ConsumeIntegral<size_t>(); + const std::string query = fuzzed_data_provider.ConsumeBytesAsString(std::min<size_t>(query_size, 1024 * 1024)); + const std::string span_str = fuzzed_data_provider.ConsumeRemainingBytesAsString(); + const Span<const char> const_span = MakeSpan(span_str); + + Span<const char> mut_span = const_span; + (void)spanparsing::Const(query, mut_span); + + mut_span = const_span; + (void)spanparsing::Func(query, mut_span); + + mut_span = const_span; + (void)spanparsing::Expr(mut_span); + + if (!query.empty()) { + mut_span = const_span; + (void)spanparsing::Split(mut_span, query.front()); + } +} diff --git a/src/test/fuzz/transaction.cpp b/src/test/fuzz/transaction.cpp index 96d7947b07..383d879040 100644 --- a/src/test/fuzz/transaction.cpp +++ b/src/test/fuzz/transaction.cpp @@ -43,12 +43,7 @@ void test_one_input(const std::vector<uint8_t>& buffer) } CValidationState state_with_dupe_check; - const bool valid_with_dupe_check = CheckTransaction(tx, state_with_dupe_check, /* fCheckDuplicateInputs= */ true); - CValidationState state_without_dupe_check; - const bool valid_without_dupe_check = CheckTransaction(tx, state_without_dupe_check, /* fCheckDuplicateInputs= */ false); - if (valid_with_dupe_check) { - assert(valid_without_dupe_check); - } + (void)CheckTransaction(tx, state_with_dupe_check); const CFeeRate dust_relay_fee{DUST_RELAY_TX_FEE}; std::string reason; diff --git a/src/test/key_properties.cpp b/src/test/key_properties.cpp index abcfc4547b..95587130fc 100644 --- a/src/test/key_properties.cpp +++ b/src/test/key_properties.cpp @@ -4,7 +4,6 @@ #include <key.h> #include <uint256.h> -#include <util/system.h> #include <test/setup_common.h> #include <vector> diff --git a/src/test/lib/transaction_utils.cpp b/src/test/lib/transaction_utils.cpp new file mode 100644 index 0000000000..2619fb9006 --- /dev/null +++ b/src/test/lib/transaction_utils.cpp @@ -0,0 +1,39 @@ +// Copyright (c) 2019 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include <test/lib/transaction_utils.h> + +CMutableTransaction BuildCreditingTransaction(const CScript& scriptPubKey, int nValue) +{ + CMutableTransaction txCredit; + txCredit.nVersion = 1; + txCredit.nLockTime = 0; + txCredit.vin.resize(1); + txCredit.vout.resize(1); + txCredit.vin[0].prevout.SetNull(); + txCredit.vin[0].scriptSig = CScript() << CScriptNum(0) << CScriptNum(0); + txCredit.vin[0].nSequence = CTxIn::SEQUENCE_FINAL; + txCredit.vout[0].scriptPubKey = scriptPubKey; + txCredit.vout[0].nValue = nValue; + + return txCredit; +} + +CMutableTransaction BuildSpendingTransaction(const CScript& scriptSig, const CScriptWitness& scriptWitness, const CTransaction& txCredit) +{ + CMutableTransaction txSpend; + txSpend.nVersion = 1; + txSpend.nLockTime = 0; + txSpend.vin.resize(1); + txSpend.vout.resize(1); + txSpend.vin[0].scriptWitness = scriptWitness; + txSpend.vin[0].prevout.hash = txCredit.GetHash(); + txSpend.vin[0].prevout.n = 0; + txSpend.vin[0].scriptSig = scriptSig; + txSpend.vin[0].nSequence = CTxIn::SEQUENCE_FINAL; + txSpend.vout[0].scriptPubKey = CScript(); + txSpend.vout[0].nValue = txCredit.vout[0].nValue; + + return txSpend; +} diff --git a/src/test/lib/transaction_utils.h b/src/test/lib/transaction_utils.h new file mode 100644 index 0000000000..6f297ac34f --- /dev/null +++ b/src/test/lib/transaction_utils.h @@ -0,0 +1,19 @@ +// Copyright (c) 2019 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_TEST_LIB_TRANSACTION_UTILS_H +#define BITCOIN_TEST_LIB_TRANSACTION_UTILS_H + +#include <primitives/transaction.h> + +// create crediting transaction +// [1 coinbase input => 1 output with given scriptPubkey and value] +CMutableTransaction BuildCreditingTransaction(const CScript& scriptPubKey, int nValue = 0); + +// create spending transaction +// [1 input with referenced transaction outpoint, scriptSig, scriptWitness => +// 1 output with empty scriptPubKey, full value of referenced transaction] +CMutableTransaction BuildSpendingTransaction(const CScript& scriptSig, const CScriptWitness& scriptWitness, const CTransaction& txCredit); + +#endif // BITCOIN_TEST_LIB_TRANSACTION_UTILS_H diff --git a/src/test/policyestimator_tests.cpp b/src/test/policyestimator_tests.cpp index 016a4f471b..5368f82ffe 100644 --- a/src/test/policyestimator_tests.cpp +++ b/src/test/policyestimator_tests.cpp @@ -6,7 +6,6 @@ #include <policy/fees.h> #include <txmempool.h> #include <uint256.h> -#include <util/system.h> #include <util/time.h> #include <test/setup_common.h> diff --git a/src/test/pow_tests.cpp b/src/test/pow_tests.cpp index deac349867..6c99021d97 100644 --- a/src/test/pow_tests.cpp +++ b/src/test/pow_tests.cpp @@ -5,7 +5,6 @@ #include <chain.h> #include <chainparams.h> #include <pow.h> -#include <util/system.h> #include <test/setup_common.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index 84a70fe78b..caa99805c3 100644 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -12,6 +12,7 @@ #include <script/signingprovider.h> #include <util/system.h> #include <util/strencodings.h> +#include <test/lib/transaction_utils.h> #include <test/setup_common.h> #include <rpc/util.h> #include <streams.h> @@ -121,40 +122,6 @@ static ScriptError_t ParseScriptError(const std::string &name) BOOST_FIXTURE_TEST_SUITE(script_tests, BasicTestingSetup) -CMutableTransaction BuildCreditingTransaction(const CScript& scriptPubKey, int nValue = 0) -{ - CMutableTransaction txCredit; - txCredit.nVersion = 1; - txCredit.nLockTime = 0; - txCredit.vin.resize(1); - txCredit.vout.resize(1); - txCredit.vin[0].prevout.SetNull(); - txCredit.vin[0].scriptSig = CScript() << CScriptNum(0) << CScriptNum(0); - txCredit.vin[0].nSequence = CTxIn::SEQUENCE_FINAL; - txCredit.vout[0].scriptPubKey = scriptPubKey; - txCredit.vout[0].nValue = nValue; - - return txCredit; -} - -CMutableTransaction BuildSpendingTransaction(const CScript& scriptSig, const CScriptWitness& scriptWitness, const CTransaction& txCredit) -{ - CMutableTransaction txSpend; - txSpend.nVersion = 1; - txSpend.nLockTime = 0; - txSpend.vin.resize(1); - txSpend.vout.resize(1); - txSpend.vin[0].scriptWitness = scriptWitness; - txSpend.vin[0].prevout.hash = txCredit.GetHash(); - txSpend.vin[0].prevout.n = 0; - txSpend.vin[0].scriptSig = scriptSig; - txSpend.vin[0].nSequence = CTxIn::SEQUENCE_FINAL; - txSpend.vout[0].scriptPubKey = CScript(); - txSpend.vout[0].nValue = txCredit.vout[0].nValue; - - return txSpend; -} - void DoTest(const CScript& scriptPubKey, const CScript& scriptSig, const CScriptWitness& scriptWitness, int flags, const std::string& message, int scriptError, CAmount nValue = 0) { bool expect = (scriptError == SCRIPT_ERR_OK); diff --git a/src/test/skiplist_tests.cpp b/src/test/skiplist_tests.cpp index 3d39dfdb75..1cba3a1297 100644 --- a/src/test/skiplist_tests.cpp +++ b/src/test/skiplist_tests.cpp @@ -3,7 +3,6 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <chain.h> -#include <util/system.h> #include <test/setup_common.h> #include <vector> diff --git a/src/test/streams_tests.cpp b/src/test/streams_tests.cpp index 638819d564..6075fbfeca 100644 --- a/src/test/streams_tests.cpp +++ b/src/test/streams_tests.cpp @@ -2,7 +2,6 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include <random.h> #include <streams.h> #include <test/setup_common.h> diff --git a/src/test/txindex_tests.cpp b/src/test/txindex_tests.cpp index d794d09d30..0ac4b7ebc9 100644 --- a/src/test/txindex_tests.cpp +++ b/src/test/txindex_tests.cpp @@ -6,7 +6,6 @@ #include <index/txindex.h> #include <script/standard.h> #include <test/setup_common.h> -#include <util/system.h> #include <util/time.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index 31a66b6fa9..02303d0f65 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -13,6 +13,7 @@ #include <util/string.h> #include <util/time.h> #include <util/spanparsing.h> +#include <util/vector.h> #include <stdint.h> #include <thread> @@ -26,6 +27,11 @@ #include <boost/test/unit_test.hpp> +/* defined in logging.cpp */ +namespace BCLog { + std::string LogEscapeMessage(const std::string& str); +} + BOOST_FIXTURE_TEST_SUITE(util_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(util_criticalsection) @@ -1696,4 +1702,122 @@ BOOST_AUTO_TEST_CASE(test_spanparsing) BOOST_CHECK_EQUAL(SpanToStr(results[3]), ""); } +BOOST_AUTO_TEST_CASE(test_LogEscapeMessage) +{ + // ASCII and UTF-8 must pass through unaltered. + BOOST_CHECK_EQUAL(BCLog::LogEscapeMessage("Valid log message貓"), "Valid log message貓"); + // Newlines must pass through unaltered. + BOOST_CHECK_EQUAL(BCLog::LogEscapeMessage("Message\n with newlines\n"), "Message\n with newlines\n"); + // Other control characters are escaped in C syntax. + BOOST_CHECK_EQUAL(BCLog::LogEscapeMessage("\x01\x7f Corrupted log message\x0d"), R"(\x01\x7f Corrupted log message\x0d)"); + // Embedded NULL characters are escaped too. + const std::string NUL("O\x00O", 3); + BOOST_CHECK_EQUAL(BCLog::LogEscapeMessage(NUL), R"(O\x00O)"); +} + +namespace { + +struct Tracker +{ + //! Points to the original object (possibly itself) we moved/copied from + const Tracker* origin; + //! How many copies where involved between the original object and this one (moves are not counted) + int copies; + + Tracker() noexcept : origin(this), copies(0) {} + Tracker(const Tracker& t) noexcept : origin(t.origin), copies(t.copies + 1) {} + Tracker(Tracker&& t) noexcept : origin(t.origin), copies(t.copies) {} + Tracker& operator=(const Tracker& t) noexcept + { + origin = t.origin; + copies = t.copies + 1; + return *this; + } + Tracker& operator=(Tracker&& t) noexcept + { + origin = t.origin; + copies = t.copies; + return *this; + } +}; + +} + +BOOST_AUTO_TEST_CASE(test_tracked_vector) +{ + Tracker t1; + Tracker t2; + Tracker t3; + + BOOST_CHECK(t1.origin == &t1); + BOOST_CHECK(t2.origin == &t2); + BOOST_CHECK(t3.origin == &t3); + + auto v1 = Vector(t1); + BOOST_CHECK_EQUAL(v1.size(), 1); + BOOST_CHECK(v1[0].origin == &t1); + BOOST_CHECK_EQUAL(v1[0].copies, 1); + + auto v2 = Vector(std::move(t2)); + BOOST_CHECK_EQUAL(v2.size(), 1); + BOOST_CHECK(v2[0].origin == &t2); + BOOST_CHECK_EQUAL(v2[0].copies, 0); + + auto v3 = Vector(t1, std::move(t2)); + BOOST_CHECK_EQUAL(v3.size(), 2); + BOOST_CHECK(v3[0].origin == &t1); + BOOST_CHECK(v3[1].origin == &t2); + BOOST_CHECK_EQUAL(v3[0].copies, 1); + BOOST_CHECK_EQUAL(v3[1].copies, 0); + + auto v4 = Vector(std::move(v3[0]), v3[1], std::move(t3)); + BOOST_CHECK_EQUAL(v4.size(), 3); + BOOST_CHECK(v4[0].origin == &t1); + BOOST_CHECK(v4[1].origin == &t2); + BOOST_CHECK(v4[2].origin == &t3); + BOOST_CHECK_EQUAL(v4[0].copies, 1); + BOOST_CHECK_EQUAL(v4[1].copies, 1); + BOOST_CHECK_EQUAL(v4[2].copies, 0); + + auto v5 = Cat(v1, v4); + BOOST_CHECK_EQUAL(v5.size(), 4); + BOOST_CHECK(v5[0].origin == &t1); + BOOST_CHECK(v5[1].origin == &t1); + BOOST_CHECK(v5[2].origin == &t2); + BOOST_CHECK(v5[3].origin == &t3); + BOOST_CHECK_EQUAL(v5[0].copies, 2); + BOOST_CHECK_EQUAL(v5[1].copies, 2); + BOOST_CHECK_EQUAL(v5[2].copies, 2); + BOOST_CHECK_EQUAL(v5[3].copies, 1); + + auto v6 = Cat(std::move(v1), v3); + BOOST_CHECK_EQUAL(v6.size(), 3); + BOOST_CHECK(v6[0].origin == &t1); + BOOST_CHECK(v6[1].origin == &t1); + BOOST_CHECK(v6[2].origin == &t2); + BOOST_CHECK_EQUAL(v6[0].copies, 1); + BOOST_CHECK_EQUAL(v6[1].copies, 2); + BOOST_CHECK_EQUAL(v6[2].copies, 1); + + auto v7 = Cat(v2, std::move(v4)); + BOOST_CHECK_EQUAL(v7.size(), 4); + BOOST_CHECK(v7[0].origin == &t2); + BOOST_CHECK(v7[1].origin == &t1); + BOOST_CHECK(v7[2].origin == &t2); + BOOST_CHECK(v7[3].origin == &t3); + BOOST_CHECK_EQUAL(v7[0].copies, 1); + BOOST_CHECK_EQUAL(v7[1].copies, 1); + BOOST_CHECK_EQUAL(v7[2].copies, 1); + BOOST_CHECK_EQUAL(v7[3].copies, 0); + + auto v8 = Cat(std::move(v2), std::move(v3)); + BOOST_CHECK_EQUAL(v8.size(), 3); + BOOST_CHECK(v8[0].origin == &t2); + BOOST_CHECK(v8[1].origin == &t1); + BOOST_CHECK(v8[2].origin == &t2); + BOOST_CHECK_EQUAL(v8[0].copies, 0); + BOOST_CHECK_EQUAL(v8[1].copies, 1); + BOOST_CHECK_EQUAL(v8[2].copies, 0); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/threadinterrupt.h b/src/threadinterrupt.h index 2743571379..0654c2ab1f 100644 --- a/src/threadinterrupt.h +++ b/src/threadinterrupt.h @@ -10,7 +10,6 @@ #include <atomic> #include <chrono> #include <condition_variable> -#include <mutex> /* A helper class for interruptible sleeps. Calling operator() will interrupt diff --git a/src/torcontrol.h b/src/torcontrol.h index 079146b540..e1a1a7937a 100644 --- a/src/torcontrol.h +++ b/src/torcontrol.h @@ -8,7 +8,6 @@ #ifndef BITCOIN_TORCONTROL_H #define BITCOIN_TORCONTROL_H -#include <scheduler.h> extern const std::string DEFAULT_TOR_CONTROL; static const bool DEFAULT_LISTEN_ONION = true; diff --git a/src/txdb.cpp b/src/txdb.cpp index 536bfee901..a7eb5f9f67 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -12,6 +12,7 @@ #include <uint256.h> #include <util/system.h> #include <util/translation.h> +#include <util/vector.h> #include <stdint.h> @@ -102,7 +103,7 @@ bool CCoinsViewDB::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) { // A vector is used for future extensibility, as we may want to support // interrupting after partial writes from multiple independent reorgs. batch.Erase(DB_BEST_BLOCK); - batch.Write(DB_HEAD_BLOCKS, std::vector<uint256>{hashBlock, old_tip}); + batch.Write(DB_HEAD_BLOCKS, Vector(hashBlock, old_tip)); for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end();) { if (it->second.flags & CCoinsCacheEntry::DIRTY) { diff --git a/src/txdb.h b/src/txdb.h index 140ce2c7ff..05bf4e4453 100644 --- a/src/txdb.h +++ b/src/txdb.h @@ -11,7 +11,6 @@ #include <chain.h> #include <primitives/block.h> -#include <map> #include <memory> #include <string> #include <utility> diff --git a/src/txmempool.h b/src/txmempool.h index 229a923a28..b51e800001 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -8,7 +8,6 @@ #include <atomic> #include <map> -#include <memory> #include <set> #include <string> #include <utility> diff --git a/src/ui_interface.h b/src/ui_interface.h index 5e0380dc45..9efc2db391 100644 --- a/src/ui_interface.h +++ b/src/ui_interface.h @@ -8,7 +8,6 @@ #include <functional> #include <memory> -#include <stdint.h> #include <string> class CBlockIndex; diff --git a/src/uint256.cpp b/src/uint256.cpp index ea7164c1f0..ee597e1877 100644 --- a/src/uint256.cpp +++ b/src/uint256.cpp @@ -7,7 +7,6 @@ #include <util/strencodings.h> -#include <stdio.h> #include <string.h> template <unsigned int BITS> diff --git a/src/uint256.h b/src/uint256.h index 97e0cfa015..60c5e0554c 100644 --- a/src/uint256.h +++ b/src/uint256.h @@ -8,7 +8,6 @@ #include <assert.h> #include <cstring> -#include <stdexcept> #include <stdint.h> #include <string> #include <vector> diff --git a/src/util/check.h b/src/util/check.h new file mode 100644 index 0000000000..d18887ae95 --- /dev/null +++ b/src/util/check.h @@ -0,0 +1,41 @@ +// Copyright (c) 2019 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_UTIL_CHECK_H +#define BITCOIN_UTIL_CHECK_H + +#include <tinyformat.h> + +#include <stdexcept> + +class NonFatalCheckError : public std::runtime_error +{ + using std::runtime_error::runtime_error; +}; + +/** + * Throw a NonFatalCheckError when the condition evaluates to false + * + * This should only be used + * - where the condition is assumed to be true, not for error handling or validating user input + * - where a failure to fulfill the condition is recoverable and does not abort the program + * + * For example in RPC code, where it is undersirable to crash the whole program, this can be generally used to replace + * asserts or recoverable logic errors. A NonFatalCheckError in RPC code is caught and passed as a string to the RPC + * caller, which can then report the issue to the developers. + */ +#define CHECK_NONFATAL(condition) \ + do { \ + if (!(condition)) { \ + throw NonFatalCheckError( \ + strprintf("%s:%d (%s)\n" \ + "Internal bug detected: '%s'\n" \ + "You may report this issue here: %s\n", \ + __FILE__, __LINE__, __func__, \ + (#condition), \ + PACKAGE_BUGREPORT)); \ + } \ + } while (false) + +#endif // BITCOIN_UTIL_CHECK_H diff --git a/src/util/moneystr.cpp b/src/util/moneystr.cpp index f4e41eea4f..ba5a12e58c 100644 --- a/src/util/moneystr.cpp +++ b/src/util/moneystr.cpp @@ -5,7 +5,6 @@ #include <util/moneystr.h> -#include <primitives/transaction.h> #include <tinyformat.h> #include <util/strencodings.h> diff --git a/src/util/moneystr.h b/src/util/moneystr.h index b8e2812a96..4d0218911a 100644 --- a/src/util/moneystr.h +++ b/src/util/moneystr.h @@ -12,7 +12,6 @@ #include <amount.h> #include <attributes.h> -#include <cstdint> #include <string> /* Do not use these functions to represent or parse monetary amounts to or from diff --git a/src/util/string.h b/src/util/string.h index dec0c19b08..76a83a4949 100644 --- a/src/util/string.h +++ b/src/util/string.h @@ -5,7 +5,6 @@ #ifndef BITCOIN_UTIL_STRING_H #define BITCOIN_UTIL_STRING_H -#include <functional> #include <string> #include <vector> diff --git a/src/util/system.cpp b/src/util/system.cpp index f22256615f..526bf559c3 100644 --- a/src/util/system.cpp +++ b/src/util/system.cpp @@ -9,7 +9,6 @@ #include <util/strencodings.h> #include <util/translation.h> -#include <stdarg.h> #if (defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)) #include <pthread.h> @@ -380,6 +379,15 @@ bool ArgsManager::ParseParameters(int argc, const char* const argv[], std::strin for (int i = 1; i < argc; i++) { std::string key(argv[i]); + +#ifdef MAC_OSX + // At the first time when a user gets the "App downloaded from the + // internet" warning, and clicks the Open button, macOS passes + // a unique process serial number (PSN) as -psn_... command-line + // argument, which we filter out. + if (key.substr(0, 5) == "-psn_") continue; +#endif + if (key == "-") break; //bitcoin-tx using stdin std::string val; size_t is_index = key.find('='); diff --git a/src/util/threadnames.cpp b/src/util/threadnames.cpp index 168f9325d0..20df403a66 100644 --- a/src/util/threadnames.cpp +++ b/src/util/threadnames.cpp @@ -6,7 +6,6 @@ #include <config/bitcoin-config.h> #endif -#include <atomic> #include <thread> #if (defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)) diff --git a/src/util/translation.h b/src/util/translation.h index f100dab20d..0e6eb5a094 100644 --- a/src/util/translation.h +++ b/src/util/translation.h @@ -7,7 +7,6 @@ #include <tinyformat.h> -#include <utility> /** * Bilingual messages: diff --git a/src/util/validation.cpp b/src/util/validation.cpp index fe1f5a277e..9a0d889447 100644 --- a/src/util/validation.cpp +++ b/src/util/validation.cpp @@ -11,10 +11,9 @@ /** Convert CValidationState to a human-readable message for logging */ std::string FormatStateMessage(const CValidationState &state) { - return strprintf("%s%s (code %i)", + return strprintf("%s%s", state.GetRejectReason(), - state.GetDebugMessage().empty() ? "" : ", "+state.GetDebugMessage(), - state.GetRejectCode()); + state.GetDebugMessage().empty() ? "" : ", "+state.GetDebugMessage()); } const std::string strMessageMagic = "Bitcoin Signed Message:\n"; diff --git a/src/util/vector.h b/src/util/vector.h new file mode 100644 index 0000000000..dab65ded2a --- /dev/null +++ b/src/util/vector.h @@ -0,0 +1,51 @@ +// Copyright (c) 2019 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_UTIL_VECTOR_H +#define BITCOIN_UTIL_VECTOR_H + +#include <initializer_list> +#include <type_traits> +#include <vector> + +/** Construct a vector with the specified elements. + * + * This is preferable over the list initializing constructor of std::vector: + * - It automatically infers the element type from its arguments. + * - If any arguments are rvalue references, they will be moved into the vector + * (list initialization always copies). + */ +template<typename... Args> +inline std::vector<typename std::common_type<Args...>::type> Vector(Args&&... args) +{ + std::vector<typename std::common_type<Args...>::type> ret; + ret.reserve(sizeof...(args)); + // The line below uses the trick from https://www.experts-exchange.com/articles/32502/None-recursive-variadic-templates-with-std-initializer-list.html + (void)std::initializer_list<int>{(ret.emplace_back(std::forward<Args>(args)), 0)...}; + return ret; +} + +/** Concatenate two vectors, moving elements. */ +template<typename V> +inline V Cat(V v1, V&& v2) +{ + v1.reserve(v1.size() + v2.size()); + for (auto& arg : v2) { + v1.push_back(std::move(arg)); + } + return v1; +} + +/** Concatenate two vectors. */ +template<typename V> +inline V Cat(V v1, const V& v2) +{ + v1.reserve(v1.size() + v2.size()); + for (const auto& arg : v2) { + v1.push_back(arg); + } + return v1; +} + +#endif // BITCOIN_UTIL_VECTOR_H diff --git a/src/validation.cpp b/src/validation.cpp index 726f251c5a..9301066c6a 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -28,7 +28,6 @@ #include <reverse_iterator.h> #include <script/script.h> #include <script/sigcache.h> -#include <script/standard.h> #include <shutdown.h> #include <timedata.h> #include <tinyformat.h> @@ -46,8 +45,6 @@ #include <validationinterface.h> #include <warnings.h> -#include <future> -#include <sstream> #include <string> #include <boost/algorithm/string/replace.hpp> @@ -395,7 +392,7 @@ static void UpdateMempoolForReorg(DisconnectedBlockTransactions& disconnectpool, // Used to avoid mempool polluting consensus critical paths if CCoinsViewMempool // were somehow broken and returning the wrong scriptPubKeys static bool CheckInputsFromMempoolAndCache(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& view, const CTxMemPool& pool, - unsigned int flags, bool cacheSigStore, PrecomputedTransactionData& txdata) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { + unsigned int flags, PrecomputedTransactionData& txdata) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { AssertLockHeld(cs_main); // pool.cs should be locked already, but go ahead and re-take the lock here @@ -425,7 +422,8 @@ static bool CheckInputsFromMempoolAndCache(const CTransaction& tx, CValidationSt } } - return CheckInputs(tx, state, view, flags, cacheSigStore, true, txdata); + // Call CheckInputs() to cache signature and script validity against current tip consensus rules. + return CheckInputs(tx, state, view, flags, /* cacheSigStore = */ true, /* cacheFullSciptStore = */ true, txdata); } namespace { @@ -508,11 +506,11 @@ private: { CAmount mempoolRejectFee = m_pool.GetMinFee(gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000).GetFee(package_size); if (mempoolRejectFee > 0 && package_fee < mempoolRejectFee) { - return state.Invalid(ValidationInvalidReason::TX_MEMPOOL_POLICY, false, REJECT_INSUFFICIENTFEE, "mempool min fee not met", strprintf("%d < %d", package_fee, mempoolRejectFee)); + return state.Invalid(ValidationInvalidReason::TX_MEMPOOL_POLICY, false, "mempool min fee not met", strprintf("%d < %d", package_fee, mempoolRejectFee)); } if (package_fee < ::minRelayTxFee.GetFee(package_size)) { - return state.Invalid(ValidationInvalidReason::TX_MEMPOOL_POLICY, false, REJECT_INSUFFICIENTFEE, "min relay fee not met", strprintf("%d < %d", package_fee, ::minRelayTxFee.GetFee(package_size))); + return state.Invalid(ValidationInvalidReason::TX_MEMPOOL_POLICY, false, "min relay fee not met", strprintf("%d < %d", package_fee, ::minRelayTxFee.GetFee(package_size))); } return true; } @@ -565,29 +563,29 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws) // Coinbase is only valid in a block, not as a loose transaction if (tx.IsCoinBase()) - return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "coinbase"); + return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "coinbase"); // Rather not work on nonstandard transactions (unless -testnet/-regtest) std::string reason; if (fRequireStandard && !IsStandardTx(tx, reason)) - return state.Invalid(ValidationInvalidReason::TX_NOT_STANDARD, false, REJECT_NONSTANDARD, reason); + return state.Invalid(ValidationInvalidReason::TX_NOT_STANDARD, false, reason); // Do not work on transactions that are too small. // A transaction with 1 segwit input and 1 P2WPHK output has non-witness size of 82 bytes. // Transactions smaller than this are not relayed to mitigate CVE-2017-12842 by not relaying // 64-byte transactions. if (::GetSerializeSize(tx, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) < MIN_STANDARD_TX_NONWITNESS_SIZE) - return state.Invalid(ValidationInvalidReason::TX_NOT_STANDARD, false, REJECT_NONSTANDARD, "tx-size-small"); + return state.Invalid(ValidationInvalidReason::TX_NOT_STANDARD, false, "tx-size-small"); // Only accept nLockTime-using transactions that can be mined in the next // block; we don't want our mempool filled up with transactions that can't // be mined yet. if (!CheckFinalTx(tx, STANDARD_LOCKTIME_VERIFY_FLAGS)) - return state.Invalid(ValidationInvalidReason::TX_PREMATURE_SPEND, false, REJECT_NONSTANDARD, "non-final"); + return state.Invalid(ValidationInvalidReason::TX_PREMATURE_SPEND, false, "non-final"); // is it already in the memory pool? if (m_pool.exists(hash)) { - return state.Invalid(ValidationInvalidReason::TX_CONFLICT, false, REJECT_DUPLICATE, "txn-already-in-mempool"); + return state.Invalid(ValidationInvalidReason::TX_CONFLICT, false, "txn-already-in-mempool"); } // Check for conflicts with in-memory transactions @@ -619,7 +617,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws) } } if (fReplacementOptOut) { - return state.Invalid(ValidationInvalidReason::TX_MEMPOOL_POLICY, false, REJECT_DUPLICATE, "txn-mempool-conflict"); + return state.Invalid(ValidationInvalidReason::TX_MEMPOOL_POLICY, false, "txn-mempool-conflict"); } setConflicts.insert(ptxConflicting->GetHash()); @@ -645,7 +643,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws) for (size_t out = 0; out < tx.vout.size(); out++) { // Optimistically just do efficient check of cache for outputs if (coins_cache.HaveCoinInCache(COutPoint(hash, out))) { - return state.Invalid(ValidationInvalidReason::TX_CONFLICT, false, REJECT_DUPLICATE, "txn-already-known"); + return state.Invalid(ValidationInvalidReason::TX_CONFLICT, false, "txn-already-known"); } } // Otherwise assume this might be an orphan tx for which we just haven't seen parents yet @@ -670,7 +668,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws) // Must keep pool.cs for this unless we change CheckSequenceLocks to take a // CoinsViewCache instead of create its own if (!CheckSequenceLocks(m_pool, tx, STANDARD_LOCKTIME_VERIFY_FLAGS, &lp)) - return state.Invalid(ValidationInvalidReason::TX_PREMATURE_SPEND, false, REJECT_NONSTANDARD, "non-BIP68-final"); + return state.Invalid(ValidationInvalidReason::TX_PREMATURE_SPEND, false, "non-BIP68-final"); CAmount nFees = 0; if (!Consensus::CheckTxInputs(tx, state, m_view, GetSpendHeight(m_view), nFees)) { @@ -679,11 +677,11 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws) // Check for non-standard pay-to-script-hash in inputs if (fRequireStandard && !AreInputsStandard(tx, m_view)) - return state.Invalid(ValidationInvalidReason::TX_NOT_STANDARD, false, REJECT_NONSTANDARD, "bad-txns-nonstandard-inputs"); + return state.Invalid(ValidationInvalidReason::TX_NOT_STANDARD, false, "bad-txns-nonstandard-inputs"); // Check for non-standard witness in P2WSH if (tx.HasWitness() && fRequireStandard && !IsWitnessStandard(tx, m_view)) - return state.Invalid(ValidationInvalidReason::TX_WITNESS_MUTATED, false, REJECT_NONSTANDARD, "bad-witness-nonstandard"); + return state.Invalid(ValidationInvalidReason::TX_WITNESS_MUTATED, false, "bad-witness-nonstandard"); int64_t nSigOpsCost = GetTransactionSigOpCost(tx, m_view, STANDARD_SCRIPT_VERIFY_FLAGS); @@ -707,7 +705,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws) unsigned int nSize = entry->GetTxSize(); if (nSigOpsCost > MAX_STANDARD_TX_SIGOPS_COST) - return state.Invalid(ValidationInvalidReason::TX_NOT_STANDARD, false, REJECT_NONSTANDARD, "bad-txns-too-many-sigops", + return state.Invalid(ValidationInvalidReason::TX_NOT_STANDARD, false, "bad-txns-too-many-sigops", strprintf("%d", nSigOpsCost)); // No transactions are allowed below minRelayTxFee except from disconnected @@ -716,8 +714,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws) if (nAbsurdFee && nFees > nAbsurdFee) return state.Invalid(ValidationInvalidReason::TX_NOT_STANDARD, false, - REJECT_HIGHFEE, "absurdly-high-fee", - strprintf("%d > %d", nFees, nAbsurdFee)); + "absurdly-high-fee", strprintf("%d > %d", nFees, nAbsurdFee)); const CTxMemPool::setEntries setIterConflicting = m_pool.GetIterSet(setConflicts); // Calculate in-mempool ancestors, up to a limit. @@ -774,7 +771,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws) // this, see https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-November/016518.html if (nSize > EXTRA_DESCENDANT_TX_SIZE_LIMIT || !m_pool.CalculateMemPoolAncestors(*entry, setAncestors, 2, m_limit_ancestor_size, m_limit_descendants + 1, m_limit_descendant_size + EXTRA_DESCENDANT_TX_SIZE_LIMIT, dummy_err_string)) { - return state.Invalid(ValidationInvalidReason::TX_MEMPOOL_POLICY, false, REJECT_NONSTANDARD, "too-long-mempool-chain", errString); + return state.Invalid(ValidationInvalidReason::TX_MEMPOOL_POLICY, false, "too-long-mempool-chain", errString); } } @@ -787,7 +784,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws) const uint256 &hashAncestor = ancestorIt->GetTx().GetHash(); if (setConflicts.count(hashAncestor)) { - return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-txns-spends-conflicting-tx", + return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-txns-spends-conflicting-tx", strprintf("%s spends conflicting transaction %s", hash.ToString(), hashAncestor.ToString())); @@ -827,7 +824,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws) CFeeRate oldFeeRate(mi->GetModifiedFee(), mi->GetTxSize()); if (newFeeRate <= oldFeeRate) { - return state.Invalid(ValidationInvalidReason::TX_MEMPOOL_POLICY, false, REJECT_INSUFFICIENTFEE, "insufficient fee", + return state.Invalid(ValidationInvalidReason::TX_MEMPOOL_POLICY, false, "insufficient fee", strprintf("rejecting replacement %s; new feerate %s <= old feerate %s", hash.ToString(), newFeeRate.ToString(), @@ -855,7 +852,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws) nConflictingSize += it->GetTxSize(); } } else { - return state.Invalid(ValidationInvalidReason::TX_MEMPOOL_POLICY, false, REJECT_NONSTANDARD, "too many potential replacements", + return state.Invalid(ValidationInvalidReason::TX_MEMPOOL_POLICY, false, "too many potential replacements", strprintf("rejecting replacement %s; too many potential replacements (%d > %d)\n", hash.ToString(), nConflictingCount, @@ -879,7 +876,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws) // it's cheaper to just check if the new input refers to a // tx that's in the mempool. if (m_pool.exists(tx.vin[j].prevout.hash)) { - return state.Invalid(ValidationInvalidReason::TX_MEMPOOL_POLICY, false, REJECT_NONSTANDARD, "replacement-adds-unconfirmed", + return state.Invalid(ValidationInvalidReason::TX_MEMPOOL_POLICY, false, "replacement-adds-unconfirmed", strprintf("replacement %s adds unconfirmed input, idx %d", hash.ToString(), j)); } @@ -891,7 +888,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws) // transactions would not be paid for. if (nModifiedFees < nConflictingFees) { - return state.Invalid(ValidationInvalidReason::TX_MEMPOOL_POLICY, false, REJECT_INSUFFICIENTFEE, "insufficient fee", + return state.Invalid(ValidationInvalidReason::TX_MEMPOOL_POLICY, false, "insufficient fee", strprintf("rejecting replacement %s, less fees than conflicting txs; %s < %s", hash.ToString(), FormatMoney(nModifiedFees), FormatMoney(nConflictingFees))); } @@ -901,7 +898,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws) CAmount nDeltaFees = nModifiedFees - nConflictingFees; if (nDeltaFees < ::incrementalRelayFee.GetFee(nSize)) { - return state.Invalid(ValidationInvalidReason::TX_MEMPOOL_POLICY, false, REJECT_INSUFFICIENTFEE, "insufficient fee", + return state.Invalid(ValidationInvalidReason::TX_MEMPOOL_POLICY, false, "insufficient fee", strprintf("rejecting replacement %s, not enough additional fees to relay; %s < %s", hash.ToString(), FormatMoney(nDeltaFees), @@ -930,7 +927,7 @@ bool MemPoolAccept::PolicyScriptChecks(ATMPArgs& args, Workspace& ws, Precompute !CheckInputs(tx, stateDummy, m_view, scriptVerifyFlags & ~SCRIPT_VERIFY_CLEANSTACK, true, false, txdata)) { // Only the witness is missing, so the transaction itself may be fine. state.Invalid(ValidationInvalidReason::TX_WITNESS_MUTATED, false, - state.GetRejectCode(), state.GetRejectReason(), state.GetDebugMessage()); + state.GetRejectReason(), state.GetDebugMessage()); } assert(IsTransactionReason(state.GetReason())); return false; // state filled in by CheckInputs @@ -963,7 +960,7 @@ bool MemPoolAccept::ConsensusScriptChecks(ATMPArgs& args, Workspace& ws, Precomp // invalid blocks (using TestBlockValidity), however allowing such // transactions into the mempool can be exploited as a DoS attack. unsigned int currentBlockScriptVerifyFlags = GetBlockScriptFlags(::ChainActive().Tip(), chainparams.GetConsensus()); - if (!CheckInputsFromMempoolAndCache(tx, state, m_view, m_pool, currentBlockScriptVerifyFlags, true, txdata)) { + if (!CheckInputsFromMempoolAndCache(tx, state, m_view, m_pool, currentBlockScriptVerifyFlags, txdata)) { return error("%s: BUG! PLEASE REPORT THIS! CheckInputs failed against latest-block but not STANDARD flags %s, %s", __func__, hash.ToString(), FormatStateMessage(state)); } @@ -1013,7 +1010,7 @@ bool MemPoolAccept::Finalize(ATMPArgs& args, Workspace& ws) if (!bypass_limits) { LimitMempoolSize(m_pool, gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000, std::chrono::hours{gArgs.GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY)}); if (!m_pool.exists(hash)) - return state.Invalid(ValidationInvalidReason::TX_MEMPOOL_POLICY, false, REJECT_INSUFFICIENTFEE, "mempool full"); + return state.Invalid(ValidationInvalidReason::TX_MEMPOOL_POLICY, false, "mempool full"); } return true; } @@ -1548,7 +1545,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi CScriptCheck check2(coin.out, tx, i, flags & ~STANDARD_NOT_MANDATORY_VERIFY_FLAGS, cacheSigStore, &txdata); if (check2()) - return state.Invalid(ValidationInvalidReason::TX_NOT_STANDARD, false, REJECT_NONSTANDARD, strprintf("non-mandatory-script-verify-flag (%s)", ScriptErrorString(check.GetScriptError()))); + return state.Invalid(ValidationInvalidReason::TX_NOT_STANDARD, false, strprintf("non-mandatory-script-verify-flag (%s)", ScriptErrorString(check.GetScriptError()))); } // MANDATORY flag failures correspond to // ValidationInvalidReason::CONSENSUS. Because CONSENSUS @@ -1559,7 +1556,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi // support, to avoid splitting the network (but this // depends on the details of how net_processing handles // such errors). - return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, strprintf("mandatory-script-verify-flag-failed (%s)", ScriptErrorString(check.GetScriptError()))); + return state.Invalid(ValidationInvalidReason::CONSENSUS, false, strprintf("mandatory-script-verify-flag-failed (%s)", ScriptErrorString(check.GetScriptError()))); } } @@ -2062,7 +2059,7 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl for (size_t o = 0; o < tx->vout.size(); o++) { if (view.HaveCoin(COutPoint(tx->GetHash(), o))) { return state.Invalid(ValidationInvalidReason::CONSENSUS, error("ConnectBlock(): tried to overwrite transaction"), - REJECT_INVALID, "bad-txns-BIP30"); + "bad-txns-BIP30"); } } } @@ -2107,14 +2104,14 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl // defined for a block, so we reset the reason flag to // CONSENSUS here. state.Invalid(ValidationInvalidReason::CONSENSUS, false, - state.GetRejectCode(), state.GetRejectReason(), state.GetDebugMessage()); + state.GetRejectReason(), state.GetDebugMessage()); } return error("%s: Consensus::CheckTxInputs: %s, %s", __func__, tx.GetHash().ToString(), FormatStateMessage(state)); } nFees += txfee; if (!MoneyRange(nFees)) { return state.Invalid(ValidationInvalidReason::CONSENSUS, error("%s: accumulated fee in the block out of range.", __func__), - REJECT_INVALID, "bad-txns-accumulated-fee-outofrange"); + "bad-txns-accumulated-fee-outofrange"); } // Check that transaction is BIP68 final @@ -2127,7 +2124,7 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl if (!SequenceLocks(tx, nLockTimeFlags, &prevheights, *pindex)) { return state.Invalid(ValidationInvalidReason::CONSENSUS, error("%s: contains a non-BIP68-final transaction", __func__), - REJECT_INVALID, "bad-txns-nonfinal"); + "bad-txns-nonfinal"); } } @@ -2138,7 +2135,7 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl nSigOpsCost += GetTransactionSigOpCost(tx, view, flags); if (nSigOpsCost > MAX_BLOCK_SIGOPS_COST) return state.Invalid(ValidationInvalidReason::CONSENSUS, error("ConnectBlock(): too many sigops"), - REJECT_INVALID, "bad-blk-sigops"); + "bad-blk-sigops"); txdata.emplace_back(tx); if (!tx.IsCoinBase()) @@ -2154,7 +2151,7 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl // consider whether rewriting to CONSENSUS or // RECENT_CONSENSUS_CHANGE would be more appropriate. state.Invalid(ValidationInvalidReason::CONSENSUS, false, - state.GetRejectCode(), state.GetRejectReason(), state.GetDebugMessage()); + state.GetRejectReason(), state.GetDebugMessage()); } return error("ConnectBlock(): CheckInputs on %s failed with %s", tx.GetHash().ToString(), FormatStateMessage(state)); @@ -2176,10 +2173,10 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl return state.Invalid(ValidationInvalidReason::CONSENSUS, error("ConnectBlock(): coinbase pays too much (actual=%d vs limit=%d)", block.vtx[0]->GetValueOut(), blockReward), - REJECT_INVALID, "bad-cb-amount"); + "bad-cb-amount"); if (!control.Wait()) - return state.Invalid(ValidationInvalidReason::CONSENSUS, error("%s: CheckQueue failed", __func__), REJECT_INVALID, "block-validation-failed"); + return state.Invalid(ValidationInvalidReason::CONSENSUS, error("%s: CheckQueue failed", __func__), "block-validation-failed"); int64_t nTime4 = GetTimeMicros(); nTimeVerify += nTime4 - nTime2; LogPrint(BCLog::BENCH, " - Verify %u txins: %.2fms (%.3fms/txin) [%.2fs (%.2fms/blk)]\n", nInputs - 1, MILLI * (nTime4 - nTime2), nInputs <= 1 ? 0 : MILLI * (nTime4 - nTime2) / (nInputs-1), nTimeVerify * MICRO, nTimeVerify * MILLI / nBlocksTotal); @@ -3256,7 +3253,7 @@ static bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, { // Check proof of work matches claimed amount if (fCheckPOW && !CheckProofOfWork(block.GetHash(), block.nBits, consensusParams)) - return state.Invalid(ValidationInvalidReason::BLOCK_INVALID_HEADER, false, REJECT_INVALID, "high-hash", "proof of work failed"); + return state.Invalid(ValidationInvalidReason::BLOCK_INVALID_HEADER, false, "high-hash", "proof of work failed"); return true; } @@ -3278,13 +3275,13 @@ bool CheckBlock(const CBlock& block, CValidationState& state, const Consensus::P bool mutated; uint256 hashMerkleRoot2 = BlockMerkleRoot(block, &mutated); if (block.hashMerkleRoot != hashMerkleRoot2) - return state.Invalid(ValidationInvalidReason::BLOCK_MUTATED, false, REJECT_INVALID, "bad-txnmrklroot", "hashMerkleRoot mismatch"); + return state.Invalid(ValidationInvalidReason::BLOCK_MUTATED, false, "bad-txnmrklroot", "hashMerkleRoot mismatch"); // Check for merkle tree malleability (CVE-2012-2459): repeating sequences // of transactions in a block without affecting the merkle root of a block, // while still invalidating it. if (mutated) - return state.Invalid(ValidationInvalidReason::BLOCK_MUTATED, false, REJECT_INVALID, "bad-txns-duplicate", "duplicate transaction"); + return state.Invalid(ValidationInvalidReason::BLOCK_MUTATED, false, "bad-txns-duplicate", "duplicate transaction"); } // All potential-corruption validation must be done before we do any @@ -3295,20 +3292,19 @@ bool CheckBlock(const CBlock& block, CValidationState& state, const Consensus::P // Size limits if (block.vtx.empty() || block.vtx.size() * WITNESS_SCALE_FACTOR > MAX_BLOCK_WEIGHT || ::GetSerializeSize(block, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * WITNESS_SCALE_FACTOR > MAX_BLOCK_WEIGHT) - return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-blk-length", "size limits failed"); + return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-blk-length", "size limits failed"); // First transaction must be coinbase, the rest must not be if (block.vtx.empty() || !block.vtx[0]->IsCoinBase()) - return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-cb-missing", "first tx is not coinbase"); + return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-cb-missing", "first tx is not coinbase"); for (unsigned int i = 1; i < block.vtx.size(); i++) if (block.vtx[i]->IsCoinBase()) - return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-cb-multiple", "more than one coinbase"); + return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-cb-multiple", "more than one coinbase"); // Check transactions - // Must check for duplicate inputs (see CVE-2018-17144) for (const auto& tx : block.vtx) - if (!CheckTransaction(*tx, state, true)) - return state.Invalid(state.GetReason(), false, state.GetRejectCode(), state.GetRejectReason(), + if (!CheckTransaction(*tx, state)) + return state.Invalid(state.GetReason(), false, state.GetRejectReason(), strprintf("Transaction check failed (tx hash %s) %s", tx->GetHash().ToString(), state.GetDebugMessage())); unsigned int nSigOps = 0; @@ -3317,7 +3313,7 @@ bool CheckBlock(const CBlock& block, CValidationState& state, const Consensus::P nSigOps += GetLegacySigOpCount(*tx); } if (nSigOps * WITNESS_SCALE_FACTOR > MAX_BLOCK_SIGOPS_COST) - return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-blk-sigops", "out-of-bounds SigOpCount"); + return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-blk-sigops", "out-of-bounds SigOpCount"); if (fCheckPOW && fCheckMerkleRoot) block.fChecked = true; @@ -3418,7 +3414,7 @@ static bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationSta // Check proof of work const Consensus::Params& consensusParams = params.GetConsensus(); if (block.nBits != GetNextWorkRequired(pindexPrev, &block, consensusParams)) - return state.Invalid(ValidationInvalidReason::BLOCK_INVALID_HEADER, false, REJECT_INVALID, "bad-diffbits", "incorrect proof of work"); + return state.Invalid(ValidationInvalidReason::BLOCK_INVALID_HEADER, false, "bad-diffbits", "incorrect proof of work"); // Check against checkpoints if (fCheckpointsEnabled) { @@ -3427,23 +3423,23 @@ static bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationSta // g_blockman.m_block_index. CBlockIndex* pcheckpoint = GetLastCheckpoint(params.Checkpoints()); if (pcheckpoint && nHeight < pcheckpoint->nHeight) - return state.Invalid(ValidationInvalidReason::BLOCK_CHECKPOINT, error("%s: forked chain older than last checkpoint (height %d)", __func__, nHeight), REJECT_CHECKPOINT, "bad-fork-prior-to-checkpoint"); + return state.Invalid(ValidationInvalidReason::BLOCK_CHECKPOINT, error("%s: forked chain older than last checkpoint (height %d)", __func__, nHeight), "bad-fork-prior-to-checkpoint"); } // Check timestamp against prev if (block.GetBlockTime() <= pindexPrev->GetMedianTimePast()) - return state.Invalid(ValidationInvalidReason::BLOCK_INVALID_HEADER, false, REJECT_INVALID, "time-too-old", "block's timestamp is too early"); + return state.Invalid(ValidationInvalidReason::BLOCK_INVALID_HEADER, false, "time-too-old", "block's timestamp is too early"); // Check timestamp if (block.GetBlockTime() > nAdjustedTime + MAX_FUTURE_BLOCK_TIME) - return state.Invalid(ValidationInvalidReason::BLOCK_TIME_FUTURE, false, REJECT_INVALID, "time-too-new", "block timestamp too far in the future"); + return state.Invalid(ValidationInvalidReason::BLOCK_TIME_FUTURE, false, "time-too-new", "block timestamp too far in the future"); // Reject outdated version blocks when 95% (75% on testnet) of the network has upgraded: // check for version 2, 3 and 4 upgrades if((block.nVersion < 2 && nHeight >= consensusParams.BIP34Height) || (block.nVersion < 3 && nHeight >= consensusParams.BIP66Height) || (block.nVersion < 4 && nHeight >= consensusParams.BIP65Height)) - return state.Invalid(ValidationInvalidReason::BLOCK_INVALID_HEADER, false, REJECT_OBSOLETE, strprintf("bad-version(0x%08x)", block.nVersion), + return state.Invalid(ValidationInvalidReason::BLOCK_INVALID_HEADER, false, strprintf("bad-version(0x%08x)", block.nVersion), strprintf("rejected nVersion=0x%08x block", block.nVersion)); return true; @@ -3473,7 +3469,7 @@ static bool ContextualCheckBlock(const CBlock& block, CValidationState& state, c // Check that all transactions are finalized for (const auto& tx : block.vtx) { if (!IsFinalTx(*tx, nHeight, nLockTimeCutoff)) { - return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-txns-nonfinal", "non-final transaction"); + return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-txns-nonfinal", "non-final transaction"); } } @@ -3483,7 +3479,7 @@ static bool ContextualCheckBlock(const CBlock& block, CValidationState& state, c CScript expect = CScript() << nHeight; if (block.vtx[0]->vin[0].scriptSig.size() < expect.size() || !std::equal(expect.begin(), expect.end(), block.vtx[0]->vin[0].scriptSig.begin())) { - return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-cb-height", "block height mismatch in coinbase"); + return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-cb-height", "block height mismatch in coinbase"); } } @@ -3505,11 +3501,11 @@ static bool ContextualCheckBlock(const CBlock& block, CValidationState& state, c // already does not permit it, it is impossible to trigger in the // witness tree. if (block.vtx[0]->vin[0].scriptWitness.stack.size() != 1 || block.vtx[0]->vin[0].scriptWitness.stack[0].size() != 32) { - return state.Invalid(ValidationInvalidReason::BLOCK_MUTATED, false, REJECT_INVALID, "bad-witness-nonce-size", strprintf("%s : invalid witness reserved value size", __func__)); + return state.Invalid(ValidationInvalidReason::BLOCK_MUTATED, false, "bad-witness-nonce-size", strprintf("%s : invalid witness reserved value size", __func__)); } CHash256().Write(hashWitness.begin(), 32).Write(&block.vtx[0]->vin[0].scriptWitness.stack[0][0], 32).Finalize(hashWitness.begin()); if (memcmp(hashWitness.begin(), &block.vtx[0]->vout[commitpos].scriptPubKey[6], 32)) { - return state.Invalid(ValidationInvalidReason::BLOCK_MUTATED, false, REJECT_INVALID, "bad-witness-merkle-match", strprintf("%s : witness merkle commitment mismatch", __func__)); + return state.Invalid(ValidationInvalidReason::BLOCK_MUTATED, false, "bad-witness-merkle-match", strprintf("%s : witness merkle commitment mismatch", __func__)); } fHaveWitness = true; } @@ -3519,7 +3515,7 @@ static bool ContextualCheckBlock(const CBlock& block, CValidationState& state, c if (!fHaveWitness) { for (const auto& tx : block.vtx) { if (tx->HasWitness()) { - return state.Invalid(ValidationInvalidReason::BLOCK_MUTATED, false, REJECT_INVALID, "unexpected-witness", strprintf("%s : unexpected witness data found", __func__)); + return state.Invalid(ValidationInvalidReason::BLOCK_MUTATED, false, "unexpected-witness", strprintf("%s : unexpected witness data found", __func__)); } } } @@ -3531,7 +3527,7 @@ static bool ContextualCheckBlock(const CBlock& block, CValidationState& state, c // the block hash, so we couldn't mark the block as permanently // failed). if (GetBlockWeight(block) > MAX_BLOCK_WEIGHT) { - return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-blk-weight", strprintf("%s : weight limit failed", __func__)); + return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-blk-weight", strprintf("%s : weight limit failed", __func__)); } return true; @@ -3551,7 +3547,7 @@ bool BlockManager::AcceptBlockHeader(const CBlockHeader& block, CValidationState if (ppindex) *ppindex = pindex; if (pindex->nStatus & BLOCK_FAILED_MASK) - return state.Invalid(ValidationInvalidReason::CACHED_INVALID, error("%s: block %s is marked invalid", __func__, hash.ToString()), 0, "duplicate"); + return state.Invalid(ValidationInvalidReason::CACHED_INVALID, error("%s: block %s is marked invalid", __func__, hash.ToString()), "duplicate"); return true; } @@ -3562,10 +3558,10 @@ bool BlockManager::AcceptBlockHeader(const CBlockHeader& block, CValidationState CBlockIndex* pindexPrev = nullptr; BlockMap::iterator mi = m_block_index.find(block.hashPrevBlock); if (mi == m_block_index.end()) - return state.Invalid(ValidationInvalidReason::BLOCK_MISSING_PREV, error("%s: prev block not found", __func__), 0, "prev-blk-not-found"); + return state.Invalid(ValidationInvalidReason::BLOCK_MISSING_PREV, error("%s: prev block not found", __func__), "prev-blk-not-found"); pindexPrev = (*mi).second; if (pindexPrev->nStatus & BLOCK_FAILED_MASK) - return state.Invalid(ValidationInvalidReason::BLOCK_INVALID_PREV, error("%s: prev block invalid", __func__), REJECT_INVALID, "bad-prevblk"); + return state.Invalid(ValidationInvalidReason::BLOCK_INVALID_PREV, error("%s: prev block invalid", __func__), "bad-prevblk"); if (!ContextualCheckBlockHeader(block, state, chainparams, pindexPrev, GetAdjustedTime())) return error("%s: Consensus::ContextualCheckBlockHeader: %s, %s", __func__, hash.ToString(), FormatStateMessage(state)); @@ -3602,7 +3598,7 @@ bool BlockManager::AcceptBlockHeader(const CBlockHeader& block, CValidationState setDirtyBlockIndex.insert(invalid_walk); invalid_walk = invalid_walk->pprev; } - return state.Invalid(ValidationInvalidReason::BLOCK_INVALID_PREV, error("%s: prev block invalid", __func__), REJECT_INVALID, "bad-prevblk"); + return state.Invalid(ValidationInvalidReason::BLOCK_INVALID_PREV, error("%s: prev block invalid", __func__), "bad-prevblk"); } } } diff --git a/src/validation.h b/src/validation.h index fbbe3757e0..d17a320a47 100644 --- a/src/validation.h +++ b/src/validation.h @@ -24,12 +24,10 @@ #include <algorithm> #include <atomic> -#include <exception> #include <map> #include <memory> #include <set> #include <stdint.h> -#include <string> #include <utility> #include <vector> @@ -779,14 +777,6 @@ extern VersionBitsCache versionbitscache; */ int32_t ComputeBlockVersion(const CBlockIndex* pindexPrev, const Consensus::Params& params); -/** Reject codes greater or equal to this can be returned by AcceptToMemPool - * for transactions, to signal internal conditions. They cannot and should not - * be sent over the P2P network. - */ -static const unsigned int REJECT_INTERNAL = 0x100; -/** Too high fee. Can not be triggered by P2P transactions */ -static const unsigned int REJECT_HIGHFEE = 0x100; - /** Get block file info entry for one block file */ CBlockFileInfo* GetBlockFileInfo(size_t n); diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp index 59a620ab95..cf4a529a6d 100644 --- a/src/validationinterface.cpp +++ b/src/validationinterface.cpp @@ -9,8 +9,6 @@ #include <scheduler.h> #include <txmempool.h> -#include <list> -#include <atomic> #include <future> #include <utility> diff --git a/src/wallet/crypter.cpp b/src/wallet/crypter.cpp index 0b76c1a0eb..f6179aa298 100644 --- a/src/wallet/crypter.cpp +++ b/src/wallet/crypter.cpp @@ -6,11 +6,8 @@ #include <crypto/aes.h> #include <crypto/sha512.h> -#include <script/script.h> -#include <script/standard.h> #include <util/system.h> -#include <string> #include <vector> int CCrypter::BytesToKeySHA512AES(const std::vector<unsigned char>& chSalt, const SecureString& strKeyData, int count, unsigned char *key,unsigned char *iv) const diff --git a/src/wallet/crypter.h b/src/wallet/crypter.h index 17a4e9820c..4367a5047f 100644 --- a/src/wallet/crypter.h +++ b/src/wallet/crypter.h @@ -9,7 +9,6 @@ #include <support/allocators/secure.h> #include <script/signingprovider.h> -#include <atomic> const unsigned int WALLET_CRYPTO_KEY_SIZE = 32; const unsigned int WALLET_CRYPTO_SALT_SIZE = 8; diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp index 26aeb754ad..e48eee6c2c 100644 --- a/src/wallet/db.cpp +++ b/src/wallet/db.cpp @@ -412,7 +412,7 @@ bool BerkeleyBatch::VerifyEnvironment(const fs::path& file_path, std::string& er return true; } -bool BerkeleyBatch::VerifyDatabaseFile(const fs::path& file_path, std::string& warningStr, std::string& errorStr, BerkeleyEnvironment::recoverFunc_type recoverFunc) +bool BerkeleyBatch::VerifyDatabaseFile(const fs::path& file_path, std::vector<std::string>& warnings, std::string& errorStr, BerkeleyEnvironment::recoverFunc_type recoverFunc) { std::string walletFile; std::shared_ptr<BerkeleyEnvironment> env = GetWalletEnv(file_path, walletFile); @@ -424,11 +424,11 @@ bool BerkeleyBatch::VerifyDatabaseFile(const fs::path& file_path, std::string& w BerkeleyEnvironment::VerifyResult r = env->Verify(walletFile, recoverFunc, backup_filename); if (r == BerkeleyEnvironment::VerifyResult::RECOVER_OK) { - warningStr = strprintf(_("Warning: Wallet file corrupt, data salvaged!" + warnings.push_back(strprintf(_("Warning: Wallet file corrupt, data salvaged!" " Original %s saved as %s in %s; if" " your balance or transactions are incorrect you should" " restore from a backup.").translated, - walletFile, backup_filename, walletDir); + walletFile, backup_filename, walletDir)); } if (r == BerkeleyEnvironment::VerifyResult::RECOVER_FAIL) { diff --git a/src/wallet/db.h b/src/wallet/db.h index 94f41eaf16..abec3ae4e2 100644 --- a/src/wallet/db.h +++ b/src/wallet/db.h @@ -10,9 +10,7 @@ #include <fs.h> #include <serialize.h> #include <streams.h> -#include <sync.h> #include <util/system.h> -#include <version.h> #include <atomic> #include <map> @@ -246,7 +244,7 @@ public: /* verifies the database environment */ static bool VerifyEnvironment(const fs::path& file_path, std::string& errorStr); /* verifies the database file */ - static bool VerifyDatabaseFile(const fs::path& file_path, std::string& warningStr, std::string& errorStr, BerkeleyEnvironment::recoverFunc_type recoverFunc); + static bool VerifyDatabaseFile(const fs::path& file_path, std::vector<std::string>& warnings, std::string& errorStr, BerkeleyEnvironment::recoverFunc_type recoverFunc); template <typename K, typename T> bool Read(const K& key, T& value) diff --git a/src/wallet/feebumper.cpp b/src/wallet/feebumper.cpp index b87231293f..0a4bb3f396 100644 --- a/src/wallet/feebumper.cpp +++ b/src/wallet/feebumper.cpp @@ -2,7 +2,6 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include <consensus/validation.h> #include <interfaces/chain.h> #include <wallet/coincontrol.h> #include <wallet/feebumper.h> @@ -17,15 +16,15 @@ //! Check whether transaction has descendant in wallet or mempool, or has been //! mined, or conflicts with a mined transaction. Return a feebumper::Result. -static feebumper::Result PreconditionChecks(interfaces::Chain::Lock& locked_chain, const CWallet* wallet, const CWalletTx& wtx, std::vector<std::string>& errors) EXCLUSIVE_LOCKS_REQUIRED(wallet->cs_wallet) +static feebumper::Result PreconditionChecks(interfaces::Chain::Lock& locked_chain, const CWallet& wallet, const CWalletTx& wtx, std::vector<std::string>& errors) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet) { - if (wallet->HasWalletSpend(wtx.GetHash())) { + if (wallet.HasWalletSpend(wtx.GetHash())) { errors.push_back("Transaction has descendants in the wallet"); return feebumper::Result::INVALID_PARAMETER; } { - if (wallet->chain().hasDescendantsInMempool(wtx.GetHash())) { + if (wallet.chain().hasDescendantsInMempool(wtx.GetHash())) { errors.push_back("Transaction has descendants in the mempool"); return feebumper::Result::INVALID_PARAMETER; } @@ -48,7 +47,7 @@ static feebumper::Result PreconditionChecks(interfaces::Chain::Lock& locked_chai // check that original tx consists entirely of our inputs // if not, we can't bump the fee, because the wallet has no way of knowing the value of the other inputs (thus the fee) - if (!wallet->IsAllFromMe(*wtx.tx, ISMINE_SPENDABLE)) { + if (!wallet.IsAllFromMe(*wtx.tx, ISMINE_SPENDABLE)) { errors.push_back("Transaction contains inputs that don't belong to this wallet"); return feebumper::Result::WALLET_ERROR; } @@ -58,13 +57,13 @@ static feebumper::Result PreconditionChecks(interfaces::Chain::Lock& locked_chai } //! Check if the user provided a valid feeRate -static feebumper::Result CheckFeeRate(const CWallet* wallet, const CWalletTx& wtx, const CFeeRate& newFeerate, const int64_t maxTxSize, std::vector<std::string>& errors) { +static feebumper::Result CheckFeeRate(const CWallet& wallet, const CWalletTx& wtx, const CFeeRate& newFeerate, const int64_t maxTxSize, std::vector<std::string>& errors) { // check that fee rate is higher than mempool's minimum fee // (no point in bumping fee if we know that the new tx won't be accepted to the mempool) // This may occur if the user set FeeRate, TotalFee or paytxfee too low, if fallbackfee is too low, or, perhaps, // in a rare situation where the mempool minimum fee increased significantly since the fee estimation just a // moment earlier. In this case, we report an error to the user, who may adjust the fee. - CFeeRate minMempoolFeeRate = wallet->chain().mempoolMinFee(); + CFeeRate minMempoolFeeRate = wallet.chain().mempoolMinFee(); if (newFeerate.GetFeePerK() < minMempoolFeeRate.GetFeePerK()) { errors.push_back(strprintf( @@ -76,7 +75,7 @@ static feebumper::Result CheckFeeRate(const CWallet* wallet, const CWalletTx& wt CAmount new_total_fee = newFeerate.GetFee(maxTxSize); - CFeeRate incrementalRelayFee = std::max(wallet->chain().relayIncrementalFee(), CFeeRate(WALLET_INCREMENTAL_RELAY_FEE)); + CFeeRate incrementalRelayFee = std::max(wallet.chain().relayIncrementalFee(), CFeeRate(WALLET_INCREMENTAL_RELAY_FEE)); // Given old total fee and transaction size, calculate the old feeRate CAmount old_fee = wtx.GetDebit(ISMINE_SPENDABLE) - wtx.tx->GetValueOut(); @@ -91,7 +90,7 @@ static feebumper::Result CheckFeeRate(const CWallet* wallet, const CWalletTx& wt return feebumper::Result::INVALID_PARAMETER; } - CAmount requiredFee = GetRequiredFee(*wallet, maxTxSize); + CAmount requiredFee = GetRequiredFee(wallet, maxTxSize); if (new_total_fee < requiredFee) { errors.push_back(strprintf("Insufficient total fee (cannot be less than required fee %s)", FormatMoney(requiredFee))); @@ -99,7 +98,7 @@ static feebumper::Result CheckFeeRate(const CWallet* wallet, const CWalletTx& wt } // Check that in all cases the new fee doesn't violate maxTxFee - const CAmount max_tx_fee = wallet->m_default_max_tx_fee; + const CAmount max_tx_fee = wallet.m_default_max_tx_fee; if (new_total_fee > max_tx_fee) { errors.push_back(strprintf("Specified or calculated fee %s is too high (cannot be higher than -maxtxfee %s)", FormatMoney(new_total_fee), FormatMoney(max_tx_fee))); @@ -109,7 +108,7 @@ static feebumper::Result CheckFeeRate(const CWallet* wallet, const CWalletTx& wt return feebumper::Result::OK; } -static CFeeRate EstimateFeeRate(CWallet* wallet, const CWalletTx& wtx, CCoinControl& coin_control, CAmount& old_fee) +static CFeeRate EstimateFeeRate(const CWallet& wallet, const CWalletTx& wtx, CCoinControl& coin_control, CAmount& old_fee) { // Get the fee rate of the original transaction. This is calculated from // the tx fee/vsize, so it may have been rounded down. Add 1 satoshi to the @@ -123,15 +122,15 @@ static CFeeRate EstimateFeeRate(CWallet* wallet, const CWalletTx& wtx, CCoinCont // the minimum of that and the wallet's conservative // WALLET_INCREMENTAL_RELAY_FEE value to future proof against changes to // network wide policy for incremental relay fee that our node may not be - // aware of. This ensures we're over the over the required relay fee rate + // aware of. This ensures we're over the required relay fee rate // (BIP 125 rule 4). The replacement tx will be at least as large as the // original tx, so the total fee will be greater (BIP 125 rule 3) - CFeeRate node_incremental_relay_fee = wallet->chain().relayIncrementalFee(); + CFeeRate node_incremental_relay_fee = wallet.chain().relayIncrementalFee(); CFeeRate wallet_incremental_relay_fee = CFeeRate(WALLET_INCREMENTAL_RELAY_FEE); feerate += std::max(node_incremental_relay_fee, wallet_incremental_relay_fee); // Fee rate must also be at least the wallet's GetMinimumFeeRate - CFeeRate min_feerate(GetMinimumFeeRate(*wallet, coin_control, /* feeCalc */ nullptr)); + CFeeRate min_feerate(GetMinimumFeeRate(wallet, coin_control, /* feeCalc */ nullptr)); // Set the required fee rate for the replacement transaction in coin control. return std::max(feerate, min_feerate); @@ -139,11 +138,11 @@ static CFeeRate EstimateFeeRate(CWallet* wallet, const CWalletTx& wtx, CCoinCont namespace feebumper { -bool TransactionCanBeBumped(const CWallet* wallet, const uint256& txid) +bool TransactionCanBeBumped(const CWallet& wallet, const uint256& txid) { - auto locked_chain = wallet->chain().lock(); - LOCK(wallet->cs_wallet); - const CWalletTx* wtx = wallet->GetWalletTx(txid); + auto locked_chain = wallet.chain().lock(); + LOCK(wallet.cs_wallet); + const CWalletTx* wtx = wallet.GetWalletTx(txid); if (wtx == nullptr) return false; std::vector<std::string> errors_dummy; @@ -166,7 +165,7 @@ Result CreateTotalBumpTransaction(const CWallet* wallet, const uint256& txid, co } const CWalletTx& wtx = it->second; - Result result = PreconditionChecks(*locked_chain, wallet, wtx, errors); + Result result = PreconditionChecks(*locked_chain, *wallet, wtx, errors); if (result != Result::OK) { return result; } @@ -276,17 +275,17 @@ Result CreateTotalBumpTransaction(const CWallet* wallet, const uint256& txid, co } -Result CreateRateBumpTransaction(CWallet* wallet, const uint256& txid, const CCoinControl& coin_control, std::vector<std::string>& errors, +Result CreateRateBumpTransaction(CWallet& wallet, const uint256& txid, const CCoinControl& coin_control, std::vector<std::string>& errors, CAmount& old_fee, CAmount& new_fee, CMutableTransaction& mtx) { // We are going to modify coin control later, copy to re-use CCoinControl new_coin_control(coin_control); - auto locked_chain = wallet->chain().lock(); - LOCK(wallet->cs_wallet); + auto locked_chain = wallet.chain().lock(); + LOCK(wallet.cs_wallet); errors.clear(); - auto it = wallet->mapWallet.find(txid); - if (it == wallet->mapWallet.end()) { + auto it = wallet.mapWallet.find(txid); + if (it == wallet.mapWallet.end()) { errors.push_back("Invalid or non-wallet transaction id"); return Result::INVALID_ADDRESS_OR_KEY; } @@ -300,7 +299,7 @@ Result CreateRateBumpTransaction(CWallet* wallet, const uint256& txid, const CCo // Fill in recipients(and preserve a single change key if there is one) std::vector<CRecipient> recipients; for (const auto& output : wtx.tx->vout) { - if (!wallet->IsChange(output)) { + if (!wallet.IsChange(output)) { CRecipient recipient = {output.scriptPubKey, output.nValue, false}; recipients.push_back(recipient); } else { @@ -313,8 +312,8 @@ Result CreateRateBumpTransaction(CWallet* wallet, const uint256& txid, const CCo if (coin_control.m_feerate) { // The user provided a feeRate argument. // We calculate this here to avoid compiler warning on the cs_wallet lock - const int64_t maxTxSize = CalculateMaximumSignedTxSize(*wtx.tx, wallet); - Result res = CheckFeeRate(wallet, wtx, *(new_coin_control.m_feerate), maxTxSize, errors); + const int64_t maxTxSize = CalculateMaximumSignedTxSize(*wtx.tx, &wallet); + Result res = CheckFeeRate(wallet, wtx, *new_coin_control.m_feerate, maxTxSize, errors); if (res != Result::OK) { return res; } @@ -342,7 +341,7 @@ Result CreateRateBumpTransaction(CWallet* wallet, const uint256& txid, const CCo CAmount fee_ret; int change_pos_in_out = -1; // No requested location for change std::string fail_reason; - if (!wallet->CreateTransaction(*locked_chain, recipients, tx_new, fee_ret, change_pos_in_out, fail_reason, new_coin_control, false)) { + if (!wallet.CreateTransaction(*locked_chain, recipients, tx_new, fee_ret, change_pos_in_out, fail_reason, new_coin_control, false)) { errors.push_back("Unable to create transaction: " + fail_reason); return Result::WALLET_ERROR; } @@ -353,7 +352,7 @@ Result CreateRateBumpTransaction(CWallet* wallet, const uint256& txid, const CCo // Write back transaction mtx = CMutableTransaction(*tx_new); // Mark new tx not replaceable, if requested. - if (!coin_control.m_signal_bip125_rbf.get_value_or(wallet->m_signal_rbf)) { + if (!coin_control.m_signal_bip125_rbf.get_value_or(wallet.m_signal_rbf)) { for (auto& input : mtx.vin) { if (input.nSequence < 0xfffffffe) input.nSequence = 0xfffffffe; } @@ -362,21 +361,21 @@ Result CreateRateBumpTransaction(CWallet* wallet, const uint256& txid, const CCo return Result::OK; } -bool SignTransaction(CWallet* wallet, CMutableTransaction& mtx) { - auto locked_chain = wallet->chain().lock(); - LOCK(wallet->cs_wallet); - return wallet->SignTransaction(mtx); +bool SignTransaction(CWallet& wallet, CMutableTransaction& mtx) { + auto locked_chain = wallet.chain().lock(); + LOCK(wallet.cs_wallet); + return wallet.SignTransaction(mtx); } -Result CommitTransaction(CWallet* wallet, const uint256& txid, CMutableTransaction&& mtx, std::vector<std::string>& errors, uint256& bumped_txid) +Result CommitTransaction(CWallet& wallet, const uint256& txid, CMutableTransaction&& mtx, std::vector<std::string>& errors, uint256& bumped_txid) { - auto locked_chain = wallet->chain().lock(); - LOCK(wallet->cs_wallet); + auto locked_chain = wallet.chain().lock(); + LOCK(wallet.cs_wallet); if (!errors.empty()) { return Result::MISC_ERROR; } - auto it = txid.IsNull() ? wallet->mapWallet.end() : wallet->mapWallet.find(txid); - if (it == wallet->mapWallet.end()) { + auto it = txid.IsNull() ? wallet.mapWallet.end() : wallet.mapWallet.find(txid); + if (it == wallet.mapWallet.end()) { errors.push_back("Invalid or non-wallet transaction id"); return Result::MISC_ERROR; } @@ -393,22 +392,11 @@ Result CommitTransaction(CWallet* wallet, const uint256& txid, CMutableTransacti mapValue_t mapValue = oldWtx.mapValue; mapValue["replaces_txid"] = oldWtx.GetHash().ToString(); - CValidationState state; - if (!wallet->CommitTransaction(tx, std::move(mapValue), oldWtx.vOrderForm, state)) { - // NOTE: CommitTransaction never returns false, so this should never happen. - errors.push_back(strprintf("The transaction was rejected: %s", FormatStateMessage(state))); - return Result::WALLET_ERROR; - } - - bumped_txid = tx->GetHash(); - if (state.IsInvalid()) { - // This can happen if the mempool rejected the transaction. Report - // what happened in the "errors" response. - errors.push_back(strprintf("Error: The transaction was rejected: %s", FormatStateMessage(state))); - } + wallet.CommitTransaction(tx, std::move(mapValue), oldWtx.vOrderForm); // mark the original tx as bumped - if (!wallet->MarkReplaced(oldWtx.GetHash(), bumped_txid)) { + bumped_txid = tx->GetHash(); + if (!wallet.MarkReplaced(oldWtx.GetHash(), bumped_txid)) { // TODO: see if JSON-RPC has a standard way of returning a response // along with an exception. It would be good to return information about // wtxBumped to the caller even if marking the original transaction diff --git a/src/wallet/feebumper.h b/src/wallet/feebumper.h index 0c4e1cb7dd..9357397606 100644 --- a/src/wallet/feebumper.h +++ b/src/wallet/feebumper.h @@ -26,7 +26,7 @@ enum class Result }; //! Return whether transaction can be bumped. -bool TransactionCanBeBumped(const CWallet* wallet, const uint256& txid); +bool TransactionCanBeBumped(const CWallet& wallet, const uint256& txid); //! Create bumpfee transaction based on total amount. Result CreateTotalBumpTransaction(const CWallet* wallet, @@ -39,7 +39,7 @@ Result CreateTotalBumpTransaction(const CWallet* wallet, CMutableTransaction& mtx); //! Create bumpfee transaction based on feerate estimates. -Result CreateRateBumpTransaction(CWallet* wallet, +Result CreateRateBumpTransaction(CWallet& wallet, const uint256& txid, const CCoinControl& coin_control, std::vector<std::string>& errors, @@ -50,13 +50,13 @@ Result CreateRateBumpTransaction(CWallet* wallet, //! Sign the new transaction, //! @return false if the tx couldn't be found or if it was //! impossible to create the signature(s) -bool SignTransaction(CWallet* wallet, CMutableTransaction& mtx); +bool SignTransaction(CWallet& wallet, CMutableTransaction& mtx); //! Commit the bumpfee transaction. //! @return success in case of CWallet::CommitTransaction was successful, //! but sets errors if the tx could not be added to the mempool (will try later) //! or if the old transaction could not be marked as replaced. -Result CommitTransaction(CWallet* wallet, +Result CommitTransaction(CWallet& wallet, const uint256& txid, CMutableTransaction&& mtx, std::vector<std::string>& errors, diff --git a/src/wallet/fees.cpp b/src/wallet/fees.cpp index 2792058f2a..249bc833c6 100644 --- a/src/wallet/fees.cpp +++ b/src/wallet/fees.cpp @@ -5,7 +5,6 @@ #include <wallet/fees.h> -#include <util/system.h> #include <wallet/coincontrol.h> #include <wallet/wallet.h> diff --git a/src/wallet/init.cpp b/src/wallet/init.cpp index 43b6ead028..3657a157b6 100644 --- a/src/wallet/init.cpp +++ b/src/wallet/init.cpp @@ -11,7 +11,6 @@ #include <util/system.h> #include <util/translation.h> #include <wallet/wallet.h> -#include <wallet/walletutil.h> #include <walletinitinterface.h> class WalletInit : public WalletInitInterface { @@ -122,8 +121,6 @@ bool WalletInit::ParameterInteraction() const if (gArgs.GetBoolArg("-sysperms", false)) return InitError("-sysperms is not allowed in combination with enabled wallet functionality"); - if (gArgs.GetArg("-prune", 0) && gArgs.GetBoolArg("-rescan", false)) - return InitError(_("Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again.").translated); return true; } diff --git a/src/wallet/ismine.cpp b/src/wallet/ismine.cpp index b7ef2d4490..029b922785 100644 --- a/src/wallet/ismine.cpp +++ b/src/wallet/ismine.cpp @@ -7,7 +7,6 @@ #include <key.h> #include <script/script.h> -#include <script/sign.h> #include <script/signingprovider.h> #include <wallet/wallet.h> diff --git a/src/wallet/load.cpp b/src/wallet/load.cpp index b5d3b8c305..071befaebf 100644 --- a/src/wallet/load.cpp +++ b/src/wallet/load.cpp @@ -7,6 +7,7 @@ #include <interfaces/chain.h> #include <scheduler.h> +#include <util/string.h> #include <util/system.h> #include <util/translation.h> #include <wallet/wallet.h> @@ -53,10 +54,10 @@ bool VerifyWallets(interfaces::Chain& chain, const std::vector<std::string>& wal } std::string error_string; - std::string warning_string; - bool verify_success = CWallet::Verify(chain, location, salvage_wallet, error_string, warning_string); + std::vector<std::string> warnings; + bool verify_success = CWallet::Verify(chain, location, salvage_wallet, error_string, warnings); if (!error_string.empty()) chain.initError(error_string); - if (!warning_string.empty()) chain.initWarning(warning_string); + if (!warnings.empty()) chain.initWarning(Join(warnings, "\n")); if (!verify_success) return false; } @@ -66,8 +67,12 @@ bool VerifyWallets(interfaces::Chain& chain, const std::vector<std::string>& wal bool LoadWallets(interfaces::Chain& chain, const std::vector<std::string>& wallet_files) { for (const std::string& walletFile : wallet_files) { - std::shared_ptr<CWallet> pwallet = CWallet::CreateWalletFromFile(chain, WalletLocation(walletFile)); + std::string error; + std::vector<std::string> warnings; + std::shared_ptr<CWallet> pwallet = CWallet::CreateWalletFromFile(chain, WalletLocation(walletFile), error, warnings); + if (!warnings.empty()) chain.initWarning(Join(warnings, "\n")); if (!pwallet) { + chain.initError(error); return false; } AddWallet(pwallet); diff --git a/src/wallet/psbtwallet.h b/src/wallet/psbtwallet.h index a24a0967d2..a7e52df6d9 100644 --- a/src/wallet/psbtwallet.h +++ b/src/wallet/psbtwallet.h @@ -5,9 +5,7 @@ #ifndef BITCOIN_WALLET_PSBTWALLET_H #define BITCOIN_WALLET_PSBTWALLET_H -#include <node/transaction.h> #include <psbt.h> -#include <primitives/transaction.h> #include <wallet/wallet.h> /** diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index f52e4318c8..1cd4cb93b4 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -7,7 +7,6 @@ #include <interfaces/chain.h> #include <key_io.h> #include <merkleblock.h> -#include <rpc/server.h> #include <rpc/util.h> #include <script/descriptor.h> #include <script/script.h> diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index dc437e5cd8..e571501221 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -4,12 +4,10 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <amount.h> -#include <consensus/validation.h> #include <core_io.h> #include <init.h> #include <interfaces/chain.h> #include <key_io.h> -#include <node/transaction.h> #include <outputtype.h> #include <policy/feerate.h> #include <policy/fees.h> @@ -22,6 +20,7 @@ #include <util/bip32.h> #include <util/fees.h> #include <util/moneystr.h> +#include <util/string.h> #include <util/system.h> #include <util/url.h> #include <util/validation.h> @@ -37,7 +36,6 @@ #include <univalue.h> -#include <functional> static const std::string WALLET_ENDPOINT_BASE = "/wallet/"; @@ -342,11 +340,7 @@ static CTransactionRef SendMoney(interfaces::Chain::Lock& locked_chain, CWallet strError = strprintf("Error: This transaction requires a transaction fee of at least %s", FormatMoney(nFeeRequired)); throw JSONRPCError(RPC_WALLET_ERROR, strError); } - CValidationState state; - if (!pwallet->CommitTransaction(tx, std::move(mapValue), {} /* orderForm */, state)) { - strError = strprintf("Error: The transaction was rejected! Reason given: %s", FormatStateMessage(state)); - throw JSONRPCError(RPC_WALLET_ERROR, strError); - } + pwallet->CommitTransaction(tx, std::move(mapValue), {} /* orderForm */); return tx; } @@ -927,12 +921,7 @@ static UniValue sendmany(const JSONRPCRequest& request) bool fCreated = pwallet->CreateTransaction(*locked_chain, vecSend, tx, nFeeRequired, nChangePosRet, strFailReason, coin_control); if (!fCreated) throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, strFailReason); - CValidationState state; - if (!pwallet->CommitTransaction(tx, std::move(mapValue), {} /* orderForm */, state)) { - strFailReason = strprintf("Transaction commit failed:: %s", FormatStateMessage(state)); - throw JSONRPCError(RPC_WALLET_ERROR, strFailReason); - } - + pwallet->CommitTransaction(tx, std::move(mapValue), {} /* orderForm */); return tx->GetHash().GetHex(); } @@ -2583,13 +2572,14 @@ static UniValue loadwallet(const JSONRPCRequest& request) } } - std::string error, warning; + std::string error; + std::vector<std::string> warning; std::shared_ptr<CWallet> const wallet = LoadWallet(*g_rpc_interfaces->chain, location, error, warning); if (!wallet) throw JSONRPCError(RPC_WALLET_ERROR, error); UniValue obj(UniValue::VOBJ); obj.pushKV("name", wallet->GetName()); - obj.pushKV("warning", warning); + obj.pushKV("warning", Join(warning, "\n")); return obj; } @@ -2695,12 +2685,12 @@ static UniValue createwallet(const JSONRPCRequest& request) } SecureString passphrase; passphrase.reserve(100); - std::string warning; + std::vector<std::string> warnings; if (!request.params[3].isNull()) { passphrase = request.params[3].get_str().c_str(); if (passphrase.empty()) { // Empty string means unencrypted - warning = "Empty string given as passphrase, wallet will not be encrypted."; + warnings.emplace_back("Empty string given as passphrase, wallet will not be encrypted."); } } @@ -2709,9 +2699,8 @@ static UniValue createwallet(const JSONRPCRequest& request) } std::string error; - std::string create_warning; std::shared_ptr<CWallet> wallet; - WalletCreationStatus status = CreateWallet(*g_rpc_interfaces->chain, passphrase, flags, request.params[0].get_str(), error, create_warning, wallet); + WalletCreationStatus status = CreateWallet(*g_rpc_interfaces->chain, passphrase, flags, request.params[0].get_str(), error, warnings, wallet); switch (status) { case WalletCreationStatus::CREATION_FAILED: throw JSONRPCError(RPC_WALLET_ERROR, error); @@ -2722,15 +2711,9 @@ static UniValue createwallet(const JSONRPCRequest& request) // no default case, so the compiler can warn about missing cases } - if (warning.empty()) { - warning = create_warning; - } else if (!warning.empty() && !create_warning.empty()){ - warning += "; " + create_warning; - } - UniValue obj(UniValue::VOBJ); obj.pushKV("name", wallet->GetName()); - obj.pushKV("warning", warning); + obj.pushKV("warning", Join(warnings, "\n")); return obj; } @@ -3417,7 +3400,7 @@ static UniValue bumpfee(const JSONRPCRequest& request) res = feebumper::CreateTotalBumpTransaction(pwallet, hash, coin_control, totalFee, errors, old_fee, new_fee, mtx); } else { // Targeting feerate bump. - res = feebumper::CreateRateBumpTransaction(pwallet, hash, coin_control, errors, old_fee, new_fee, mtx); + res = feebumper::CreateRateBumpTransaction(*pwallet, hash, coin_control, errors, old_fee, new_fee, mtx); } if (res != feebumper::Result::OK) { switch(res) { @@ -3440,12 +3423,12 @@ static UniValue bumpfee(const JSONRPCRequest& request) } // sign bumped transaction - if (!feebumper::SignTransaction(pwallet, mtx)) { + if (!feebumper::SignTransaction(*pwallet, mtx)) { throw JSONRPCError(RPC_WALLET_ERROR, "Can't sign transaction."); } // commit the bumped transaction uint256 txid; - if (feebumper::CommitTransaction(pwallet, hash, std::move(mtx), errors, txid) != feebumper::Result::OK) { + if (feebumper::CommitTransaction(*pwallet, hash, std::move(mtx), errors, txid) != feebumper::Result::OK) { throw JSONRPCError(RPC_WALLET_ERROR, errors[0]); } UniValue result(UniValue::VOBJ); diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp index 73523ca36d..a2b2a7b227 100644 --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -8,7 +8,6 @@ #include <stdint.h> #include <vector> -#include <consensus/validation.h> #include <interfaces/chain.h> #include <policy/policy.h> #include <rpc/server.h> @@ -451,8 +450,7 @@ public: auto locked_chain = m_chain->lock(); BOOST_CHECK(wallet->CreateTransaction(*locked_chain, {recipient}, tx, fee, changePos, error, dummy)); } - CValidationState state; - BOOST_CHECK(wallet->CommitTransaction(tx, {}, {}, state)); + wallet->CommitTransaction(tx, {}, {}); CMutableTransaction blocktx; { LOCK(wallet->cs_wallet); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 09f08220db..159d4f78c6 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -27,13 +27,11 @@ #include <util/rbf.h> #include <util/translation.h> #include <util/validation.h> -#include <validation.h> #include <wallet/coincontrol.h> #include <wallet/fees.h> #include <algorithm> #include <assert.h> -#include <future> #include <boost/algorithm/string/replace.hpp> @@ -140,16 +138,16 @@ void UnloadWallet(std::shared_ptr<CWallet>&& wallet) } } -std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const WalletLocation& location, std::string& error, std::string& warning) +std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const WalletLocation& location, std::string& error, std::vector<std::string>& warnings) { - if (!CWallet::Verify(chain, location, false, error, warning)) { + if (!CWallet::Verify(chain, location, false, error, warnings)) { error = "Wallet file verification failed: " + error; return nullptr; } - std::shared_ptr<CWallet> wallet = CWallet::CreateWalletFromFile(chain, location); + std::shared_ptr<CWallet> wallet = CWallet::CreateWalletFromFile(chain, location, error, warnings); if (!wallet) { - error = "Wallet loading failed."; + error = "Wallet loading failed: " + error; return nullptr; } AddWallet(wallet); @@ -157,12 +155,12 @@ std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const WalletLocati return wallet; } -std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const std::string& name, std::string& error, std::string& warning) +std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const std::string& name, std::string& error, std::vector<std::string>& warnings) { - return LoadWallet(chain, WalletLocation(name), error, warning); + return LoadWallet(chain, WalletLocation(name), error, warnings); } -WalletCreationStatus CreateWallet(interfaces::Chain& chain, const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, std::string& error, std::string& warning, std::shared_ptr<CWallet>& result) +WalletCreationStatus CreateWallet(interfaces::Chain& chain, const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, std::string& error, std::vector<std::string>& warnings, std::shared_ptr<CWallet>& result) { // Indicate that the wallet is actually supposed to be blank and not just blank to make it encrypted bool create_blank = (wallet_creation_flags & WALLET_FLAG_BLANK_WALLET); @@ -180,9 +178,8 @@ WalletCreationStatus CreateWallet(interfaces::Chain& chain, const SecureString& } // Wallet::Verify will check if we're trying to create a wallet with a duplicate name. - std::string wallet_error; - if (!CWallet::Verify(chain, location, false, wallet_error, warning)) { - error = "Wallet file verification failed: " + wallet_error; + if (!CWallet::Verify(chain, location, false, error, warnings)) { + error = "Wallet file verification failed: " + error; return WalletCreationStatus::CREATION_FAILED; } @@ -193,9 +190,9 @@ WalletCreationStatus CreateWallet(interfaces::Chain& chain, const SecureString& } // Make the wallet - std::shared_ptr<CWallet> wallet = CWallet::CreateWalletFromFile(chain, location, wallet_creation_flags); + std::shared_ptr<CWallet> wallet = CWallet::CreateWalletFromFile(chain, location, error, warnings, wallet_creation_flags); if (!wallet) { - error = "Wallet creation failed"; + error = "Wallet creation failed: " + error; return WalletCreationStatus::CREATION_FAILED; } @@ -2739,8 +2736,11 @@ bool CWallet::SelectCoins(const std::vector<COutput>& vAvailableCoins, const CAm } std::vector<OutputGroup> groups = GroupOutputs(vCoins, !coin_control.m_avoid_partial_spends); - size_t max_ancestors = (size_t)std::max<int64_t>(1, gArgs.GetArg("-limitancestorcount", DEFAULT_ANCESTOR_LIMIT)); - size_t max_descendants = (size_t)std::max<int64_t>(1, gArgs.GetArg("-limitdescendantcount", DEFAULT_DESCENDANT_LIMIT)); + unsigned int limit_ancestor_count; + unsigned int limit_descendant_count; + chain().getPackageLimits(limit_ancestor_count, limit_descendant_count); + size_t max_ancestors = (size_t)std::max<int64_t>(1, limit_ancestor_count); + size_t max_descendants = (size_t)std::max<int64_t>(1, limit_descendant_count); bool fRejectLongChains = gArgs.GetBoolArg("-walletrejectlongchains", DEFAULT_WALLET_REJECT_LONG_CHAINS); bool res = nTargetValue <= nValueFromPresetInputs || @@ -3284,51 +3284,44 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std return true; } -/** - * Call after CreateTransaction unless you want to abort - */ -bool CWallet::CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::vector<std::pair<std::string, std::string>> orderForm, CValidationState& state) +void CWallet::CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::vector<std::pair<std::string, std::string>> orderForm) { - { - auto locked_chain = chain().lock(); - LOCK(cs_wallet); + auto locked_chain = chain().lock(); + LOCK(cs_wallet); - CWalletTx wtxNew(this, std::move(tx)); - wtxNew.mapValue = std::move(mapValue); - wtxNew.vOrderForm = std::move(orderForm); - wtxNew.fTimeReceivedIsTxTime = true; - wtxNew.fFromMe = true; + CWalletTx wtxNew(this, std::move(tx)); + wtxNew.mapValue = std::move(mapValue); + wtxNew.vOrderForm = std::move(orderForm); + wtxNew.fTimeReceivedIsTxTime = true; + wtxNew.fFromMe = true; - WalletLogPrintf("CommitTransaction:\n%s", wtxNew.tx->ToString()); /* Continued */ - { + WalletLogPrintf("CommitTransaction:\n%s", wtxNew.tx->ToString()); /* Continued */ - // Add tx to wallet, because if it has change it's also ours, - // otherwise just for transaction history. - AddToWallet(wtxNew); + // Add tx to wallet, because if it has change it's also ours, + // otherwise just for transaction history. + AddToWallet(wtxNew); - // Notify that old coins are spent - for (const CTxIn& txin : wtxNew.tx->vin) - { - CWalletTx &coin = mapWallet.at(txin.prevout.hash); - coin.BindWallet(this); - NotifyTransactionChanged(this, coin.GetHash(), CT_UPDATED); - } - } + // Notify that old coins are spent + for (const CTxIn& txin : wtxNew.tx->vin) { + CWalletTx &coin = mapWallet.at(txin.prevout.hash); + coin.BindWallet(this); + NotifyTransactionChanged(this, coin.GetHash(), CT_UPDATED); + } - // Get the inserted-CWalletTx from mapWallet so that the - // fInMempool flag is cached properly - CWalletTx& wtx = mapWallet.at(wtxNew.GetHash()); + // Get the inserted-CWalletTx from mapWallet so that the + // fInMempool flag is cached properly + CWalletTx& wtx = mapWallet.at(wtxNew.GetHash()); - if (fBroadcastTransactions) - { - std::string err_string; - if (!wtx.SubmitMemoryPoolAndRelay(err_string, true, *locked_chain)) { - WalletLogPrintf("CommitTransaction(): Transaction cannot be broadcast immediately, %s\n", err_string); - // TODO: if we expect the failure to be long term or permanent, instead delete wtx from the wallet and return failure. - } - } + if (!fBroadcastTransactions) { + // Don't submit tx to the mempool + return; + } + + std::string err_string; + if (!wtx.SubmitMemoryPoolAndRelay(err_string, true, *locked_chain)) { + WalletLogPrintf("CommitTransaction(): Transaction cannot be broadcast immediately, %s\n", err_string); + // TODO: if we expect the failure to be long term or permanent, instead delete wtx from the wallet and return failure. } - return true; } DBErrors CWallet::LoadWallet(bool& fFirstRunRet) @@ -3467,21 +3460,6 @@ bool CWallet::DelAddressBook(const CTxDestination& address) return WalletBatch(*database).EraseName(EncodeDestination(address)); } -const std::string& CWallet::GetLabelName(const CScript& scriptPubKey) const -{ - CTxDestination address; - if (ExtractDestination(scriptPubKey, address) && !scriptPubKey.IsUnspendable()) { - auto mi = mapAddressBook.find(address); - if (mi != mapAddressBook.end()) { - return mi->second.name; - } - } - // A scriptPubKey that doesn't have an entry in the address book is - // associated with the default label (""). - const static std::string DEFAULT_LABEL_NAME; - return DEFAULT_LABEL_NAME; -} - /** * Mark old keypool keys as used, * and generate all new keys @@ -4196,7 +4174,7 @@ void CWallet::MarkPreSplitKeys() } } -bool CWallet::Verify(interfaces::Chain& chain, const WalletLocation& location, bool salvage_wallet, std::string& error_string, std::string& warning_string) +bool CWallet::Verify(interfaces::Chain& chain, const WalletLocation& location, bool salvage_wallet, std::string& error_string, std::vector<std::string>& warnings) { // Do some checking on wallet path. It should be either a: // @@ -4250,10 +4228,10 @@ bool CWallet::Verify(interfaces::Chain& chain, const WalletLocation& location, b } } - return WalletBatch::VerifyDatabaseFile(wallet_path, warning_string, error_string); + return WalletBatch::VerifyDatabaseFile(wallet_path, warnings, error_string); } -std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain, const WalletLocation& location, uint64_t wallet_creation_flags) +std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain, const WalletLocation& location, std::string& error, std::vector<std::string>& warnings, uint64_t wallet_creation_flags) { const std::string walletFile = WalletDataFilePath(location.GetPath()).string(); @@ -4266,7 +4244,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain, std::unique_ptr<CWallet> tempWallet = MakeUnique<CWallet>(&chain, location, WalletDatabase::Create(location.GetPath())); DBErrors nZapWalletRet = tempWallet->ZapWalletTx(vWtx); if (nZapWalletRet != DBErrors::LOAD_OK) { - chain.initError(strprintf(_("Error loading %s: Wallet corrupted").translated, walletFile)); + error = strprintf(_("Error loading %s: Wallet corrupted").translated, walletFile); return nullptr; } } @@ -4279,29 +4257,28 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain, // should be possible to use std::allocate_shared. std::shared_ptr<CWallet> walletInstance(new CWallet(&chain, location, WalletDatabase::Create(location.GetPath())), ReleaseWallet); DBErrors nLoadWalletRet = walletInstance->LoadWallet(fFirstRun); - if (nLoadWalletRet != DBErrors::LOAD_OK) - { + if (nLoadWalletRet != DBErrors::LOAD_OK) { if (nLoadWalletRet == DBErrors::CORRUPT) { - chain.initError(strprintf(_("Error loading %s: Wallet corrupted").translated, walletFile)); + error = strprintf(_("Error loading %s: Wallet corrupted").translated, walletFile); return nullptr; } else if (nLoadWalletRet == DBErrors::NONCRITICAL_ERROR) { - chain.initWarning(strprintf(_("Error reading %s! All keys read correctly, but transaction data" + warnings.push_back(strprintf(_("Error reading %s! All keys read correctly, but transaction data" " or address book entries might be missing or incorrect.").translated, walletFile)); } else if (nLoadWalletRet == DBErrors::TOO_NEW) { - chain.initError(strprintf(_("Error loading %s: Wallet requires newer version of %s").translated, walletFile, PACKAGE_NAME)); + error = strprintf(_("Error loading %s: Wallet requires newer version of %s").translated, walletFile, PACKAGE_NAME); return nullptr; } else if (nLoadWalletRet == DBErrors::NEED_REWRITE) { - chain.initError(strprintf(_("Wallet needed to be rewritten: restart %s to complete").translated, PACKAGE_NAME)); + error = strprintf(_("Wallet needed to be rewritten: restart %s to complete").translated, PACKAGE_NAME); return nullptr; } else { - chain.initError(strprintf(_("Error loading %s").translated, walletFile)); + error = strprintf(_("Error loading %s").translated, walletFile); return nullptr; } } @@ -4320,7 +4297,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain, walletInstance->WalletLogPrintf("Allowing wallet upgrade up to %i\n", nMaxVersion); if (nMaxVersion < walletInstance->GetVersion()) { - chain.initError(_("Cannot downgrade wallet").translated); + error = _("Cannot downgrade wallet").translated; return nullptr; } walletInstance->SetMaxVersion(nMaxVersion); @@ -4333,7 +4310,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain, // Do not upgrade versions to any version between HD_SPLIT and FEATURE_PRE_SPLIT_KEYPOOL unless already supporting HD_SPLIT int max_version = walletInstance->GetVersion(); if (!walletInstance->CanSupportFeature(FEATURE_HD_SPLIT) && max_version >= FEATURE_HD_SPLIT && max_version < FEATURE_PRE_SPLIT_KEYPOOL) { - chain.initError(_("Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.").translated); + error = _("Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.").translated; return nullptr; } @@ -4361,7 +4338,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain, // Regenerate the keypool if upgraded to HD if (hd_upgrade) { if (!walletInstance->TopUpKeyPool()) { - chain.initError(_("Unable to generate keys").translated); + error = _("Unable to generate keys").translated; return nullptr; } } @@ -4381,7 +4358,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain, // Top up the keypool if (walletInstance->CanGenerateKeys() && !walletInstance->TopUpKeyPool()) { - chain.initError(_("Unable to generate initial keys").translated); + error = _("Unable to generate initial keys").translated; return nullptr; } @@ -4389,33 +4366,33 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain, walletInstance->ChainStateFlushed(locked_chain->getTipLocator()); } else if (wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS) { // Make it impossible to disable private keys after creation - chain.initError(strprintf(_("Error loading %s: Private keys can only be disabled during creation").translated, walletFile)); + error = strprintf(_("Error loading %s: Private keys can only be disabled during creation").translated, walletFile); return NULL; } else if (walletInstance->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) { LOCK(walletInstance->cs_KeyStore); if (!walletInstance->mapKeys.empty() || !walletInstance->mapCryptedKeys.empty()) { - chain.initWarning(strprintf(_("Warning: Private keys detected in wallet {%s} with disabled private keys").translated, walletFile)); + warnings.push_back(strprintf(_("Warning: Private keys detected in wallet {%s} with disabled private keys").translated, walletFile)); } } if (!gArgs.GetArg("-addresstype", "").empty() && !ParseOutputType(gArgs.GetArg("-addresstype", ""), walletInstance->m_default_address_type)) { - chain.initError(strprintf(_("Unknown address type '%s'").translated, gArgs.GetArg("-addresstype", ""))); + error = strprintf(_("Unknown address type '%s'").translated, gArgs.GetArg("-addresstype", "")); return nullptr; } if (!gArgs.GetArg("-changetype", "").empty() && !ParseOutputType(gArgs.GetArg("-changetype", ""), walletInstance->m_default_change_type)) { - chain.initError(strprintf(_("Unknown change type '%s'").translated, gArgs.GetArg("-changetype", ""))); + error = strprintf(_("Unknown change type '%s'").translated, gArgs.GetArg("-changetype", "")); return nullptr; } if (gArgs.IsArgSet("-mintxfee")) { CAmount n = 0; if (!ParseMoney(gArgs.GetArg("-mintxfee", ""), n) || 0 == n) { - chain.initError(AmountErrMsg("mintxfee", gArgs.GetArg("-mintxfee", "")).translated); + error = AmountErrMsg("mintxfee", gArgs.GetArg("-mintxfee", "")).translated; return nullptr; } if (n > HIGH_TX_FEE_PER_KB) { - chain.initWarning(AmountHighWarn("-mintxfee").translated + " " + + warnings.push_back(AmountHighWarn("-mintxfee").translated + " " + _("This is the minimum transaction fee you pay on every transaction.").translated); } walletInstance->m_min_fee = CFeeRate(n); @@ -4424,11 +4401,11 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain, if (gArgs.IsArgSet("-fallbackfee")) { CAmount nFeePerK = 0; if (!ParseMoney(gArgs.GetArg("-fallbackfee", ""), nFeePerK)) { - chain.initError(strprintf(_("Invalid amount for -fallbackfee=<amount>: '%s'").translated, gArgs.GetArg("-fallbackfee", ""))); + error = strprintf(_("Invalid amount for -fallbackfee=<amount>: '%s'").translated, gArgs.GetArg("-fallbackfee", "")); return nullptr; } if (nFeePerK > HIGH_TX_FEE_PER_KB) { - chain.initWarning(AmountHighWarn("-fallbackfee").translated + " " + + warnings.push_back(AmountHighWarn("-fallbackfee").translated + " " + _("This is the transaction fee you may pay when fee estimates are not available.").translated); } walletInstance->m_fallback_fee = CFeeRate(nFeePerK); @@ -4439,11 +4416,11 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain, if (gArgs.IsArgSet("-discardfee")) { CAmount nFeePerK = 0; if (!ParseMoney(gArgs.GetArg("-discardfee", ""), nFeePerK)) { - chain.initError(strprintf(_("Invalid amount for -discardfee=<amount>: '%s'").translated, gArgs.GetArg("-discardfee", ""))); + error = strprintf(_("Invalid amount for -discardfee=<amount>: '%s'").translated, gArgs.GetArg("-discardfee", "")); return nullptr; } if (nFeePerK > HIGH_TX_FEE_PER_KB) { - chain.initWarning(AmountHighWarn("-discardfee").translated + " " + + warnings.push_back(AmountHighWarn("-discardfee").translated + " " + _("This is the transaction fee you may discard if change is smaller than dust at this level").translated); } walletInstance->m_discard_rate = CFeeRate(nFeePerK); @@ -4451,41 +4428,40 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain, if (gArgs.IsArgSet("-paytxfee")) { CAmount nFeePerK = 0; if (!ParseMoney(gArgs.GetArg("-paytxfee", ""), nFeePerK)) { - chain.initError(AmountErrMsg("paytxfee", gArgs.GetArg("-paytxfee", "")).translated); + error = AmountErrMsg("paytxfee", gArgs.GetArg("-paytxfee", "")).translated; return nullptr; } if (nFeePerK > HIGH_TX_FEE_PER_KB) { - chain.initWarning(AmountHighWarn("-paytxfee").translated + " " + + warnings.push_back(AmountHighWarn("-paytxfee").translated + " " + _("This is the transaction fee you will pay if you send a transaction.").translated); } walletInstance->m_pay_tx_fee = CFeeRate(nFeePerK, 1000); if (walletInstance->m_pay_tx_fee < chain.relayMinFee()) { - chain.initError(strprintf(_("Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s)").translated, - gArgs.GetArg("-paytxfee", ""), chain.relayMinFee().ToString())); + error = strprintf(_("Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s)").translated, + gArgs.GetArg("-paytxfee", ""), chain.relayMinFee().ToString()); return nullptr; } } - if (gArgs.IsArgSet("-maxtxfee")) - { + if (gArgs.IsArgSet("-maxtxfee")) { CAmount nMaxFee = 0; if (!ParseMoney(gArgs.GetArg("-maxtxfee", ""), nMaxFee)) { - chain.initError(AmountErrMsg("maxtxfee", gArgs.GetArg("-maxtxfee", "")).translated); + error = AmountErrMsg("maxtxfee", gArgs.GetArg("-maxtxfee", "")).translated; return nullptr; } if (nMaxFee > HIGH_MAX_TX_FEE) { - chain.initWarning(_("-maxtxfee is set very high! Fees this large could be paid on a single transaction.").translated); + warnings.push_back(_("-maxtxfee is set very high! Fees this large could be paid on a single transaction.").translated); } if (CFeeRate(nMaxFee, 1000) < chain.relayMinFee()) { - chain.initError(strprintf(_("Invalid amount for -maxtxfee=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)").translated, - gArgs.GetArg("-maxtxfee", ""), chain.relayMinFee().ToString())); + error = strprintf(_("Invalid amount for -maxtxfee=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)").translated, + gArgs.GetArg("-maxtxfee", ""), chain.relayMinFee().ToString()); return nullptr; } walletInstance->m_default_max_tx_fee = nMaxFee; } if (chain.relayMinFee().GetFeePerK() > HIGH_TX_FEE_PER_KB) { - chain.initWarning(AmountHighWarn("-minrelaytxfee").translated + " " + + warnings.push_back(AmountHighWarn("-minrelaytxfee").translated + " " + _("The wallet will avoid paying less than the minimum relay fee.").translated); } @@ -4535,7 +4511,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain, } if (rescan_height != block_height) { - chain.initError(_("Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)").translated); + error = _("Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)").translated; return nullptr; } } @@ -4554,7 +4530,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain, { WalletRescanReserver reserver(walletInstance.get()); if (!reserver.reserve() || (ScanResult::SUCCESS != walletInstance->ScanForWalletTransactions(locked_chain->getBlockHash(rescan_height), {} /* stop block */, reserver, true /* update */).status)) { - chain.initError(_("Failed to rescan the wallet during initialization").translated); + error = _("Failed to rescan the wallet during initialization").translated; return nullptr; } } diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 006775e83b..85c277ff50 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -11,7 +11,6 @@ #include <interfaces/handler.h> #include <outputtype.h> #include <policy/feerate.h> -#include <script/sign.h> #include <tinyformat.h> #include <ui_interface.h> #include <util/strencodings.h> @@ -48,7 +47,7 @@ bool RemoveWallet(const std::shared_ptr<CWallet>& wallet); bool HasWallets(); std::vector<std::shared_ptr<CWallet>> GetWallets(); std::shared_ptr<CWallet> GetWallet(const std::string& name); -std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const WalletLocation& location, std::string& error, std::string& warning); +std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const WalletLocation& location, std::string& error, std::vector<std::string>& warnings); enum class WalletCreationStatus { SUCCESS, @@ -56,7 +55,7 @@ enum class WalletCreationStatus { ENCRYPTION_FAILED }; -WalletCreationStatus CreateWallet(interfaces::Chain& chain, const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, std::string& error, std::string& warning, std::shared_ptr<CWallet>& result); +WalletCreationStatus CreateWallet(interfaces::Chain& chain, const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, std::string& error, std::vector<std::string>& warnings, std::shared_ptr<CWallet>& result); //! Default for -keypool static const unsigned int DEFAULT_KEYPOOL_SIZE = 1000; @@ -1147,7 +1146,16 @@ public: */ bool CreateTransaction(interfaces::Chain::Lock& locked_chain, const std::vector<CRecipient>& vecSend, CTransactionRef& tx, CAmount& nFeeRet, int& nChangePosInOut, std::string& strFailReason, const CCoinControl& coin_control, bool sign = true); - bool CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::vector<std::pair<std::string, std::string>> orderForm, CValidationState& state); + /** + * Submit the transaction to the node's mempool and then relay to peers. + * Should be called after CreateTransaction unless you want to abort + * broadcasting the transaction. + * + * @param tx[in] The transaction to be broadcast. + * @param mapValue[in] key-values to be set on the transaction. + * @param orderForm[in] BIP 70 / BIP 21 order form details to be set on the transaction. + */ + void CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::vector<std::pair<std::string, std::string>> orderForm); bool DummySignTx(CMutableTransaction &txNew, const std::set<CTxOut> &txouts, bool use_max_sig = false) const { @@ -1246,8 +1254,6 @@ public: bool DelAddressBook(const CTxDestination& address); - const std::string& GetLabelName(const CScript& scriptPubKey) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); - unsigned int GetKeyPoolSize() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) { AssertLockHeld(cs_wallet); @@ -1321,10 +1327,10 @@ public: bool MarkReplaced(const uint256& originalHash, const uint256& newHash); //! Verify wallet naming and perform salvage on the wallet if required - static bool Verify(interfaces::Chain& chain, const WalletLocation& location, bool salvage_wallet, std::string& error_string, std::string& warning_string); + static bool Verify(interfaces::Chain& chain, const WalletLocation& location, bool salvage_wallet, std::string& error_string, std::vector<std::string>& warnings); /* Initializes the wallet, returns a new CWallet instance or a null pointer in case of an error */ - static std::shared_ptr<CWallet> CreateWalletFromFile(interfaces::Chain& chain, const WalletLocation& location, uint64_t wallet_creation_flags = 0); + static std::shared_ptr<CWallet> CreateWalletFromFile(interfaces::Chain& chain, const WalletLocation& location, std::string& error, std::vector<std::string>& warnings, uint64_t wallet_creation_flags = 0); /** * Wallet post-init setup diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 635997afc9..a9e6763c6d 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -5,8 +5,6 @@ #include <wallet/walletdb.h> -#include <consensus/tx_check.h> -#include <consensus/validation.h> #include <fs.h> #include <key_io.h> #include <protocol.h> @@ -218,8 +216,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, ssKey >> hash; CWalletTx wtx(nullptr /* pwallet */, MakeTransactionRef()); ssValue >> wtx; - CValidationState state; - if (!(CheckTransaction(*wtx.tx, state) && (wtx.GetHash() == hash) && state.IsValid())) + if (wtx.GetHash() != hash) return false; // Undo serialize changes in 31600 @@ -729,9 +726,9 @@ bool WalletBatch::VerifyEnvironment(const fs::path& wallet_path, std::string& er return BerkeleyBatch::VerifyEnvironment(wallet_path, errorStr); } -bool WalletBatch::VerifyDatabaseFile(const fs::path& wallet_path, std::string& warningStr, std::string& errorStr) +bool WalletBatch::VerifyDatabaseFile(const fs::path& wallet_path, std::vector<std::string>& warnings, std::string& errorStr) { - return BerkeleyBatch::VerifyDatabaseFile(wallet_path, warningStr, errorStr, WalletBatch::Recover); + return BerkeleyBatch::VerifyDatabaseFile(wallet_path, warnings, errorStr, WalletBatch::Recover); } bool WalletBatch::WriteDestData(const std::string &address, const std::string &key, const std::string &value) diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h index 0fee35934d..b1781d5ccf 100644 --- a/src/wallet/walletdb.h +++ b/src/wallet/walletdb.h @@ -7,15 +7,12 @@ #define BITCOIN_WALLET_WALLETDB_H #include <amount.h> -#include <primitives/transaction.h> #include <script/sign.h> #include <wallet/db.h> #include <key.h> -#include <list> #include <stdint.h> #include <string> -#include <utility> #include <vector> /** @@ -263,7 +260,7 @@ public: /* verifies the database environment */ static bool VerifyEnvironment(const fs::path& wallet_path, std::string& errorStr); /* verifies the database file */ - static bool VerifyDatabaseFile(const fs::path& wallet_path, std::string& warningStr, std::string& errorStr); + static bool VerifyDatabaseFile(const fs::path& wallet_path, std::vector<std::string>& warnings, std::string& errorStr); //! write the hdchain model (external chain child index counter) bool WriteHDChain(const CHDChain& chain); diff --git a/src/wallet/wallettool.h b/src/wallet/wallettool.h index 7ee2505631..bd08da42d6 100644 --- a/src/wallet/wallettool.h +++ b/src/wallet/wallettool.h @@ -5,7 +5,6 @@ #ifndef BITCOIN_WALLET_WALLETTOOL_H #define BITCOIN_WALLET_WALLETTOOL_H -#include <wallet/ismine.h> #include <wallet/wallet.h> namespace WalletTool { diff --git a/src/warnings.h b/src/warnings.h index 16c8f7b52e..e6701ebd9e 100644 --- a/src/warnings.h +++ b/src/warnings.h @@ -6,7 +6,6 @@ #ifndef BITCOIN_WARNINGS_H #define BITCOIN_WARNINGS_H -#include <stdlib.h> #include <string> void SetMiscWarning(const std::string& strWarning); diff --git a/src/zmq/zmqconfig.h b/src/zmq/zmqconfig.h index 5219ffad40..e3fdbf7402 100644 --- a/src/zmq/zmqconfig.h +++ b/src/zmq/zmqconfig.h @@ -10,13 +10,11 @@ #endif #include <stdarg.h> -#include <string> #if ENABLE_ZMQ #include <zmq.h> #endif -#include <primitives/block.h> #include <primitives/transaction.h> void zmqError(const char *str); diff --git a/src/zmq/zmqnotificationinterface.cpp b/src/zmq/zmqnotificationinterface.cpp index de59b71b8f..ebbaf8683d 100644 --- a/src/zmq/zmqnotificationinterface.cpp +++ b/src/zmq/zmqnotificationinterface.cpp @@ -5,7 +5,6 @@ #include <zmq/zmqnotificationinterface.h> #include <zmq/zmqpublishnotifier.h> -#include <version.h> #include <validation.h> #include <util/system.h> diff --git a/src/zmq/zmqnotificationinterface.h b/src/zmq/zmqnotificationinterface.h index a0cc26a162..6be0554a65 100644 --- a/src/zmq/zmqnotificationinterface.h +++ b/src/zmq/zmqnotificationinterface.h @@ -6,8 +6,6 @@ #define BITCOIN_ZMQ_ZMQNOTIFICATIONINTERFACE_H #include <validationinterface.h> -#include <string> -#include <map> #include <list> class CBlockIndex; diff --git a/test/README.md b/test/README.md index 26fd525064..11adc11278 100644 --- a/test/README.md +++ b/test/README.md @@ -88,7 +88,7 @@ By default, up to 4 tests will be run in parallel by test_runner. To specify how many jobs to run, append `--jobs=n` The individual tests and the test_runner harness have many command-line -options. Run `test_runner.py -h` to see them all. +options. Run `test/functional/test_runner.py -h` to see them all. #### Troubleshooting and debugging test failures @@ -101,7 +101,7 @@ killed all its bitcoind nodes), then there may be a port conflict which will cause the test to fail. It is recommended that you run the tests on a system where no other bitcoind processes are running. -On linux, the test_framework will warn if there is another +On linux, the test framework will warn if there is another bitcoind process running when the tests are started. If there are zombie bitcoind processes after test failure, you can kill them @@ -130,7 +130,7 @@ tests will fail. If this happens, remove the cache directory (and make sure bitcoind processes are stopped as above): ```bash -rm -rf cache +rm -rf test/cache killall bitcoind ``` @@ -149,6 +149,15 @@ levels using the logger included in the test_framework, e.g. fails, the `test_framework.log` and bitcoind `debug.log`s will all be dumped to the console to help troubleshooting. +These log files can be located under the test data directory (which is always +printed in the first line of test output): + - `<test data directory>/test_framework.log` + - `<test data directory>/node<node number>/regtest/debug.log`. + +The node number identifies the relevant test node, starting from `node0`, which +corresponds to its position in the nodes list of the specific test, +e.g. `self.nodes[0]`. + To change the level of logs output to the console, use the `-l` command line argument. @@ -157,7 +166,7 @@ aggregate log by running the `combine_logs.py` script. The output can be plain text, colorized text or html. For example: ``` -combine_logs.py -c <test data directory> | less -r +test/functional/combine_logs.py -c <test data directory> | less -r ``` will pipe the colorized logs from the test into less. diff --git a/test/functional/README.md b/test/functional/README.md index 197c2afbe4..a9b83076eb 100644 --- a/test/functional/README.md +++ b/test/functional/README.md @@ -4,13 +4,13 @@ #### Example test -The [example_test.py](example_test.py) is a heavily commented example of a test case that uses both -the RPC and P2P interfaces. If you are writing your first test, copy that file -and modify to fit your needs. +The file [test/functional/example_test.py](example_test.py) is a heavily commented example +of a test case that uses both the RPC and P2P interfaces. If you are writing your first test, copy +that file and modify to fit your needs. #### Coverage -Running `test_runner.py` with the `--coverage` argument tracks which RPCs are +Running `test/functional/test_runner.py` with the `--coverage` argument tracks which RPCs are called by the tests and prints a report of uncovered RPCs in the summary. This can be used (along with the `--extended` argument) to find out which RPCs we don't have test cases for. @@ -82,7 +82,7 @@ P2P messages. These can be found in the following source files: #### Using the P2P interface -- `messages.py` contains all the definitions for objects that pass +- [messages.py](test_framework/messages.py) contains all the definitions for objects that pass over the network (`CBlock`, `CTransaction`, etc, along with the network-level wrappers for them, `msg_block`, `msg_tx`, etc). @@ -96,32 +96,35 @@ the Bitcoin Core node application logic. For custom behaviour, subclass the P2PInterface object and override the callback methods. - Can be used to write tests where specific P2P protocol behavior is tested. -Examples tests are `p2p_unrequested_blocks.py`, `p2p_compactblocks.py`. +Examples tests are [p2p_unrequested_blocks.py](p2p_unrequested_blocks.py), +[p2p_compactblocks.py](p2p_compactblocks.py). -### test-framework modules +### Test framework modules +The following are useful modules for test developers. They are located in +[test/functional/test_framework/](test_framework). -#### [test_framework/authproxy.py](test_framework/authproxy.py) +#### [authproxy.py](test_framework/authproxy.py) Taken from the [python-bitcoinrpc repository](https://github.com/jgarzik/python-bitcoinrpc). -#### [test_framework/test_framework.py](test_framework/test_framework.py) +#### [test_framework.py](test_framework/test_framework.py) Base class for functional tests. -#### [test_framework/util.py](test_framework/util.py) +#### [util.py](test_framework/util.py) Generally useful functions. -#### [test_framework/mininode.py](test_framework/mininode.py) +#### [mininode.py](test_framework/mininode.py) Basic code to support P2P connectivity to a bitcoind. -#### [test_framework/script.py](test_framework/script.py) +#### [script.py](test_framework/script.py) Utilities for manipulating transaction scripts (originally from python-bitcoinlib) -#### [test_framework/key.py](test_framework/key.py) +#### [key.py](test_framework/key.py) Test-only secp256k1 elliptic curve implementation -#### [test_framework/bignum.py](test_framework/bignum.py) +#### [bignum.py](test_framework/bignum.py) Helpers for script.py -#### [test_framework/blocktools.py](test_framework/blocktools.py) +#### [blocktools.py](test_framework/blocktools.py) Helper functions for creating blocks and transactions. ### Benchmarking with perf diff --git a/test/functional/feature_bip68_sequence.py b/test/functional/feature_bip68_sequence.py index 677362756c..fe45ed34b5 100755 --- a/test/functional/feature_bip68_sequence.py +++ b/test/functional/feature_bip68_sequence.py @@ -8,7 +8,6 @@ import time from test_framework.blocktools import create_block, create_coinbase, add_witness_commitment from test_framework.messages import COIN, COutPoint, CTransaction, CTxIn, CTxOut, FromHex, ToHex -from test_framework.script import CScript from test_framework.test_framework import BitcoinTestFramework from test_framework.util import ( assert_equal, @@ -17,6 +16,7 @@ from test_framework.util import ( satoshi_round, softfork_active, ) +from test_framework.script_util import DUMMY_P2WPKH_SCRIPT SEQUENCE_LOCKTIME_DISABLE_FLAG = (1<<31) SEQUENCE_LOCKTIME_TYPE_FLAG = (1<<22) # this means use time (0 means height) @@ -24,15 +24,14 @@ SEQUENCE_LOCKTIME_GRANULARITY = 9 # this is a bit-shift SEQUENCE_LOCKTIME_MASK = 0x0000ffff # RPC error for non-BIP68 final transactions -NOT_FINAL_ERROR = "non-BIP68-final (code 64)" +NOT_FINAL_ERROR = "non-BIP68-final" class BIP68Test(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 2 - # TODO remove output type argument and fix resulting "tx-size-small" errors self.extra_args = [ - ["-acceptnonstdtxn=1", "-addresstype=p2sh-segwit"], - ["-acceptnonstdtxn=0", "-addresstype=p2sh-segwit"], + ["-acceptnonstdtxn=1"], + ["-acceptnonstdtxn=0"], ] def skip_test_if_missing_module(self): @@ -85,7 +84,7 @@ class BIP68Test(BitcoinTestFramework): # input to mature. sequence_value = SEQUENCE_LOCKTIME_DISABLE_FLAG | 1 tx1.vin = [CTxIn(COutPoint(int(utxo["txid"], 16), utxo["vout"]), nSequence=sequence_value)] - tx1.vout = [CTxOut(value, CScript([b'a']))] + tx1.vout = [CTxOut(value, DUMMY_P2WPKH_SCRIPT)] tx1_signed = self.nodes[0].signrawtransactionwithwallet(ToHex(tx1))["hex"] tx1_id = self.nodes[0].sendrawtransaction(tx1_signed) @@ -97,7 +96,7 @@ class BIP68Test(BitcoinTestFramework): tx2.nVersion = 2 sequence_value = sequence_value & 0x7fffffff tx2.vin = [CTxIn(COutPoint(tx1_id, 0), nSequence=sequence_value)] - tx2.vout = [CTxOut(int(value - self.relayfee * COIN), CScript([b'a' * 35]))] + tx2.vout = [CTxOut(int(value - self.relayfee * COIN), DUMMY_P2WPKH_SCRIPT)] tx2.rehash() assert_raises_rpc_error(-26, NOT_FINAL_ERROR, self.nodes[0].sendrawtransaction, ToHex(tx2)) @@ -192,7 +191,7 @@ class BIP68Test(BitcoinTestFramework): value += utxos[j]["amount"]*COIN # Overestimate the size of the tx - signatures should be less than 120 bytes, and leave 50 for the output tx_size = len(ToHex(tx))//2 + 120*num_inputs + 50 - tx.vout.append(CTxOut(int(value-self.relayfee*tx_size*COIN/1000), CScript([b'a']))) + tx.vout.append(CTxOut(int(value-self.relayfee*tx_size*COIN/1000), DUMMY_P2WPKH_SCRIPT)) rawtx = self.nodes[0].signrawtransactionwithwallet(ToHex(tx))["hex"] if (using_sequence_locks and not should_pass): @@ -221,7 +220,7 @@ class BIP68Test(BitcoinTestFramework): tx2 = CTransaction() tx2.nVersion = 2 tx2.vin = [CTxIn(COutPoint(tx1.sha256, 0), nSequence=0)] - tx2.vout = [CTxOut(int(tx1.vout[0].nValue - self.relayfee*COIN), CScript([b'a']))] + tx2.vout = [CTxOut(int(tx1.vout[0].nValue - self.relayfee*COIN), DUMMY_P2WPKH_SCRIPT)] tx2_raw = self.nodes[0].signrawtransactionwithwallet(ToHex(tx2))["hex"] tx2 = FromHex(tx2, tx2_raw) tx2.rehash() @@ -239,7 +238,7 @@ class BIP68Test(BitcoinTestFramework): tx = CTransaction() tx.nVersion = 2 tx.vin = [CTxIn(COutPoint(orig_tx.sha256, 0), nSequence=sequence_value)] - tx.vout = [CTxOut(int(orig_tx.vout[0].nValue - relayfee * COIN), CScript([b'a' * 35]))] + tx.vout = [CTxOut(int(orig_tx.vout[0].nValue - relayfee * COIN), DUMMY_P2WPKH_SCRIPT)] tx.rehash() if (orig_tx.hash in node.getrawmempool()): @@ -352,7 +351,7 @@ class BIP68Test(BitcoinTestFramework): tx2 = CTransaction() tx2.nVersion = 1 tx2.vin = [CTxIn(COutPoint(tx1.sha256, 0), nSequence=0)] - tx2.vout = [CTxOut(int(tx1.vout[0].nValue - self.relayfee*COIN), CScript([b'a']))] + tx2.vout = [CTxOut(int(tx1.vout[0].nValue - self.relayfee*COIN), DUMMY_P2WPKH_SCRIPT)] # sign tx2 tx2_raw = self.nodes[0].signrawtransactionwithwallet(ToHex(tx2))["hex"] @@ -367,7 +366,7 @@ class BIP68Test(BitcoinTestFramework): tx3 = CTransaction() tx3.nVersion = 2 tx3.vin = [CTxIn(COutPoint(tx2.sha256, 0), nSequence=sequence_value)] - tx3.vout = [CTxOut(int(tx2.vout[0].nValue - self.relayfee * COIN), CScript([b'a' * 35]))] + tx3.vout = [CTxOut(int(tx2.vout[0].nValue - self.relayfee * COIN), DUMMY_P2WPKH_SCRIPT)] tx3.rehash() assert_raises_rpc_error(-26, NOT_FINAL_ERROR, self.nodes[0].sendrawtransaction, ToHex(tx3)) diff --git a/test/functional/feature_block.py b/test/functional/feature_block.py index c74270febc..c7e98bd4db 100755 --- a/test/functional/feature_block.py +++ b/test/functional/feature_block.py @@ -46,7 +46,7 @@ from test_framework.script import ( OP_RETURN, OP_TRUE, SIGHASH_ALL, - SignatureHash, + LegacySignatureHash, hash160, ) from test_framework.test_framework import BitcoinTestFramework @@ -532,7 +532,7 @@ class FullBlockTest(BitcoinTestFramework): # second input is corresponding P2SH output from b39 tx.vin.append(CTxIn(COutPoint(b39.vtx[i].sha256, 0), b'')) # Note: must pass the redeem_script (not p2sh_script) to the signature hash function - (sighash, err) = SignatureHash(redeem_script, tx, 1, SIGHASH_ALL) + (sighash, err) = LegacySignatureHash(redeem_script, tx, 1, SIGHASH_ALL) sig = self.coinbase_key.sign_ecdsa(sighash) + bytes(bytearray([SIGHASH_ALL])) scriptSig = CScript([sig, redeem_script]) @@ -1312,7 +1312,7 @@ class FullBlockTest(BitcoinTestFramework): if (scriptPubKey[0] == OP_TRUE): # an anyone-can-spend tx.vin[0].scriptSig = CScript() return - (sighash, err) = SignatureHash(spend_tx.vout[0].scriptPubKey, tx, 0, SIGHASH_ALL) + (sighash, err) = LegacySignatureHash(spend_tx.vout[0].scriptPubKey, tx, 0, SIGHASH_ALL) tx.vin[0].scriptSig = CScript([self.coinbase_key.sign_ecdsa(sighash) + bytes(bytearray([SIGHASH_ALL]))]) def create_and_sign_transaction(self, spend_tx, value, script=CScript([OP_TRUE])): diff --git a/test/functional/feature_cltv.py b/test/functional/feature_cltv.py index 13f1c9216a..7d131e6045 100755 --- a/test/functional/feature_cltv.py +++ b/test/functional/feature_cltv.py @@ -126,7 +126,7 @@ class BIP65Test(BitcoinTestFramework): # First we show that this tx is valid except for CLTV by getting it # rejected from the mempool for exactly that reason. assert_equal( - [{'txid': spendtx.hash, 'allowed': False, 'reject-reason': '64: non-mandatory-script-verify-flag (Negative locktime)'}], + [{'txid': spendtx.hash, 'allowed': False, 'reject-reason': 'non-mandatory-script-verify-flag (Negative locktime)'}], self.nodes[0].testmempoolaccept(rawtxs=[spendtx.serialize().hex()], maxfeerate=0) ) diff --git a/test/functional/feature_dersig.py b/test/functional/feature_dersig.py index 92f6eea5b2..2ace96fef4 100755 --- a/test/functional/feature_dersig.py +++ b/test/functional/feature_dersig.py @@ -110,7 +110,7 @@ class BIP66Test(BitcoinTestFramework): # First we show that this tx is valid except for DERSIG by getting it # rejected from the mempool for exactly that reason. assert_equal( - [{'txid': spendtx.hash, 'allowed': False, 'reject-reason': '64: non-mandatory-script-verify-flag (Non-canonical DER signature)'}], + [{'txid': spendtx.hash, 'allowed': False, 'reject-reason': 'non-mandatory-script-verify-flag (Non-canonical DER signature)'}], self.nodes[0].testmempoolaccept(rawtxs=[spendtx.serialize().hex()], maxfeerate=0) ) diff --git a/test/functional/feature_loadblock.py b/test/functional/feature_loadblock.py new file mode 100755 index 0000000000..bf2a4ff61f --- /dev/null +++ b/test/functional/feature_loadblock.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python3 +# Copyright (c) 2017-2019 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. +"""Test loadblock option + +Test the option to start a node with the option loadblock which loads +a serialized blockchain from a file (usually called bootstrap.dat). +To generate that file this test uses the helper scripts available +in contrib/linearize. +""" + +import os +import subprocess +import sys +import tempfile +import urllib + +from test_framework.test_framework import ( + BitcoinTestFramework, +) +from test_framework.util import assert_equal, wait_until + + +class LoadblockTest(BitcoinTestFramework): + def set_test_params(self): + self.setup_clean_chain = True + self.num_nodes = 2 + + def run_test(self): + self.nodes[1].setnetworkactive(state=False) + self.nodes[0].generate(100) + + # Parsing the url of our node to get settings for config file + data_dir = self.nodes[0].datadir + node_url = urllib.parse.urlparse(self.nodes[0].url) + cfg_file = os.path.join(data_dir, "linearize.cfg") + bootstrap_file = os.path.join(self.options.tmpdir, "bootstrap.dat") + genesis_block = self.nodes[0].getblockhash(0) + blocks_dir = os.path.join(data_dir, "regtest", "blocks") + hash_list = tempfile.NamedTemporaryFile(dir=data_dir, + mode='w', + delete=False, + encoding="utf-8") + + self.log.info("Create linearization config file") + with open(cfg_file, "a", encoding="utf-8") as cfg: + cfg.write("datadir={}\n".format(data_dir)) + cfg.write("rpcuser={}\n".format(node_url.username)) + cfg.write("rpcpassword={}\n".format(node_url.password)) + cfg.write("port={}\n".format(node_url.port)) + cfg.write("host={}\n".format(node_url.hostname)) + cfg.write("output_file={}\n".format(bootstrap_file)) + cfg.write("max_height=100\n") + cfg.write("netmagic=fabfb5da\n") + cfg.write("input={}\n".format(blocks_dir)) + cfg.write("genesis={}\n".format(genesis_block)) + cfg.write("hashlist={}\n".format(hash_list.name)) + + base_dir = self.config["environment"]["SRCDIR"] + linearize_dir = os.path.join(base_dir, "contrib", "linearize") + + self.log.info("Run linearization of block hashes") + linearize_hashes_file = os.path.join(linearize_dir, "linearize-hashes.py") + subprocess.run([sys.executable, linearize_hashes_file, cfg_file], + stdout=hash_list, + check=True) + + self.log.info("Run linearization of block data") + linearize_data_file = os.path.join(linearize_dir, "linearize-data.py") + subprocess.run([sys.executable, linearize_data_file, cfg_file], + check=True) + + self.log.info("Restart second, unsynced node with bootstrap file") + self.stop_node(1) + self.start_node(1, ["-loadblock=" + bootstrap_file]) + wait_until(lambda: self.nodes[1].getblockcount() == 100) + + assert_equal(self.nodes[1].getblockchaininfo()['blocks'], 100) + assert_equal(self.nodes[0].getbestblockhash(), self.nodes[1].getbestblockhash()) + + +if __name__ == '__main__': + LoadblockTest().main() diff --git a/test/functional/feature_nulldummy.py b/test/functional/feature_nulldummy.py index 250dee1528..aaf56a42d0 100755 --- a/test/functional/feature_nulldummy.py +++ b/test/functional/feature_nulldummy.py @@ -20,7 +20,7 @@ from test_framework.script import CScript from test_framework.test_framework import BitcoinTestFramework from test_framework.util import assert_equal, assert_raises_rpc_error -NULLDUMMY_ERROR = "non-mandatory-script-verify-flag (Dummy CHECKMULTISIG argument must be zero) (code 64)" +NULLDUMMY_ERROR = "non-mandatory-script-verify-flag (Dummy CHECKMULTISIG argument must be zero)" def trueDummy(tx): scriptSig = CScript(tx.vin[0].scriptSig) diff --git a/test/functional/feature_rbf.py b/test/functional/feature_rbf.py index a1d4ce4c73..e7afbd0272 100755 --- a/test/functional/feature_rbf.py +++ b/test/functional/feature_rbf.py @@ -10,13 +10,14 @@ from test_framework.messages import COIN, COutPoint, CTransaction, CTxIn, CTxOut from test_framework.script import CScript, OP_DROP from test_framework.test_framework import BitcoinTestFramework from test_framework.util import assert_equal, assert_raises_rpc_error, satoshi_round +from test_framework.script_util import DUMMY_P2WPKH_SCRIPT MAX_REPLACEMENT_LIMIT = 100 def txToHex(tx): return tx.serialize().hex() -def make_utxo(node, amount, confirmed=True, scriptPubKey=CScript([1])): +def make_utxo(node, amount, confirmed=True, scriptPubKey=DUMMY_P2WPKH_SCRIPT): """Create a txout with a given amount and scriptPubKey Mines coins as needed. @@ -65,7 +66,6 @@ def make_utxo(node, amount, confirmed=True, scriptPubKey=CScript([1])): class ReplaceByFeeTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 1 - # TODO remove output type argument and fix resulting "tx-size-small" errors self.extra_args = [ [ "-acceptnonstdtxn=1", @@ -74,7 +74,6 @@ class ReplaceByFeeTest(BitcoinTestFramework): "-limitancestorsize=101", "-limitdescendantcount=200", "-limitdescendantsize=101", - "-addresstype=p2sh-segwit", ], ] @@ -133,7 +132,7 @@ class ReplaceByFeeTest(BitcoinTestFramework): tx1a = CTransaction() tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0)] - tx1a.vout = [CTxOut(1 * COIN, CScript([b'a' * 35]))] + tx1a.vout = [CTxOut(1 * COIN, DUMMY_P2WPKH_SCRIPT)] tx1a_hex = txToHex(tx1a) tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, 0) @@ -142,7 +141,7 @@ class ReplaceByFeeTest(BitcoinTestFramework): # Should fail because we haven't changed the fee tx1b = CTransaction() tx1b.vin = [CTxIn(tx0_outpoint, nSequence=0)] - tx1b.vout = [CTxOut(1 * COIN, CScript([b'b' * 35]))] + tx1b.vout = [CTxOut(1 * COIN, DUMMY_P2WPKH_SCRIPT + b'a')] tx1b_hex = txToHex(tx1b) # This will raise an exception due to insufficient fee @@ -151,7 +150,7 @@ class ReplaceByFeeTest(BitcoinTestFramework): # Extra 0.1 BTC fee tx1b = CTransaction() tx1b.vin = [CTxIn(tx0_outpoint, nSequence=0)] - tx1b.vout = [CTxOut(int(0.9 * COIN), CScript([b'b' * 35]))] + tx1b.vout = [CTxOut(int(0.9 * COIN), DUMMY_P2WPKH_SCRIPT)] tx1b_hex = txToHex(tx1b) # Works when enabled tx1b_txid = self.nodes[0].sendrawtransaction(tx1b_hex, 0) @@ -186,7 +185,7 @@ class ReplaceByFeeTest(BitcoinTestFramework): # child fees - 40 BTC - so this attempt is rejected. dbl_tx = CTransaction() dbl_tx.vin = [CTxIn(tx0_outpoint, nSequence=0)] - dbl_tx.vout = [CTxOut(initial_nValue - 30 * COIN, CScript([1] * 35))] + dbl_tx.vout = [CTxOut(initial_nValue - 30 * COIN, DUMMY_P2WPKH_SCRIPT)] dbl_tx_hex = txToHex(dbl_tx) # This will raise an exception due to insufficient fee @@ -195,7 +194,7 @@ class ReplaceByFeeTest(BitcoinTestFramework): # Accepted with sufficient fee dbl_tx = CTransaction() dbl_tx.vin = [CTxIn(tx0_outpoint, nSequence=0)] - dbl_tx.vout = [CTxOut(1 * COIN, CScript([1] * 35))] + dbl_tx.vout = [CTxOut(1 * COIN, DUMMY_P2WPKH_SCRIPT)] dbl_tx_hex = txToHex(dbl_tx) self.nodes[0].sendrawtransaction(dbl_tx_hex, 0) @@ -248,7 +247,7 @@ class ReplaceByFeeTest(BitcoinTestFramework): # Attempt double-spend, will fail because too little fee paid dbl_tx = CTransaction() dbl_tx.vin = [CTxIn(tx0_outpoint, nSequence=0)] - dbl_tx.vout = [CTxOut(initial_nValue - fee * n, CScript([1] * 35))] + dbl_tx.vout = [CTxOut(initial_nValue - fee * n, DUMMY_P2WPKH_SCRIPT)] dbl_tx_hex = txToHex(dbl_tx) # This will raise an exception due to insufficient fee assert_raises_rpc_error(-26, "insufficient fee", self.nodes[0].sendrawtransaction, dbl_tx_hex, 0) @@ -256,7 +255,7 @@ class ReplaceByFeeTest(BitcoinTestFramework): # 1 BTC fee is enough dbl_tx = CTransaction() dbl_tx.vin = [CTxIn(tx0_outpoint, nSequence=0)] - dbl_tx.vout = [CTxOut(initial_nValue - fee * n - 1 * COIN, CScript([1] * 35))] + dbl_tx.vout = [CTxOut(initial_nValue - fee * n - 1 * COIN, DUMMY_P2WPKH_SCRIPT)] dbl_tx_hex = txToHex(dbl_tx) self.nodes[0].sendrawtransaction(dbl_tx_hex, 0) @@ -276,7 +275,7 @@ class ReplaceByFeeTest(BitcoinTestFramework): dbl_tx = CTransaction() dbl_tx.vin = [CTxIn(tx0_outpoint, nSequence=0)] - dbl_tx.vout = [CTxOut(initial_nValue - 2 * fee * n, CScript([1] * 35))] + dbl_tx.vout = [CTxOut(initial_nValue - 2 * fee * n, DUMMY_P2WPKH_SCRIPT)] dbl_tx_hex = txToHex(dbl_tx) # This will raise an exception assert_raises_rpc_error(-26, "too many potential replacements", self.nodes[0].sendrawtransaction, dbl_tx_hex, 0) @@ -291,7 +290,7 @@ class ReplaceByFeeTest(BitcoinTestFramework): tx1a = CTransaction() tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0)] - tx1a.vout = [CTxOut(1 * COIN, CScript([b'a' * 35]))] + tx1a.vout = [CTxOut(1 * COIN, DUMMY_P2WPKH_SCRIPT)] tx1a_hex = txToHex(tx1a) self.nodes[0].sendrawtransaction(tx1a_hex, 0) @@ -312,7 +311,7 @@ class ReplaceByFeeTest(BitcoinTestFramework): tx1a = CTransaction() tx1a.vin = [CTxIn(utxo1, nSequence=0)] - tx1a.vout = [CTxOut(int(1.1 * COIN), CScript([b'a' * 35]))] + tx1a.vout = [CTxOut(int(1.1 * COIN), DUMMY_P2WPKH_SCRIPT)] tx1a_hex = txToHex(tx1a) tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, 0) @@ -331,7 +330,7 @@ class ReplaceByFeeTest(BitcoinTestFramework): # Spend tx1a's output to test the indirect case. tx1b = CTransaction() tx1b.vin = [CTxIn(COutPoint(tx1a_txid, 0), nSequence=0)] - tx1b.vout = [CTxOut(1 * COIN, CScript([b'a' * 35]))] + tx1b.vout = [CTxOut(1 * COIN, DUMMY_P2WPKH_SCRIPT)] tx1b_hex = txToHex(tx1b) tx1b_txid = self.nodes[0].sendrawtransaction(tx1b_hex, 0) tx1b_txid = int(tx1b_txid, 16) @@ -352,7 +351,7 @@ class ReplaceByFeeTest(BitcoinTestFramework): tx1 = CTransaction() tx1.vin = [CTxIn(confirmed_utxo)] - tx1.vout = [CTxOut(1 * COIN, CScript([b'a' * 35]))] + tx1.vout = [CTxOut(1 * COIN, DUMMY_P2WPKH_SCRIPT)] tx1_hex = txToHex(tx1) self.nodes[0].sendrawtransaction(tx1_hex, 0) @@ -391,7 +390,7 @@ class ReplaceByFeeTest(BitcoinTestFramework): for i in range(MAX_REPLACEMENT_LIMIT+1): tx_i = CTransaction() tx_i.vin = [CTxIn(COutPoint(txid, i), nSequence=0)] - tx_i.vout = [CTxOut(split_value - fee, CScript([b'a' * 35]))] + tx_i.vout = [CTxOut(split_value - fee, DUMMY_P2WPKH_SCRIPT)] tx_i_hex = txToHex(tx_i) self.nodes[0].sendrawtransaction(tx_i_hex, 0) @@ -424,7 +423,7 @@ class ReplaceByFeeTest(BitcoinTestFramework): # Create a non-opting in transaction tx1a = CTransaction() tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0xffffffff)] - tx1a.vout = [CTxOut(1 * COIN, CScript([b'a' * 35]))] + tx1a.vout = [CTxOut(1 * COIN, DUMMY_P2WPKH_SCRIPT)] tx1a_hex = txToHex(tx1a) tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, 0) @@ -434,7 +433,7 @@ class ReplaceByFeeTest(BitcoinTestFramework): # Shouldn't be able to double-spend tx1b = CTransaction() tx1b.vin = [CTxIn(tx0_outpoint, nSequence=0)] - tx1b.vout = [CTxOut(int(0.9 * COIN), CScript([b'b' * 35]))] + tx1b.vout = [CTxOut(int(0.9 * COIN), DUMMY_P2WPKH_SCRIPT)] tx1b_hex = txToHex(tx1b) # This will raise an exception @@ -445,14 +444,14 @@ class ReplaceByFeeTest(BitcoinTestFramework): # Create a different non-opting in transaction tx2a = CTransaction() tx2a.vin = [CTxIn(tx1_outpoint, nSequence=0xfffffffe)] - tx2a.vout = [CTxOut(1 * COIN, CScript([b'a' * 35]))] + tx2a.vout = [CTxOut(1 * COIN, DUMMY_P2WPKH_SCRIPT)] tx2a_hex = txToHex(tx2a) tx2a_txid = self.nodes[0].sendrawtransaction(tx2a_hex, 0) # Still shouldn't be able to double-spend tx2b = CTransaction() tx2b.vin = [CTxIn(tx1_outpoint, nSequence=0)] - tx2b.vout = [CTxOut(int(0.9 * COIN), CScript([b'b' * 35]))] + tx2b.vout = [CTxOut(int(0.9 * COIN), DUMMY_P2WPKH_SCRIPT)] tx2b_hex = txToHex(tx2b) # This will raise an exception @@ -478,12 +477,12 @@ class ReplaceByFeeTest(BitcoinTestFramework): tx3b = CTransaction() tx3b.vin = [CTxIn(COutPoint(tx1a_txid, 0), nSequence=0)] - tx3b.vout = [CTxOut(int(0.5 * COIN), CScript([b'e' * 35]))] + tx3b.vout = [CTxOut(int(0.5 * COIN), DUMMY_P2WPKH_SCRIPT)] tx3b_hex = txToHex(tx3b) tx3c = CTransaction() tx3c.vin = [CTxIn(COutPoint(tx2a_txid, 0), nSequence=0)] - tx3c.vout = [CTxOut(int(0.5 * COIN), CScript([b'f' * 35]))] + tx3c.vout = [CTxOut(int(0.5 * COIN), DUMMY_P2WPKH_SCRIPT)] tx3c_hex = txToHex(tx3c) self.nodes[0].sendrawtransaction(tx3b_hex, 0) @@ -500,7 +499,7 @@ class ReplaceByFeeTest(BitcoinTestFramework): tx1a = CTransaction() tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0)] - tx1a.vout = [CTxOut(1 * COIN, CScript([b'a' * 35]))] + tx1a.vout = [CTxOut(1 * COIN, DUMMY_P2WPKH_SCRIPT)] tx1a_hex = txToHex(tx1a) tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, 0) @@ -526,14 +525,14 @@ class ReplaceByFeeTest(BitcoinTestFramework): tx2a = CTransaction() tx2a.vin = [CTxIn(tx1_outpoint, nSequence=0)] - tx2a.vout = [CTxOut(1 * COIN, CScript([b'a' * 35]))] + tx2a.vout = [CTxOut(1 * COIN, DUMMY_P2WPKH_SCRIPT)] tx2a_hex = txToHex(tx2a) self.nodes[0].sendrawtransaction(tx2a_hex, 0) # Lower fee, but we'll prioritise it tx2b = CTransaction() tx2b.vin = [CTxIn(tx1_outpoint, nSequence=0)] - tx2b.vout = [CTxOut(int(1.01 * COIN), CScript([b'a' * 35]))] + tx2b.vout = [CTxOut(int(1.01 * COIN), DUMMY_P2WPKH_SCRIPT)] tx2b.rehash() tx2b_hex = txToHex(tx2b) diff --git a/test/functional/feature_segwit.py b/test/functional/feature_segwit.py index c69c7f90e8..82c7e55245 100755 --- a/test/functional/feature_segwit.py +++ b/test/functional/feature_segwit.py @@ -193,10 +193,10 @@ class SegWitTest(BitcoinTestFramework): assert self.nodes[0].getrawtransaction(tx_id, False, blockhash) == tx.serialize_without_witness().hex() self.log.info("Verify witness txs without witness data are invalid after the fork") - self.fail_accept(self.nodes[2], 'non-mandatory-script-verify-flag (Witness program hash mismatch) (code 64)', wit_ids[NODE_2][WIT_V0][2], sign=False) - self.fail_accept(self.nodes[2], 'non-mandatory-script-verify-flag (Witness program was passed an empty witness) (code 64)', wit_ids[NODE_2][WIT_V1][2], sign=False) - self.fail_accept(self.nodes[2], 'non-mandatory-script-verify-flag (Witness program hash mismatch) (code 64)', p2sh_ids[NODE_2][WIT_V0][2], sign=False, redeem_script=witness_script(False, self.pubkey[2])) - self.fail_accept(self.nodes[2], 'non-mandatory-script-verify-flag (Witness program was passed an empty witness) (code 64)', p2sh_ids[NODE_2][WIT_V1][2], sign=False, redeem_script=witness_script(True, self.pubkey[2])) + self.fail_accept(self.nodes[2], 'non-mandatory-script-verify-flag (Witness program hash mismatch)', wit_ids[NODE_2][WIT_V0][2], sign=False) + self.fail_accept(self.nodes[2], 'non-mandatory-script-verify-flag (Witness program was passed an empty witness)', wit_ids[NODE_2][WIT_V1][2], sign=False) + self.fail_accept(self.nodes[2], 'non-mandatory-script-verify-flag (Witness program hash mismatch)', p2sh_ids[NODE_2][WIT_V0][2], sign=False, redeem_script=witness_script(False, self.pubkey[2])) + self.fail_accept(self.nodes[2], 'non-mandatory-script-verify-flag (Witness program was passed an empty witness)', p2sh_ids[NODE_2][WIT_V1][2], sign=False, redeem_script=witness_script(True, self.pubkey[2])) self.log.info("Verify default node can now use witness txs") self.success_mine(self.nodes[0], wit_ids[NODE_0][WIT_V0][0], True) # block 432 diff --git a/test/functional/mempool_accept.py b/test/functional/mempool_accept.py index dee7a04516..c466b120f2 100755 --- a/test/functional/mempool_accept.py +++ b/test/functional/mempool_accept.py @@ -71,7 +71,7 @@ class MempoolAcceptanceTest(BitcoinTestFramework): node.generate(1) self.mempool_size = 0 self.check_mempool_result( - result_expected=[{'txid': txid_in_block, 'allowed': False, 'reject-reason': '18: txn-already-known'}], + result_expected=[{'txid': txid_in_block, 'allowed': False, 'reject-reason': 'txn-already-known'}], rawtxs=[raw_tx_in_block], ) @@ -109,7 +109,7 @@ class MempoolAcceptanceTest(BitcoinTestFramework): node.sendrawtransaction(hexstring=raw_tx_0) self.mempool_size += 1 self.check_mempool_result( - result_expected=[{'txid': txid_0, 'allowed': False, 'reject-reason': '18: txn-already-in-mempool'}], + result_expected=[{'txid': txid_0, 'allowed': False, 'reject-reason': 'txn-already-in-mempool'}], rawtxs=[raw_tx_0], ) @@ -133,7 +133,7 @@ class MempoolAcceptanceTest(BitcoinTestFramework): tx.vout[0].nValue -= int(4 * fee * COIN) # Set more fee # skip re-signing the tx self.check_mempool_result( - result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': '18: txn-mempool-conflict'}], + result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'txn-mempool-conflict'}], rawtxs=[tx.serialize().hex()], maxfeerate=0, ) @@ -192,7 +192,7 @@ class MempoolAcceptanceTest(BitcoinTestFramework): # Skip re-signing the transaction for context independent checks from now on # tx.deserialize(BytesIO(hex_str_to_bytes(node.signrawtransactionwithwallet(tx.serialize().hex())['hex']))) self.check_mempool_result( - result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': '16: bad-txns-vout-empty'}], + result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'bad-txns-vout-empty'}], rawtxs=[tx.serialize().hex()], ) @@ -200,7 +200,7 @@ class MempoolAcceptanceTest(BitcoinTestFramework): tx.deserialize(BytesIO(hex_str_to_bytes(raw_tx_reference))) tx.vin = [tx.vin[0]] * math.ceil(MAX_BLOCK_BASE_SIZE / len(tx.vin[0].serialize())) self.check_mempool_result( - result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': '16: bad-txns-oversize'}], + result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'bad-txns-oversize'}], rawtxs=[tx.serialize().hex()], ) @@ -208,7 +208,7 @@ class MempoolAcceptanceTest(BitcoinTestFramework): tx.deserialize(BytesIO(hex_str_to_bytes(raw_tx_reference))) tx.vout[0].nValue *= -1 self.check_mempool_result( - result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': '16: bad-txns-vout-negative'}], + result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'bad-txns-vout-negative'}], rawtxs=[tx.serialize().hex()], ) @@ -217,7 +217,7 @@ class MempoolAcceptanceTest(BitcoinTestFramework): tx.deserialize(BytesIO(hex_str_to_bytes(raw_tx_reference))) tx.vout[0].nValue = 21000000 * COIN + 1 self.check_mempool_result( - result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': '16: bad-txns-vout-toolarge'}], + result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'bad-txns-vout-toolarge'}], rawtxs=[tx.serialize().hex()], ) @@ -226,7 +226,7 @@ class MempoolAcceptanceTest(BitcoinTestFramework): tx.vout = [tx.vout[0]] * 2 tx.vout[0].nValue = 21000000 * COIN self.check_mempool_result( - result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': '16: bad-txns-txouttotal-toolarge'}], + result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'bad-txns-txouttotal-toolarge'}], rawtxs=[tx.serialize().hex()], ) @@ -234,7 +234,7 @@ class MempoolAcceptanceTest(BitcoinTestFramework): tx.deserialize(BytesIO(hex_str_to_bytes(raw_tx_reference))) tx.vin = [tx.vin[0]] * 2 self.check_mempool_result( - result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': '16: bad-txns-inputs-duplicate'}], + result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'bad-txns-inputs-duplicate'}], rawtxs=[tx.serialize().hex()], ) @@ -243,7 +243,7 @@ class MempoolAcceptanceTest(BitcoinTestFramework): raw_tx_coinbase_spent = node.getrawtransaction(txid=node.decoderawtransaction(hexstring=raw_tx_in_block)['vin'][0]['txid']) tx.deserialize(BytesIO(hex_str_to_bytes(raw_tx_coinbase_spent))) self.check_mempool_result( - result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': '16: coinbase'}], + result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'coinbase'}], rawtxs=[tx.serialize().hex()], ) @@ -251,19 +251,19 @@ class MempoolAcceptanceTest(BitcoinTestFramework): tx.deserialize(BytesIO(hex_str_to_bytes(raw_tx_reference))) tx.nVersion = 3 # A version currently non-standard self.check_mempool_result( - result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': '64: version'}], + result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'version'}], rawtxs=[tx.serialize().hex()], ) tx.deserialize(BytesIO(hex_str_to_bytes(raw_tx_reference))) tx.vout[0].scriptPubKey = CScript([OP_0]) # Some non-standard script self.check_mempool_result( - result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': '64: scriptpubkey'}], + result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'scriptpubkey'}], rawtxs=[tx.serialize().hex()], ) tx.deserialize(BytesIO(hex_str_to_bytes(raw_tx_reference))) tx.vin[0].scriptSig = CScript([OP_HASH160]) # Some not-pushonly scriptSig self.check_mempool_result( - result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': '64: scriptsig-not-pushonly'}], + result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'scriptsig-not-pushonly'}], rawtxs=[tx.serialize().hex()], ) tx.deserialize(BytesIO(hex_str_to_bytes(raw_tx_reference))) @@ -271,21 +271,21 @@ class MempoolAcceptanceTest(BitcoinTestFramework): num_scripts = 100000 // len(output_p2sh_burn.serialize()) # Use enough outputs to make the tx too large for our policy tx.vout = [output_p2sh_burn] * num_scripts self.check_mempool_result( - result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': '64: tx-size'}], + result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'tx-size'}], rawtxs=[tx.serialize().hex()], ) tx.deserialize(BytesIO(hex_str_to_bytes(raw_tx_reference))) tx.vout[0] = output_p2sh_burn tx.vout[0].nValue -= 1 # Make output smaller, such that it is dust for our policy self.check_mempool_result( - result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': '64: dust'}], + result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'dust'}], rawtxs=[tx.serialize().hex()], ) tx.deserialize(BytesIO(hex_str_to_bytes(raw_tx_reference))) tx.vout[0].scriptPubKey = CScript([OP_RETURN, b'\xff']) tx.vout = [tx.vout[0]] * 2 self.check_mempool_result( - result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': '64: multi-op-return'}], + result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'multi-op-return'}], rawtxs=[tx.serialize().hex()], ) @@ -294,7 +294,7 @@ class MempoolAcceptanceTest(BitcoinTestFramework): tx.vin[0].nSequence -= 1 # Should be non-max, so locktime is not ignored tx.nLockTime = node.getblockcount() + 1 self.check_mempool_result( - result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': '64: non-final'}], + result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'non-final'}], rawtxs=[tx.serialize().hex()], ) @@ -303,7 +303,7 @@ class MempoolAcceptanceTest(BitcoinTestFramework): tx.vin[0].nSequence = 2 # We could include it in the second block mined from now, but not the very next one # Can skip re-signing the tx because of early rejection self.check_mempool_result( - result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': '64: non-BIP68-final'}], + result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'non-BIP68-final'}], rawtxs=[tx.serialize().hex()], maxfeerate=0, ) diff --git a/test/functional/p2p_dos_header_tree.py b/test/functional/p2p_dos_header_tree.py index 7d386c47f6..6676b84e54 100755 --- a/test/functional/p2p_dos_header_tree.py +++ b/test/functional/p2p_dos_header_tree.py @@ -57,7 +57,7 @@ class RejectLowDifficultyHeadersTest(BitcoinTestFramework): } in self.nodes[0].getchaintips() self.log.info("Feed all fork headers (fails due to checkpoint)") - with self.nodes[0].assert_debug_log(['bad-fork-prior-to-checkpoint (code 67)']): + with self.nodes[0].assert_debug_log(['bad-fork-prior-to-checkpoint']): self.nodes[0].p2p.send_message(msg_headers(self.headers_fork)) self.nodes[0].p2p.wait_for_disconnect() diff --git a/test/functional/p2p_invalid_messages.py b/test/functional/p2p_invalid_messages.py index 58c72f89d8..f0ceb8e6a3 100755 --- a/test/functional/p2p_invalid_messages.py +++ b/test/functional/p2p_invalid_messages.py @@ -101,11 +101,10 @@ class InvalidMessagesTest(BitcoinTestFramework): msg_over_size = msg_unrecognized(str_data="b" * (valid_data_limit + 1)) assert len(msg_over_size.serialize()) == (msg_limit + 1) - with node.assert_debug_log(["Oversized message from peer=4, disconnecting"]): - # An unknown message type (or *any* message type) over - # MAX_PROTOCOL_MESSAGE_LENGTH should result in a disconnect. - node.p2p.send_message(msg_over_size) - node.p2p.wait_for_disconnect(timeout=4) + # An unknown message type (or *any* message type) over + # MAX_PROTOCOL_MESSAGE_LENGTH should result in a disconnect. + node.p2p.send_message(msg_over_size) + node.p2p.wait_for_disconnect(timeout=4) node.disconnect_p2ps() conn = node.add_p2p_connection(P2PDataStore()) @@ -168,7 +167,7 @@ class InvalidMessagesTest(BitcoinTestFramework): def test_checksum(self): conn = self.nodes[0].add_p2p_connection(P2PDataStore()) - with self.nodes[0].assert_debug_log(['ProcessMessages(badmsg, 2 bytes): CHECKSUM ERROR expected 78df0a04 was ffffffff']): + with self.nodes[0].assert_debug_log(['CHECKSUM ERROR (badmsg, 2 bytes), expected 78df0a04 was ffffffff']): msg = conn.build_message(msg_unrecognized(str_data="d")) cut_len = ( 4 + # magic diff --git a/test/functional/p2p_segwit.py b/test/functional/p2p_segwit.py index 98f6b1d71d..0c7edbf434 100755 --- a/test/functional/p2p_segwit.py +++ b/test/functional/p2p_segwit.py @@ -67,8 +67,8 @@ from test_framework.script import ( SIGHASH_ANYONECANPAY, SIGHASH_NONE, SIGHASH_SINGLE, - SegwitVersion1SignatureHash, - SignatureHash, + SegwitV0SignatureHash, + LegacySignatureHash, hash160, ) from test_framework.test_framework import BitcoinTestFramework @@ -103,7 +103,7 @@ def get_p2pkh_script(pubkeyhash): def sign_p2pk_witness_input(script, tx_to, in_idx, hashtype, value, key): """Add signature for a P2PK witness program.""" - tx_hash = SegwitVersion1SignatureHash(script, tx_to, in_idx, hashtype, value) + tx_hash = SegwitV0SignatureHash(script, tx_to, in_idx, hashtype, value) signature = key.sign_ecdsa(tx_hash) + chr(hashtype).encode('latin-1') tx_to.wit.vtxinwit[in_idx].scriptWitness.stack = [signature, script] tx_to.rehash() @@ -1489,7 +1489,7 @@ class SegWitTest(BitcoinTestFramework): tx2.vin.append(CTxIn(COutPoint(tx.sha256, 0), b"")) tx2.vout.append(CTxOut(tx.vout[0].nValue - 1000, script_wsh)) script = get_p2pkh_script(pubkeyhash) - sig_hash = SegwitVersion1SignatureHash(script, tx2, 0, SIGHASH_ALL, tx.vout[0].nValue) + sig_hash = SegwitV0SignatureHash(script, tx2, 0, SIGHASH_ALL, tx.vout[0].nValue) signature = key.sign_ecdsa(sig_hash) + b'\x01' # 0x1 is SIGHASH_ALL tx2.wit.vtxinwit.append(CTxInWitness()) tx2.wit.vtxinwit[0].scriptWitness.stack = [signature, pubkey] @@ -1543,7 +1543,7 @@ class SegWitTest(BitcoinTestFramework): tx5 = CTransaction() tx5.vin.append(CTxIn(COutPoint(tx4.sha256, 0), b"")) tx5.vout.append(CTxOut(tx4.vout[0].nValue - 1000, CScript([OP_TRUE]))) - (sig_hash, err) = SignatureHash(script_pubkey, tx5, 0, SIGHASH_ALL) + (sig_hash, err) = LegacySignatureHash(script_pubkey, tx5, 0, SIGHASH_ALL) signature = key.sign_ecdsa(sig_hash) + b'\x01' # 0x1 is SIGHASH_ALL tx5.vin[0].scriptSig = CScript([signature, pubkey]) tx5.rehash() @@ -1693,7 +1693,7 @@ class SegWitTest(BitcoinTestFramework): tx2.vout.append(CTxOut(tx.vout[0].nValue, CScript([OP_TRUE]))) script = get_p2pkh_script(pubkeyhash) - sig_hash = SegwitVersion1SignatureHash(script, tx2, 0, SIGHASH_ALL, tx.vout[0].nValue) + sig_hash = SegwitV0SignatureHash(script, tx2, 0, SIGHASH_ALL, tx.vout[0].nValue) signature = key.sign_ecdsa(sig_hash) + b'\x01' # 0x1 is SIGHASH_ALL # Check that we can't have a scriptSig diff --git a/test/functional/rpc_misc.py b/test/functional/rpc_misc.py index 8a3f8c6f06..3da9f05ca5 100755 --- a/test/functional/rpc_misc.py +++ b/test/functional/rpc_misc.py @@ -23,6 +23,13 @@ class RpcMiscTest(BitcoinTestFramework): def run_test(self): node = self.nodes[0] + self.log.info("test CHECK_NONFATAL") + assert_raises_rpc_error( + -1, + "Internal bug detected: 'request.params.size() != 100'", + lambda: node.echo(*[0] * 100), + ) + self.log.info("test getmemoryinfo") memory = node.getmemoryinfo()['locked'] assert_greater_than(memory['used'], 0) diff --git a/test/functional/rpc_rawtransaction.py b/test/functional/rpc_rawtransaction.py index ca0d47a5f8..74fea07350 100755 --- a/test/functional/rpc_rawtransaction.py +++ b/test/functional/rpc_rawtransaction.py @@ -454,7 +454,7 @@ class RawTransactionsTest(BitcoinTestFramework): # Thus, testmempoolaccept should reject testres = self.nodes[2].testmempoolaccept([rawTxSigned['hex']], 0.00001000)[0] assert_equal(testres['allowed'], False) - assert_equal(testres['reject-reason'], '256: absurdly-high-fee') + assert_equal(testres['reject-reason'], 'absurdly-high-fee') # and sendrawtransaction should throw assert_raises_rpc_error(-26, "absurdly-high-fee", self.nodes[2].sendrawtransaction, rawTxSigned['hex'], 0.00001000) # and the following calls should both succeed @@ -478,7 +478,7 @@ class RawTransactionsTest(BitcoinTestFramework): # Thus, testmempoolaccept should reject testres = self.nodes[2].testmempoolaccept([rawTxSigned['hex']])[0] assert_equal(testres['allowed'], False) - assert_equal(testres['reject-reason'], '256: absurdly-high-fee') + assert_equal(testres['reject-reason'], 'absurdly-high-fee') # and sendrawtransaction should throw assert_raises_rpc_error(-26, "absurdly-high-fee", self.nodes[2].sendrawtransaction, rawTxSigned['hex']) # and the following calls should both succeed diff --git a/test/functional/test_framework/script.py b/test/functional/test_framework/script.py index 384062b808..51aa9057f7 100644 --- a/test/functional/test_framework/script.py +++ b/test/functional/test_framework/script.py @@ -2,7 +2,7 @@ # Copyright (c) 2015-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. -"""Functionality to build scripts, as well as SignatureHash(). +"""Functionality to build scripts, as well as signature hash functions. This file is modified from python-bitcoinlib. """ @@ -608,7 +608,7 @@ def FindAndDelete(script, sig): return CScript(r) -def SignatureHash(script, txTo, inIdx, hashtype): +def LegacySignatureHash(script, txTo, inIdx, hashtype): """Consensus-correct SignatureHash Returns (hash, err) to precisely match the consensus-critical behavior of @@ -662,7 +662,7 @@ def SignatureHash(script, txTo, inIdx, hashtype): # Performance optimization probably not necessary for python tests, however. # Note that this corresponds to sigversion == 1 in EvalScript, which is used # for version 0 witnesses. -def SegwitVersion1SignatureHash(script, txTo, inIdx, hashtype, amount): +def SegwitV0SignatureHash(script, txTo, inIdx, hashtype, amount): hashPrevouts = 0 hashSequence = 0 diff --git a/test/functional/test_framework/script_util.py b/test/functional/test_framework/script_util.py new file mode 100755 index 0000000000..5ef67226c4 --- /dev/null +++ b/test/functional/test_framework/script_util.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 +# Copyright (c) 2019 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. +"""Useful Script constants and utils.""" +from test_framework.script import CScript + +# To prevent a "tx-size-small" policy rule error, a transaction has to have a +# non-witness size of at least 82 bytes (MIN_STANDARD_TX_NONWITNESS_SIZE in +# src/policy/policy.h). Considering a Tx with the smallest possible single +# input (blank, empty scriptSig), and with an output omitting the scriptPubKey, +# we get to a minimum size of 60 bytes: +# +# Tx Skeleton: 4 [Version] + 1 [InCount] + 1 [OutCount] + 4 [LockTime] = 10 bytes +# Blank Input: 32 [PrevTxHash] + 4 [Index] + 1 [scriptSigLen] + 4 [SeqNo] = 41 bytes +# Output: 8 [Amount] + 1 [scriptPubKeyLen] = 9 bytes +# +# Hence, the scriptPubKey of the single output has to have a size of at +# least 22 bytes, which corresponds to the size of a P2WPKH scriptPubKey. +# The following script constant consists of a single push of 21 bytes of 'a': +# <PUSH_21> <21-bytes of 'a'> +# resulting in a 22-byte size. It should be used whenever (small) fake +# scriptPubKeys are needed, to guarantee that the minimum transaction size is +# met. +DUMMY_P2WPKH_SCRIPT = CScript([b'a' * 21]) diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index 9c92091f1d..e0b523b718 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -197,6 +197,7 @@ BASE_SCRIPTS = [ 'feature_uacomment.py', 'wallet_coinbase_category.py', 'feature_filelock.py', + 'feature_loadblock.py', 'p2p_dos_header_tree.py', 'p2p_unrequested_blocks.py', 'feature_includeconf.py', diff --git a/test/functional/wallet_address_types.py b/test/functional/wallet_address_types.py index b72f5c6008..479d67fb66 100755 --- a/test/functional/wallet_address_types.py +++ b/test/functional/wallet_address_types.py @@ -80,6 +80,9 @@ class AddressTypeTest(BitcoinTestFramework): ["-changetype=p2sh-segwit"], [], ] + # whitelist all peers to speed up tx relay / mempool sync + for args in self.extra_args: + args.append("-whitelist=127.0.0.1") def skip_test_if_missing_module(self): self.skip_if_no_wallet() diff --git a/test/functional/wallet_backup.py b/test/functional/wallet_backup.py index 93178c5ab2..bb835dc811 100755 --- a/test/functional/wallet_backup.py +++ b/test/functional/wallet_backup.py @@ -48,7 +48,13 @@ class WalletBackupTest(BitcoinTestFramework): self.num_nodes = 4 self.setup_clean_chain = True # nodes 1, 2,3 are spenders, let's give them a keypool=100 - self.extra_args = [["-keypool=100"], ["-keypool=100"], ["-keypool=100"], []] + # whitelist all peers to speed up tx relay / mempool sync + self.extra_args = [ + ["-keypool=100", "-whitelist=127.0.0.1"], + ["-keypool=100", "-whitelist=127.0.0.1"], + ["-keypool=100", "-whitelist=127.0.0.1"], + ["-whitelist=127.0.0.1"] + ] self.rpc_timeout = 120 def skip_test_if_missing_module(self): diff --git a/test/functional/wallet_multiwallet.py b/test/functional/wallet_multiwallet.py index 68bc45f986..ce0b7e8782 100755 --- a/test/functional/wallet_multiwallet.py +++ b/test/functional/wallet_multiwallet.py @@ -339,14 +339,10 @@ class MultiWalletTest(BitcoinTestFramework): self.log.info("Fail -upgradewallet that results in downgrade") assert_raises_rpc_error( -4, - "Wallet loading failed.", + 'Wallet loading failed: Error loading {}: Wallet requires newer version of {}'.format( + wallet_dir('high_minversion', 'wallet.dat'), self.config['environment']['PACKAGE_NAME']), lambda: self.nodes[0].loadwallet(filename='high_minversion'), ) - self.stop_node( - i=0, - expected_stderr='Error: Error loading {}: Wallet requires newer version of Bitcoin Core'.format( - wallet_dir('high_minversion', 'wallet.dat')), - ) if __name__ == '__main__': diff --git a/test/lint/README.md b/test/lint/README.md index 15974a3598..f415d619ee 100644 --- a/test/lint/README.md +++ b/test/lint/README.md @@ -7,6 +7,8 @@ Check for missing documentation of command line options. commit-script-check.sh ====================== Verification of [scripted diffs](/doc/developer-notes.md#scripted-diffs). +Scripted diffs are only assumed to run on the latest LTS release of Ubuntu. Running them on other operating systems +might require installing GNU tools, such as GNU sed. git-subtree-check.sh ==================== diff --git a/test/lint/lint-filenames.sh b/test/lint/lint-filenames.sh index 5391e43d91..6716cac0fe 100755 --- a/test/lint/lint-filenames.sh +++ b/test/lint/lint-filenames.sh @@ -12,7 +12,7 @@ export LC_ALL=C EXIT_CODE=0 OUTPUT=$(git ls-files --full-name -- "*.[cC][pP][pP]" "*.[hH]" "*.[pP][yY]" "*.[sS][hH]" | \ grep -vE '^[a-z0-9_./-]+$' | \ - grep -vE '^src/(secp256k1|univalue)/') + grep -vE '^src/(secp256k1/|univalue/|test/fuzz/FuzzedDataProvider.h)') if [[ ${OUTPUT} != "" ]]; then echo "Use only lowercase alphanumerics (a-z0-9), underscores (_), hyphens (-) and dots (.)" diff --git a/test/lint/lint-include-guards.sh b/test/lint/lint-include-guards.sh index 464969794b..0d654e796e 100755 --- a/test/lint/lint-include-guards.sh +++ b/test/lint/lint-include-guards.sh @@ -10,7 +10,7 @@ export LC_ALL=C HEADER_ID_PREFIX="BITCOIN_" HEADER_ID_SUFFIX="_H" -REGEXP_EXCLUDE_FILES_WITH_PREFIX="src/(crypto/ctaes/|leveldb/|secp256k1/|tinyformat.h|univalue/)" +REGEXP_EXCLUDE_FILES_WITH_PREFIX="src/(crypto/ctaes/|leveldb/|secp256k1/|test/fuzz/FuzzedDataProvider.h|tinyformat.h|univalue/)" EXIT_CODE=0 for HEADER_FILE in $(git ls-files -- "*.h" | grep -vE "^${REGEXP_EXCLUDE_FILES_WITH_PREFIX}") diff --git a/test/sanitizer_suppressions/ubsan b/test/sanitizer_suppressions/ubsan index 643272de52..e7c690fabe 100644 --- a/test/sanitizer_suppressions/ubsan +++ b/test/sanitizer_suppressions/ubsan @@ -1,9 +1,19 @@ +# -fsanitize=undefined suppressions +# ================================= alignment:move.h alignment:prevector.h -bool:wallet/wallet.cpp float-divide-by-zero:policy/fees.cpp float-divide-by-zero:validation.cpp float-divide-by-zero:wallet/wallet.cpp + +# -fsanitize=integer suppressions +# =============================== +# Unsigned integer overflow occurs when the result of an unsigned integer +# computation cannot be represented in its type. Unlike signed integer overflow, +# this is not undefined behavior, but it is often unintentional. The list below +# 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:arith_uint256.h unsigned-integer-overflow:basic_string.h unsigned-integer-overflow:bench/bench.h @@ -32,4 +42,3 @@ unsigned-integer-overflow:stl_bvector.h unsigned-integer-overflow:txmempool.cpp unsigned-integer-overflow:util/strencodings.cpp unsigned-integer-overflow:validation.cpp -vptr:fs.cpp |