diff options
181 files changed, 3172 insertions, 2357 deletions
diff --git a/.cirrus.yml b/.cirrus.yml index 517cd93585..f4a3878ed8 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -16,7 +16,7 @@ task: ccache_cache: folder: "/tmp/ccache_dir" install_script: - - pkg install -y autoconf automake boost-libs git gmake libevent libtool openssl pkgconf python3 ccache + - pkg install -y autoconf automake boost-libs git gmake libevent libtool pkgconf python3 ccache - ./contrib/install_db4.sh $(pwd) - ccache --max-size=${CCACHE_SIZE} configure_script: diff --git a/.travis.yml b/.travis.yml index 73e62cd2b0..8a04326bab 100644 --- a/.travis.yml +++ b/.travis.yml @@ -43,12 +43,11 @@ before_cache: stages: - lint - test - - extended-lint env: global: - CI_RETRY_EXE="travis_retry" - CI_WAIT="while sleep 500; do echo .; done" - - CACHE_ERR_MSG="Error! Initial build successful, but not enough time remains to run later build stages and tests. Please manually re-run this job by using the travis restart button or asking a bitcoin maintainer to restart. The next run should not time out because the build cache has been saved." + - CACHE_ERR_MSG="Error! Initial build successful, but not enough time remains to run later build stages and tests. See https://docs.travis-ci.com/user/customizing-the-build#build-timeouts . Please manually re-run this job by using the travis restart button. The next run should not time out because the build cache has been saved." before_install: - set -o errexit; source ./ci/test/00_setup_env.sh - set -o errexit; source ./ci/test/03_before_install.sh @@ -82,27 +81,20 @@ jobs: script: - set -o errexit; source ./ci/lint/06_script.sh - - stage: extended-lint - name: 'extended lint [runtime >= 60 seconds]' - env: - cache: false - language: python - python: '3.5' - install: - - set -o errexit; source ./ci/extended_lint/04_install.sh - before_script: - - set -o errexit; source ./ci/lint/05_before_script.sh - script: - - set -o errexit; source ./ci/extended_lint/06_script.sh - - stage: test - name: 'ARM [GOAL: install] [unit tests, functional tests]' + name: 'ARM [GOAL: install] [bionic] [unit tests, functional tests]' arch: arm64 env: >- FILE_ENV="./ci/test/00_setup_env_arm.sh" QEMU_USER_CMD="" # Can run the tests natively without qemu - stage: test + name: 'S390x [GOAL: install] [bionic] [unit tests, functional tests]' + arch: s390x + env: >- + FILE_ENV="./ci/test/00_setup_env_s390x.sh" + + - stage: test name: 'Win64 [GOAL: deploy] [unit tests, no gui, no functional tests]' env: >- FILE_ENV="./ci/test/00_setup_env_win64.sh" @@ -144,7 +136,7 @@ jobs: FILE_ENV="./ci/test/00_setup_env_native_nowallet.sh" - stage: test - name: 'macOS 10.10 [GOAL: deploy] [no functional tests]' + name: 'macOS 10.12 [GOAL: deploy] [no functional tests]' env: >- FILE_ENV="./ci/test/00_setup_env_mac.sh" @@ -152,8 +144,8 @@ jobs: 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 + # Xcode 11.2.1, macOS 10.14, JDK 13.0.1, SDK 10.15 # https://docs.travis-ci.com/user/reference/osx/#macos-version - osx_image: xcode11 + osx_image: xcode11.2 env: >- FILE_ENV="./ci/test/00_setup_env_mac_host.sh" diff --git a/build_msvc/README.md b/build_msvc/README.md index 59be5298ad..704470cac8 100644 --- a/build_msvc/README.md +++ b/build_msvc/README.md @@ -12,7 +12,7 @@ Quick Start The minimal steps required to build Bitcoin Core with the msbuild toolchain are below. More detailed instructions are contained in the following sections. ``` -vcpkg install --triplet x64-windows-static boost-filesystem boost-multi-index boost-signals2 boost-test boost-thread libevent openssl zeromq berkeleydb rapidcheck double-conversion +vcpkg install --triplet x64-windows-static boost-filesystem boost-multi-index boost-signals2 boost-test boost-thread libevent zeromq berkeleydb rapidcheck double-conversion py -3 build_msvc\msvc-autogen.py msbuild /m build_msvc\bitcoin.sln /p:Platform=x64 /p:Configuration=Release /t:build ``` @@ -33,7 +33,6 @@ The [external dependencies](https://github.com/bitcoin/bitcoin/blob/master/doc/d - Boost - DoubleConversion - libevent -- OpenSSL - Qt5 - RapidCheck - ZeroMQ diff --git a/build_msvc/bench_bitcoin/bench_bitcoin.vcxproj.in b/build_msvc/bench_bitcoin/bench_bitcoin.vcxproj.in index 56401d7618..128c1bd8e7 100644 --- a/build_msvc/bench_bitcoin/bench_bitcoin.vcxproj.in +++ b/build_msvc/bench_bitcoin/bench_bitcoin.vcxproj.in @@ -42,6 +42,9 @@ <ProjectReference Include="..\libleveldb\libleveldb.vcxproj"> <Project>{18430fef-6b61-4c53-b396-718e02850f1b}</Project> </ProjectReference> + <ProjectReference Include="..\libtest_util\libtest_util.vcxproj"> + <Project>{1e065f03-3566-47d0-8fa9-daa72b084e7d}</Project> + </ProjectReference> </ItemGroup> <Target Name="RawBenchHeaderGen" BeforeTargets="PrepareForBuild"> <PropertyGroup> diff --git a/build_msvc/bitcoin.sln b/build_msvc/bitcoin.sln index d4b83b6529..9dff0e316e 100644 --- a/build_msvc/bitcoin.sln +++ b/build_msvc/bitcoin.sln @@ -44,6 +44,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libbitcoin_qt", "libbitcoin EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bitcoin-qt", "bitcoin-qt\bitcoin-qt.vcxproj", "{7E99172D-7FF2-4CB6-B736-AC9B76ED412A}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libtest_util", "libtest_util\libtest_util.vcxproj", "{868474FD-35F6-4400-8EED-30A33E7521D4}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -220,11 +222,21 @@ Global {7E99172D-7FF2-4CB6-B736-AC9B76ED412A}.Release|x64.Build.0 = Release|x64 {7E99172D-7FF2-4CB6-B736-AC9B76ED412A}.Release|x86.ActiveCfg = Release|Win32 {7E99172D-7FF2-4CB6-B736-AC9B76ED412A}.Release|x86.Build.0 = Release|Win32 + {868474FD-35F6-4400-8EED-30A33E7521D4}.Debug|x64.ActiveCfg = Debug|x64 + {868474FD-35F6-4400-8EED-30A33E7521D4}.Debug|x64.Build.0 = Debug|x64 + {868474FD-35F6-4400-8EED-30A33E7521D4}.Debug|x86.ActiveCfg = Debug|Win32 + {868474FD-35F6-4400-8EED-30A33E7521D4}.Debug|x86.Build.0 = Debug|Win32 + {868474FD-35F6-4400-8EED-30A33E7521D4}.Release|x64.ActiveCfg = Release|x64 + {868474FD-35F6-4400-8EED-30A33E7521D4}.Release|x64.Build.0 = Release|x64 + {868474FD-35F6-4400-8EED-30A33E7521D4}.Release|x86.ActiveCfg = Release|Win32 + {868474FD-35F6-4400-8EED-30A33E7521D4}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {8AA72EDA-2CD4-4564-B1E4-688B760EEEE9} + SolutionGuid = {8AA72EDA-2CD4-4564-B1E4-688B760EEEE9} + SolutionGuid = {8607C0F4-F33D-41B8-8D51-18E366A0F8DF} + SolutionGuid = {58AAB032-7274-49BD-845E-5EF4DBB69B70} EndGlobalSection EndGlobal diff --git a/build_msvc/libtest_util/libtest_util.vcxproj.in b/build_msvc/libtest_util/libtest_util.vcxproj.in new file mode 100644 index 0000000000..b5e844010e --- /dev/null +++ b/build_msvc/libtest_util/libtest_util.vcxproj.in @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="..\common.init.vcxproj" /> + <PropertyGroup Label="Globals"> + <ProjectGuid>{868474FD-35F6-4400-8EED-30A33E7521D4}</ProjectGuid> + </PropertyGroup> + <PropertyGroup Label="Configuration"> + <ConfigurationType>StaticLibrary</ConfigurationType> + </PropertyGroup> + <ItemGroup> +@SOURCE_FILES@ + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <Import Project="..\common.vcxproj" /> +</Project> diff --git a/build_msvc/msvc-autogen.py b/build_msvc/msvc-autogen.py index 5ddda3c03e..3951438408 100644 --- a/build_msvc/msvc-autogen.py +++ b/build_msvc/msvc-autogen.py @@ -18,6 +18,7 @@ libs = [ 'libbitcoin_wallet', 'libbitcoin_zmq', 'bench_bitcoin', + 'libtest_util', ] ignore_list = [ diff --git a/build_msvc/test_bitcoin/test_bitcoin.vcxproj b/build_msvc/test_bitcoin/test_bitcoin.vcxproj index 1d05ff6cba..96d20a2720 100644 --- a/build_msvc/test_bitcoin/test_bitcoin.vcxproj +++ b/build_msvc/test_bitcoin/test_bitcoin.vcxproj @@ -42,6 +42,9 @@ <ProjectReference Include="..\libbitcoin_zmq\libbitcoin_zmq.vcxproj"> <Project>{792d487f-f14c-49fc-a9de-3fc150f31c3f}</Project> </ProjectReference> + <ProjectReference Include="..\libtest_util\libtest_util.vcxproj"> + <Project>{1e065f03-3566-47d0-8fa9-daa72b084e7d}</Project> + </ProjectReference> <ProjectReference Include="..\libunivalue\libunivalue.vcxproj"> <Project>{5724ba7d-a09a-4ba8-800b-c4c1561b3d69}</Project> </ProjectReference> diff --git a/build_msvc/vcpkg-packages.txt b/build_msvc/vcpkg-packages.txt index 082a13f1cf..27e2bbdcde 100644 --- a/build_msvc/vcpkg-packages.txt +++ b/build_msvc/vcpkg-packages.txt @@ -1 +1 @@ -berkeleydb boost-filesystem boost-multi-index boost-signals2 boost-test boost-thread libevent openssl rapidcheck zeromq double-conversion
\ No newline at end of file +berkeleydb boost-filesystem boost-multi-index boost-signals2 boost-test boost-thread libevent[thread] rapidcheck zeromq double-conversion
\ No newline at end of file diff --git a/ci/README.md b/ci/README.md index fb1cd7460b..880e49b459 100644 --- a/ci/README.md +++ b/ci/README.md @@ -8,11 +8,21 @@ and numbered according to which stage and lifecycle step it belongs to. ### Running a stage locally +Be aware that the tests will be built and run in-place, so please run at your own risk. +If the repository is not a fresh git clone, you might have to clean files from previous builds or test runs first. + +The ci needs to perform various sysadmin tasks such as installing packages or writing to the user's home directory. +While most of the actions are done inside a docker container, this is not possible for all. Thus, cache directories, +such as the depends cache or ccache, are mounted as read-write into the docker container. While it should be fine to run +the ci system locally on you development box, the ci scripts can generally be assumed to have received less review and +testing compared to other parts of the codebase. If you want to keep the work tree clean, you might want to run the ci +system in a virtual machine with a Linux operating system of your choice. + To allow for a wide range of tested environments, but also ensure reproducibility to some extent, the test stage requires `docker` to be installed. To install all requirements on Ubuntu, run ``` -sudo apt install docker.io bash git +sudo apt install docker.io bash ``` To run the default test stage, @@ -26,6 +36,3 @@ To run the test stage with a specific configuration, ``` FILE_ENV="./ci/test/00_setup_env_arm.sh" ./ci/test_run_all.sh ``` - -Be aware that the tests will be build and run in-place, so please run at your own risk. -If the repository is not a fresh git clone, you might have to clean files from previous builds or test runs first. diff --git a/ci/extended_lint/04_install.sh b/ci/extended_lint/04_install.sh deleted file mode 100755 index 123d874a84..0000000000 --- a/ci/extended_lint/04_install.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/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 - -CPPCHECK_VERSION=1.86 -curl -s https://codeload.github.com/danmar/cppcheck/tar.gz/${CPPCHECK_VERSION} | tar -zxf - --directory /tmp/ -(cd /tmp/cppcheck-${CPPCHECK_VERSION}/ && make CFGDIR=/tmp/cppcheck-${CPPCHECK_VERSION}/cfg/ > /dev/null) -export PATH="$PATH:/tmp/cppcheck-${CPPCHECK_VERSION}/" diff --git a/ci/extended_lint/06_script.sh b/ci/extended_lint/06_script.sh deleted file mode 100755 index e8228c9c4d..0000000000 --- a/ci/extended_lint/06_script.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/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 - -test/lint/extended-lint-all.sh diff --git a/ci/lint/04_install.sh b/ci/lint/04_install.sh index 12c3bfce45..8b2d609504 100755 --- a/ci/lint/04_install.sh +++ b/ci/lint/04_install.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # -# Copyright (c) 2018 The Bitcoin Core developers +# Copyright (c) 2018-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. @@ -8,6 +8,7 @@ export LC_ALL=C travis_retry pip3 install codespell==1.15.0 travis_retry pip3 install flake8==3.7.8 +travis_retry pip3 install yq 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/ diff --git a/ci/test/00_setup_env.sh b/ci/test/00_setup_env.sh index c65054cf9e..1f485fbec4 100755 --- a/ci/test/00_setup_env.sh +++ b/ci/test/00_setup_env.sh @@ -6,6 +6,12 @@ export LC_ALL=C.UTF-8 +# The root dir. +# The ci system copies this folder. +# This is where the build is done (depends and dist). +BASE_ROOT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )"/../../ >/dev/null 2>&1 && pwd ) +export BASE_ROOT_DIR + echo "Setting specific values in env" if [ -n "${FILE_ENV}" ]; then set -o errexit; @@ -13,13 +19,11 @@ if [ -n "${FILE_ENV}" ]; then source "${FILE_ENV}" fi -BASE_ROOT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )"/../../ >/dev/null 2>&1 && pwd ) -export BASE_ROOT_DIR - echo "Fallback to default values in env (if not yet set)" # The number of parallel jobs to pass down to make and test_runner.py export MAKEJOBS=${MAKEJOBS:--j4} # A folder for the ci system to put temporary files (ccache, datadirs for tests, ...) +# This folder only exists on the ci host. export BASE_SCRATCH_DIR=${BASE_SCRATCH_DIR:-$BASE_ROOT_DIR/ci/scratch/} # What host to compile for. See also ./depends/README.md # Tests that need cross-compilation export the appropriate HOST. @@ -37,15 +41,18 @@ export BOOST_TEST_RANDOM=${BOOST_TEST_RANDOM:-1} export CCACHE_SIZE=${CCACHE_SIZE:-100M} export CCACHE_TEMPDIR=${CCACHE_TEMPDIR:-/tmp/.ccache-temp} export CCACHE_COMPRESS=${CCACHE_COMPRESS:-1} +# The cache dir. +# This folder exists on the ci host and ci guest. Changes are propagated back and forth. export CCACHE_DIR=${CCACHE_DIR:-$BASE_SCRATCH_DIR/.ccache} -# Folder where the build is done (depends and dist). Can not be changed and is equal to the root of the git repo -export BASE_BUILD_DIR=${BASE_BUILD_DIR:-$BASE_ROOT_DIR} -# Folder where the build is done (bin and lib). Can not be changed. -export BASE_OUTDIR=${BASE_OUTDIR:-$BASE_BUILD_DIR/out/$HOST} +# The depends dir. +# This folder exists on the ci host and ci guest. Changes are propagated back and forth. +export DEPENDS_DIR=${DEPENDS_DIR:-$BASE_ROOT_DIR/depends} +# Folder where the build is done (bin and lib). +export BASE_OUTDIR=${BASE_OUTDIR:-$BASE_SCRATCH_DIR/out/$HOST} export SDK_URL=${SDK_URL:-https://bitcoincore.org/depends-sources/sdks} export WINEDEBUG=${WINEDEBUG:-fixme-all} -export DOCKER_PACKAGES=${DOCKER_PACKAGES:-build-essential libtool autotools-dev automake pkg-config bsdmainutils curl ca-certificates ccache python3} +export DOCKER_PACKAGES=${DOCKER_PACKAGES:-build-essential libtool autotools-dev automake pkg-config bsdmainutils curl ca-certificates ccache python3 rsync git} export GOAL=${GOAL:-install} -export DIR_QA_ASSETS=${DIR_QA_ASSETS:-${BASE_BUILD_DIR}/qa-assets} +export DIR_QA_ASSETS=${DIR_QA_ASSETS:-${BASE_SCRATCH_DIR}/qa-assets} export PATH=${BASE_ROOT_DIR}/ci/retry:$PATH export CI_RETRY_EXE=${CI_RETRY_EXE:retry} diff --git a/ci/test/00_setup_env_mac.sh b/ci/test/00_setup_env_mac.sh index f384ba9263..af166b6ca7 100644 --- a/ci/test/00_setup_env_mac.sh +++ b/ci/test/00_setup_env_mac.sh @@ -6,7 +6,7 @@ export LC_ALL=C.UTF-8 -export HOST=x86_64-apple-darwin14 +export HOST=x86_64-apple-darwin16 export PACKAGES="cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools python3-dev python3-setuptools" export OSX_SDK=10.11 export RUN_UNIT_TESTS=false diff --git a/ci/test/00_setup_env_mac_host.sh b/ci/test/00_setup_env_mac_host.sh index aa68a5700e..0b437a723f 100644 --- a/ci/test/00_setup_env_mac_host.sh +++ b/ci/test/00_setup_env_mac_host.sh @@ -6,7 +6,7 @@ export LC_ALL=C.UTF-8 -export HOST=x86_64-apple-darwin14 +export HOST=x86_64-apple-darwin16 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 diff --git a/ci/test/00_setup_env_native_asan.sh b/ci/test/00_setup_env_native_asan.sh index 293f37fedf..2ffd3c5107 100644 --- a/ci/test/00_setup_env_native_asan.sh +++ b/ci/test/00_setup_env_native_asan.sh @@ -6,7 +6,8 @@ export LC_ALL=C.UTF-8 -export PACKAGES="clang llvm python3-zmq qtbase5-dev qttools5-dev-tools libssl1.0-dev libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-test-dev libboost-thread-dev libdb5.3++-dev libminiupnpc-dev libzmq3-dev libqrencode-dev" +export PACKAGES="clang-8 llvm-8 python3-zmq qtbase5-dev qttools5-dev-tools libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-test-dev libboost-thread-dev libdb5.3++-dev libminiupnpc-dev libzmq3-dev libqrencode-dev" +# Use clang-8 instead of default clang (which is clang-6 on Bionic) to avoid spurious segfaults when running on ppc64le export NO_DEPENDS=1 export GOAL="install" -export BITCOIN_CONFIG="--enable-zmq --with-incompatible-bdb --with-gui=qt5 CPPFLAGS=-DDEBUG_LOCKORDER --with-sanitizers=address,integer,undefined CC=clang CXX=clang++" +export BITCOIN_CONFIG="--enable-zmq --with-incompatible-bdb --with-gui=qt5 CPPFLAGS='-DARENA_DEBUG -DDEBUG_LOCKORDER' --with-sanitizers=address,integer,undefined CC=clang-8 CXX=clang++-8" diff --git a/ci/test/00_setup_env_native_fuzz.sh b/ci/test/00_setup_env_native_fuzz.sh index 2e9f529216..b0405bb762 100644 --- a/ci/test/00_setup_env_native_fuzz.sh +++ b/ci/test/00_setup_env_native_fuzz.sh @@ -6,10 +6,11 @@ export LC_ALL=C.UTF-8 -export PACKAGES="clang llvm python3 libssl1.0-dev libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-test-dev libboost-thread-dev" +export PACKAGES="clang-8 llvm-8 python3 libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-test-dev libboost-thread-dev" export NO_DEPENDS=1 export RUN_UNIT_TESTS=false export RUN_FUNCTIONAL_TESTS=false export RUN_FUZZ_TESTS=true export GOAL="install" -export BITCOIN_CONFIG="--enable-fuzz --with-sanitizers=fuzzer,address,undefined CC=clang CXX=clang++" +export BITCOIN_CONFIG="--enable-fuzz --with-sanitizers=fuzzer,address,undefined CC=clang-8 CXX=clang++-8" +# Use clang-8, instead of default clang on bionic, which is clang-6 and does not come with libfuzzer on aarch64 diff --git a/ci/test/00_setup_env_native_trusty.sh b/ci/test/00_setup_env_native_trusty.sh index fbf1488f07..893c1f6b53 100644 --- a/ci/test/00_setup_env_native_trusty.sh +++ b/ci/test/00_setup_env_native_trusty.sh @@ -7,7 +7,7 @@ export LC_ALL=C.UTF-8 export DOCKER_NAME_TAG=ubuntu:14.04 -export PACKAGES="python3-zmq qtbase5-dev qttools5-dev-tools libicu-dev libpng-dev libssl-dev libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-test-dev libboost-thread-dev libdb5.1++-dev libzmq3-dev libqrencode-dev" +export PACKAGES="python3-zmq qtbase5-dev qttools5-dev-tools libicu-dev libpng-dev libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-test-dev libboost-thread-dev libdb5.1++-dev libzmq3-dev libqrencode-dev" export NO_DEPENDS=1 export RUN_FUNCTIONAL_TESTS=false export GOAL="install" diff --git a/ci/test/00_setup_env_native_tsan.sh b/ci/test/00_setup_env_native_tsan.sh index afc082d6cf..e9b7a7bba1 100644 --- a/ci/test/00_setup_env_native_tsan.sh +++ b/ci/test/00_setup_env_native_tsan.sh @@ -7,7 +7,11 @@ export LC_ALL=C.UTF-8 export DOCKER_NAME_TAG=ubuntu:16.04 -export PACKAGES="clang llvm python3-zmq qtbase5-dev qttools5-dev-tools libssl-dev libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-test-dev libboost-thread-dev libdb5.3++-dev libminiupnpc-dev libzmq3-dev libqrencode-dev" +export PACKAGES="clang llvm python3-zmq qtbase5-dev qttools5-dev-tools libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-test-dev libboost-thread-dev libdb5.3++-dev libminiupnpc-dev libzmq3-dev libqrencode-dev" export NO_DEPENDS=1 export GOAL="install" -export BITCOIN_CONFIG="--enable-zmq --disable-wallet --with-gui=qt5 CPPFLAGS=-DDEBUG_LOCKORDER --with-sanitizers=thread --disable-hardening --disable-asm CC=clang CXX=clang++" +export BITCOIN_CONFIG="--enable-zmq --disable-wallet --with-gui=qt5 CPPFLAGS='-DARENA_DEBUG -DDEBUG_LOCKORDER' --with-sanitizers=thread --disable-hardening --disable-asm CC=clang CXX=clang++" + +# xenial comes with old clang versions that can not parse the sanitizer suppressions files +# Remove unparseable lines as a hacky workaround +sed -i '/^implicit-/d' "${BASE_ROOT_DIR}/test/sanitizer_suppressions/ubsan" diff --git a/ci/test/00_setup_env_s390x.sh b/ci/test/00_setup_env_s390x.sh new file mode 100644 index 0000000000..89660c7fa4 --- /dev/null +++ b/ci/test/00_setup_env_s390x.sh @@ -0,0 +1,15 @@ +#!/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=s390x-unknown-linux-gnu +export PACKAGES="clang llvm python3-zmq qtbase5-dev qttools5-dev-tools libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-test-dev libboost-thread-dev libdb5.3++-dev libminiupnpc-dev libzmq3-dev libqrencode-dev" +export NO_DEPENDS=1 +export RUN_UNIT_TESTS=true +export RUN_FUNCTIONAL_TESTS=true +export GOAL="install" +export BITCOIN_CONFIG="--enable-reduce-exports --with-incompatible-bdb" diff --git a/ci/test/04_install.sh b/ci/test/04_install.sh index 271ae82e5c..b9eaae0b0d 100755 --- a/ci/test/04_install.sh +++ b/ci/test/04_install.sh @@ -25,8 +25,6 @@ if [ "$TRAVIS_OS_NAME" == "osx" ]; then 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 @@ -35,16 +33,10 @@ fi mkdir -p "${BASE_SCRATCH_DIR}" mkdir -p "${CCACHE_DIR}" -if [ ! -d ${DIR_QA_ASSETS} ]; then - git clone https://github.com/bitcoin-core/qa-assets ${DIR_QA_ASSETS} -fi -export DIR_FUZZ_IN=${DIR_QA_ASSETS}/fuzz_seed_corpus/ - -mkdir -p "${BASE_BUILD_DIR}/sanitizer-output/" 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" +export LSAN_OPTIONS="suppressions=${BASE_ROOT_DIR}/test/sanitizer_suppressions/lsan" +export TSAN_OPTIONS="suppressions=${BASE_ROOT_DIR}/test/sanitizer_suppressions/tsan:log_path=${BASE_SCRATCH_DIR}/sanitizer-output/tsan" +export UBSAN_OPTIONS="suppressions=${BASE_ROOT_DIR}/test/sanitizer_suppressions/ubsan:print_stacktrace=1:halt_on_error=1:report_error_type=1" env | grep -E '^(BITCOIN_CONFIG|CCACHE_|WINEDEBUG|LC_ALL|BOOST_TEST_RANDOM|CONFIG_SHELL|(ASAN|LSAN|TSAN|UBSAN)_OPTIONS)' | tee /tmp/env if [[ $HOST = *-mingw32 ]]; then DOCKER_ADMIN="--cap-add SYS_ADMIN" @@ -52,19 +44,27 @@ elif [[ $BITCOIN_CONFIG = *--with-sanitizers=*address* ]]; then # If ran with (A DOCKER_ADMIN="--cap-add SYS_PTRACE" fi +export P_CI_DIR="$PWD" + if [ -z "$RUN_CI_ON_HOST" ]; then echo "Creating $DOCKER_NAME_TAG container to run in" ${CI_RETRY_EXE} docker pull "$DOCKER_NAME_TAG" - DOCKER_ID=$(docker run $DOCKER_ADMIN -idt --mount type=bind,src=$BASE_BUILD_DIR,dst=$BASE_BUILD_DIR --mount type=bind,src=$CCACHE_DIR,dst=$CCACHE_DIR -w $BASE_BUILD_DIR --env-file /tmp/env $DOCKER_NAME_TAG) + DOCKER_ID=$(docker run $DOCKER_ADMIN -idt \ + --mount type=bind,src=$BASE_ROOT_DIR,dst=/ro_base,readonly \ + --mount type=bind,src=$CCACHE_DIR,dst=$CCACHE_DIR \ + --mount type=bind,src=$DEPENDS_DIR,dst=$DEPENDS_DIR \ + -w $BASE_ROOT_DIR \ + --env-file /tmp/env \ + $DOCKER_NAME_TAG) DOCKER_EXEC () { - docker exec $DOCKER_ID bash -c "export PATH=$BASE_SCRATCH_DIR/bins/:\$PATH && cd $PWD && $*" + docker exec $DOCKER_ID bash -c "export PATH=$BASE_SCRATCH_DIR/bins/:\$PATH && cd $P_CI_DIR && $*" } else echo "Running on host system without docker wrapper" DOCKER_EXEC () { - bash -c "export PATH=$BASE_SCRATCH_DIR/bins/:\$PATH && cd $PWD && $*" + bash -c "export PATH=$BASE_SCRATCH_DIR/bins/:\$PATH && cd $P_CI_DIR && $*" } fi @@ -74,6 +74,8 @@ if [ "$TRAVIS_OS_NAME" == "osx" ]; then else DOCKER_EXEC free -m -h DOCKER_EXEC echo "Number of CPUs \(nproc\):" \$\(nproc\) + DOCKER_EXEC echo "Free disk space:" + DOCKER_EXEC df -h fi if [ -n "$DPKG_ADD_ARCH" ]; then @@ -85,6 +87,18 @@ if [ "$TRAVIS_OS_NAME" != "osx" ]; then ${CI_RETRY_EXE} DOCKER_EXEC apt-get install --no-install-recommends --no-upgrade -y $PACKAGES $DOCKER_PACKAGES fi +if [ ! -d ${DIR_QA_ASSETS} ]; then + DOCKER_EXEC git clone https://github.com/bitcoin-core/qa-assets ${DIR_QA_ASSETS} +fi +export DIR_FUZZ_IN=${DIR_QA_ASSETS}/fuzz_seed_corpus/ + +DOCKER_EXEC mkdir -p "${BASE_SCRATCH_DIR}/sanitizer-output/" + +if [ -z "$RUN_CI_ON_HOST" ]; then + echo "Create $BASE_ROOT_DIR" + DOCKER_EXEC rsync -a /ro_base/ $BASE_ROOT_DIR +fi + if [ "$USE_BUSY_BOX" = "true" ]; then echo "Setup to use BusyBox utils" DOCKER_EXEC mkdir -p $BASE_SCRATCH_DIR/bins/ diff --git a/ci/test/05_before_script.sh b/ci/test/05_before_script.sh index a0488f0807..51a5830682 100755 --- a/ci/test/05_before_script.sh +++ b/ci/test/05_before_script.sh @@ -13,13 +13,13 @@ else DOCKER_EXEC echo \> \$HOME/.bitcoin fi -mkdir -p depends/SDKs depends/sdk-sources +DOCKER_EXEC mkdir -p ${DEPENDS_DIR}/SDKs ${DEPENDS_DIR}/sdk-sources -if [ -n "$OSX_SDK" ] && [ ! -f depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz ]; then - curl --location --fail $SDK_URL/MacOSX${OSX_SDK}.sdk.tar.gz -o depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz +if [ -n "$OSX_SDK" ] && [ ! -f ${DEPENDS_DIR}/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz ]; then + curl --location --fail $SDK_URL/MacOSX${OSX_SDK}.sdk.tar.gz -o ${DEPENDS_DIR}/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz fi -if [ -n "$OSX_SDK" ] && [ -f depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz ]; then - tar -C depends/SDKs -xf depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz +if [ -n "$OSX_SDK" ] && [ -f ${DEPENDS_DIR}/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz ]; then + DOCKER_EXEC tar -C ${DEPENDS_DIR}/SDKs -xf ${DEPENDS_DIR}/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz fi if [[ $HOST = *-mingw32 ]]; then DOCKER_EXEC update-alternatives --set $HOST-g++ \$\(which $HOST-g++-posix\) diff --git a/ci/test/06_script_a.sh b/ci/test/06_script_a.sh index c4dc22bdd8..98b75d7497 100755 --- a/ci/test/06_script_a.sh +++ b/ci/test/06_script_a.sh @@ -6,7 +6,7 @@ export LC_ALL=C.UTF-8 -BITCOIN_CONFIG_ALL="--disable-dependency-tracking --prefix=$BASE_BUILD_DIR/depends/$HOST --bindir=$BASE_OUTDIR/bin --libdir=$BASE_OUTDIR/lib" +BITCOIN_CONFIG_ALL="--disable-dependency-tracking --prefix=$DEPENDS_DIR/$HOST --bindir=$BASE_OUTDIR/bin --libdir=$BASE_OUTDIR/lib" if [ -z "$NO_DEPENDS" ]; then DOCKER_EXEC ccache --max-size=$CCACHE_SIZE fi @@ -19,36 +19,28 @@ else 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 +DOCKER_EXEC mkdir -p build +export P_CI_DIR="$P_CI_DIR/build" BEGIN_FOLD configure -DOCKER_EXEC ../configure --cache-file=config.cache $BITCOIN_CONFIG_ALL $BITCOIN_CONFIG || ( cat config.log && false) +DOCKER_EXEC ../configure --cache-file=config.cache $BITCOIN_CONFIG_ALL $BITCOIN_CONFIG || ( (DOCKER_EXEC cat config.log) && false) END_FOLD BEGIN_FOLD distdir +# Create folder on host and docker, so that `cd` works +mkdir -p "bitcoin-$HOST" 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 +export P_CI_DIR="$P_CI_DIR/bitcoin-$HOST" BEGIN_FOLD configure -DOCKER_EXEC ./configure --cache-file=../config.cache $BITCOIN_CONFIG_ALL $BITCOIN_CONFIG || ( cat config.log && false) +DOCKER_EXEC ./configure --cache-file=../config.cache $BITCOIN_CONFIG_ALL $BITCOIN_CONFIG || ( (DOCKER_EXEC cat config.log) && false) END_FOLD set -o errtrace -trap 'DOCKER_EXEC "cat ${BASE_BUILD_DIR}/sanitizer-output/* 2> /dev/null"' ERR +trap 'DOCKER_EXEC "cat ${BASE_SCRATCH_DIR}/sanitizer-output/* 2> /dev/null"' ERR 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 7ac4907d32..a8e0a50f36 100755 --- a/ci/test/06_script_b.sh +++ b/ci/test/06_script_b.sh @@ -6,11 +6,6 @@ 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 echo "Prepare to run functional tests for HOST=$HOST" @@ -33,7 +28,7 @@ fi if [ "$RUN_UNIT_TESTS" = "true" ]; then BEGIN_FOLD unit-tests bash -c "${CI_WAIT}" & # Print dots in case the unit tests take a long time to run - DOCKER_EXEC LD_LIBRARY_PATH=$BASE_BUILD_DIR/depends/$HOST/lib make $MAKEJOBS check VERBOSE=1 + DOCKER_EXEC LD_LIBRARY_PATH=$DEPENDS_DIR/$HOST/lib make $MAKEJOBS check VERBOSE=1 END_FOLD fi @@ -48,7 +43,3 @@ if [ "$RUN_FUZZ_TESTS" = "true" ]; then DOCKER_EXEC test/fuzz/test_runner.py -l DEBUG ${DIR_FUZZ_IN} 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 998c82916a..ed9ccade6d 100644 --- a/configure.ac +++ b/configure.ac @@ -555,13 +555,8 @@ case $host in dnl It's safe to add these paths even if the functionality is disabled by dnl the user (--without-wallet or --without-gui for example). - openssl_prefix=`$BREW --prefix openssl 2>/dev/null` bdb_prefix=`$BREW --prefix berkeley-db4 2>/dev/null` qt5_prefix=`$BREW --prefix qt5 2>/dev/null` - if test x$openssl_prefix != x; then - PKG_CONFIG_PATH="$openssl_prefix/lib/pkgconfig:$PKG_CONFIG_PATH" - export PKG_CONFIG_PATH - fi if test x$bdb_prefix != x; then CPPFLAGS="$CPPFLAGS -I$bdb_prefix/include" LIBS="$LIBS -L$bdb_prefix/lib" @@ -790,7 +785,7 @@ if test x$TARGET_OS = xdarwin; then AX_CHECK_LINK_FLAG([[-Wl,-dead_strip]], [LDFLAGS="$LDFLAGS -Wl,-dead_strip"]) fi -AC_CHECK_HEADERS([endian.h sys/endian.h byteswap.h stdio.h stdlib.h unistd.h strings.h sys/types.h sys/stat.h sys/select.h sys/prctl.h]) +AC_CHECK_HEADERS([endian.h sys/endian.h byteswap.h stdio.h stdlib.h unistd.h strings.h sys/types.h sys/stat.h sys/select.h sys/prctl.h sys/sysctl.h vm/vm_param.h sys/vmmeter.h sys/resources.h]) # FD_ZERO may be dependent on a declaration of memcpy, e.g. in SmartOS # check that it fails to build without memcpy, then that it builds with @@ -950,6 +945,18 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <unistd.h> [ AC_MSG_RESULT(no)] ) +AC_MSG_CHECKING(for sysctl) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h> + #include <sys/sysctl.h>]], + [[ static const int name[2] = {CTL_KERN, KERN_VERSION}; + #ifdef __linux__ + #error "Don't use sysctl on Linux, it's deprecated even when it works" + #endif + sysctl(name, 2, nullptr, nullptr, nullptr, 0); ]])], + [ AC_MSG_RESULT(yes); AC_DEFINE(HAVE_SYSCTL, 1,[Define this symbol if the BSD sysctl() is available]) ], + [ AC_MSG_RESULT(no)] +) + AC_MSG_CHECKING(for sysctl KERN_ARND) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h> #include <sys/sysctl.h>]], @@ -1243,7 +1250,6 @@ if test x$use_pkgconfig = xyes; then m4_ifdef( [PKG_CHECK_MODULES], [ - PKG_CHECK_MODULES([CRYPTO], [libcrypto],,[AC_MSG_ERROR(libcrypto not found.)]) if test x$use_qr != xno; then BITCOIN_QT_CHECK([PKG_CHECK_MODULES([QR], [libqrencode], [have_qrencode=yes], [have_qrencode=no])]) fi @@ -1266,8 +1272,6 @@ if test x$use_pkgconfig = xyes; then ] ) 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)) 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),) @@ -1467,18 +1471,16 @@ if test x$bitcoin_enable_qt != xno; then AC_MSG_CHECKING([whether to build GUI with support for QR codes]) if test x$have_qrencode = xno; then if test x$use_qr = xyes; then - AC_MSG_ERROR("QR support requested but cannot be built. use --without-qrencode") + AC_MSG_ERROR([QR support requested but cannot be built. Use --without-qrencode]) fi - AC_MSG_RESULT(no) + use_qr=no else if test x$use_qr != xno; then - AC_MSG_RESULT(yes) AC_DEFINE([USE_QRCODE],[1],[Define if QR support should be compiled in]) use_qr=yes - else - AC_MSG_RESULT(no) fi fi + AC_MSG_RESULT([$use_qr]) if test x$XGETTEXT = x; then AC_MSG_WARN("xgettext is required to update qt translations") @@ -1587,7 +1589,6 @@ AC_SUBST(TESTDEFS) AC_SUBST(LEVELDB_TARGET_FLAGS) AC_SUBST(MINIUPNPC_CPPFLAGS) AC_SUBST(MINIUPNPC_LIBS) -AC_SUBST(CRYPTO_LIBS) AC_SUBST(EVENT_LIBS) AC_SUBST(EVENT_PTHREADS_LIBS) AC_SUBST(ZMQ_LIBS) diff --git a/contrib/devtools/symbol-check.py b/contrib/devtools/symbol-check.py index d8b684026c..0c59ab6239 100755 --- a/contrib/devtools/symbol-check.py +++ b/contrib/devtools/symbol-check.py @@ -4,8 +4,8 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. ''' A script to check that the (Linux) executables produced by gitian only contain -allowed gcc, glibc and libstdc++ version symbols. This makes sure they are -still compatible with the minimum supported Linux distribution versions. +allowed gcc and glibc version symbols. This makes sure they are still compatible +with the minimum supported Linux distribution versions. Example usage: @@ -16,30 +16,30 @@ import re import sys import os -# Debian 6.0.9 (Squeeze) has: +# Debian 8 (Jessie) EOL: 2020. https://wiki.debian.org/DebianReleases#Production_Releases # -# - g++ version 4.4.5 (https://packages.debian.org/search?suite=default§ion=all&arch=any&searchon=names&keywords=g%2B%2B) -# - libc version 2.11.3 (https://packages.debian.org/search?suite=default§ion=all&arch=any&searchon=names&keywords=libc6) -# - libstdc++ version 4.4.5 (https://packages.debian.org/search?suite=default§ion=all&arch=any&searchon=names&keywords=libstdc%2B%2B6) +# - g++ version 4.9.2 (https://packages.debian.org/search?suite=jessie&arch=any&searchon=names&keywords=g%2B%2B) +# - libc version 2.19 (https://packages.debian.org/search?suite=jessie&arch=any&searchon=names&keywords=libc6) # -# Ubuntu 10.04.4 (Lucid Lynx) has: +# Ubuntu 16.04 (Xenial) EOL: 2024. https://wiki.ubuntu.com/Releases # -# - g++ version 4.4.3 (http://packages.ubuntu.com/search?keywords=g%2B%2B&searchon=names&suite=lucid§ion=all) -# - libc version 2.11.1 (http://packages.ubuntu.com/search?keywords=libc6&searchon=names&suite=lucid§ion=all) -# - libstdc++ version 4.4.3 (http://packages.ubuntu.com/search?suite=lucid§ion=all&arch=any&keywords=libstdc%2B%2B&searchon=names) +# - g++ version 5.3.1 (https://packages.ubuntu.com/search?keywords=g%2B%2B&searchon=names&suite=xenial§ion=all) +# - libc version 2.23.0 (https://packages.ubuntu.com/search?keywords=libc6&searchon=names&suite=xenial§ion=all) +# +# CentOS 7 EOL: 2024. https://wiki.centos.org/FAQ/General +# +# - g++ version 4.8.5 (http://mirror.centos.org/centos/7/os/x86_64/Packages/) +# - libc version 2.17 (http://mirror.centos.org/centos/7/os/x86_64/Packages/) # # Taking the minimum of these as our target. # -# According to GNU ABI document (http://gcc.gnu.org/onlinedocs/libstdc++/manual/abi.html) this corresponds to: -# GCC 4.4.0: GCC_4.4.0 -# GCC 4.4.2: GLIBCXX_3.4.13, CXXABI_1.3.3 -# (glibc) GLIBC_2_11 +# According to GNU ABI document (https://gcc.gnu.org/onlinedocs/libstdc++/manual/abi.html) this corresponds to: +# GCC 4.8.5: GCC_4.8.0 +# (glibc) GLIBC_2_17 # MAX_VERSIONS = { -'GCC': (4,4,0), -'CXXABI': (1,3,3), -'GLIBCXX': (3,4,13), -'GLIBC': (2,11), +'GCC': (4,8,0), +'GLIBC': (2,17), 'LIBATOMIC': (1,0) } # See here for a description of _IO_stdin_used: @@ -47,7 +47,8 @@ MAX_VERSIONS = { # Ignore symbols that are exported as part of every executable IGNORE_EXPORTS = { -'_edata', '_end', '__end__', '_init', '__bss_start', '__bss_start__', '_bss_end__', '__bss_end__', '_fini', '_IO_stdin_used', 'stdin', 'stdout', 'stderr' +'_edata', '_end', '__end__', '_init', '__bss_start', '__bss_start__', '_bss_end__', '__bss_end__', '_fini', '_IO_stdin_used', 'stdin', 'stdout', 'stderr', +'environ', '_environ', '__environ', } READELF_CMD = os.getenv('READELF', '/usr/bin/readelf') CPPFILT_CMD = os.getenv('CPPFILT', '/usr/bin/c++filt') @@ -57,7 +58,6 @@ ALLOWED_LIBRARIES = { 'libgcc_s.so.1', # GCC base support 'libc.so.6', # C library 'libpthread.so.0', # threading -'libanl.so.1', # DNS resolve 'libm.so.6', # math library 'librt.so.1', # real-time (clock) 'libatomic.so.1', diff --git a/contrib/gitian-build.py b/contrib/gitian-build.py index 570d4906cd..712352d6b7 100755 --- a/contrib/gitian-build.py +++ b/contrib/gitian-build.py @@ -51,10 +51,8 @@ def build(): os.chdir('gitian-builder') os.makedirs('inputs', exist_ok=True) - subprocess.check_call(['wget', '-N', '-P', 'inputs', 'https://downloads.sourceforge.net/project/osslsigncode/osslsigncode/osslsigncode-1.7.1.tar.gz']) - subprocess.check_call(['wget', '-N', '-P', 'inputs', 'https://bitcoincore.org/cfields/osslsigncode-Backports-to-1.7.1.patch']) - subprocess.check_call(["echo 'a8c4e9cafba922f89de0df1f2152e7be286aba73f78505169bc351a7938dd911 inputs/osslsigncode-Backports-to-1.7.1.patch' | sha256sum -c"], shell=True) - subprocess.check_call(["echo 'f9a8cdb38b9c309326764ebc937cba1523a3a751a7ab05df3ecc99d18ae466c9 inputs/osslsigncode-1.7.1.tar.gz' | sha256sum -c"], shell=True) + subprocess.check_call(['wget', '-O' 'osslsigncode-2.0.tar.gz' '-N', '-P', 'inputs', 'https://github.com/mtrojnar/osslsigncode/archive/2.0.tar.gz']) + subprocess.check_call(["echo '5a60e0a4b3e0b4d655317b2f12a810211c50242138322b16e7e01c6fbb89d92f inputs/osslsigncode-2.0.tar.gz' | sha256sum -c"], shell=True) subprocess.check_call(['make', '-C', '../bitcoin/depends', 'download', 'SOURCES_PATH=' + os.getcwd() + '/cache/common']) if args.linux: diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml index c5b4ac1e83..2b86602a82 100644 --- a/contrib/gitian-descriptors/gitian-linux.yml +++ b/contrib/gitian-descriptors/gitian-linux.yml @@ -46,12 +46,12 @@ script: | FAKETIME_PROGS="date ar ranlib nm" HOST_CFLAGS="-O2 -g" HOST_CXXFLAGS="-O2 -g" - HOST_LDFLAGS=-static-libstdc++ + HOST_LDFLAGS_BASE="-static-libstdc++" export QT_RCC_TEST=1 export QT_RCC_SOURCE_DATE_OVERRIDE=1 export TZ="UTC" - export BUILD_DIR=`pwd` + export BUILD_DIR="$PWD" mkdir -p ${WRAP_DIR} if test -n "$GBUILD_CACHE_ENABLED"; then export SOURCES_PATH=${GBUILD_COMMON_CACHE} @@ -108,7 +108,7 @@ script: | rm -f ${WRAP_DIR}/${prog} cat << EOF > ${WRAP_DIR}/${prog} #!/usr/bin/env bash - REAL="`which -a ${prog}-8 | grep -v ${WRAP_DIR}/${prog} | head -1`" + REAL="$(which -a ${prog}-8 | grep -v ${WRAP_DIR}/${prog} | head -1)" for var in "\$@" do if [ "\$var" = "-m32" ]; then @@ -123,7 +123,7 @@ script: | done cd bitcoin - BASEPREFIX=`pwd`/depends + BASEPREFIX="${PWD}/depends" # Build dependencies for each host for i in $HOSTS; do EXTRA_INCLUDES="$EXTRA_INCLUDES_BASE/$i" @@ -142,10 +142,11 @@ script: | # Create the release tarball using (arbitrarily) the first host ./autogen.sh - CONFIG_SITE=${BASEPREFIX}/`echo "${HOSTS}" | awk '{print $1;}'`/share/config.site ./configure --prefix=/ + CONFIG_SITE=${BASEPREFIX}/$(echo "${HOSTS}" | awk '{print $1;}')/share/config.site ./configure --prefix=/ make dist - SOURCEDIST=`echo bitcoin-*.tar.gz` - DISTNAME=`echo ${SOURCEDIST} | sed 's/.tar.*//'` + SOURCEDIST=$(echo bitcoin-*.tar.gz) + DISTNAME=${SOURCEDIST/%.tar.gz} + # Correct tar file order mkdir -p temp pushd temp @@ -160,9 +161,16 @@ script: | # Extract the release tarball into a dir for each host and build for i in ${HOSTS}; do export PATH=${BASEPREFIX}/${i}/native/bin:${ORIGPATH} + if [ "${i}" = "riscv64-linux-gnu" ]; then + # Workaround for https://bugs.launchpad.net/ubuntu/+source/gcc-8-cross-ports/+bug/1853740 + # TODO: remove this when no longer needed + HOST_LDFLAGS="${HOST_LDFLAGS_BASE} -Wl,-z,noexecstack" + else + HOST_LDFLAGS="${HOST_LDFLAGS_BASE}" + fi mkdir -p distsrc-${i} cd distsrc-${i} - INSTALLPATH=`pwd`/installed/${DISTNAME} + INSTALLPATH="${PWD}/installed/${DISTNAME}" mkdir -p ${INSTALLPATH} tar --strip-components=1 -xf ../$SOURCEDIST diff --git a/contrib/gitian-descriptors/gitian-osx-signer.yml b/contrib/gitian-descriptors/gitian-osx-signer.yml index 9957fc0514..2d49493641 100644 --- a/contrib/gitian-descriptors/gitian-osx-signer.yml +++ b/contrib/gitian-descriptors/gitian-osx-signer.yml @@ -17,7 +17,7 @@ script: | WRAP_DIR=$HOME/wrapped mkdir -p ${WRAP_DIR} - export PATH=`pwd`:$PATH + export PATH="$PWD":$PATH FAKETIME_PROGS="dmg genisoimage" # Create global faketime wrappers diff --git a/contrib/gitian-descriptors/gitian-osx.yml b/contrib/gitian-descriptors/gitian-osx.yml index 79b1b22cdf..d3a2645c53 100644 --- a/contrib/gitian-descriptors/gitian-osx.yml +++ b/contrib/gitian-descriptors/gitian-osx.yml @@ -37,7 +37,7 @@ script: | set -e -o pipefail WRAP_DIR=$HOME/wrapped - HOSTS="x86_64-apple-darwin14" + HOSTS="x86_64-apple-darwin16" CONFIGFLAGS="--enable-reduce-exports --disable-bench --disable-gui-tests GENISOIMAGE=$WRAP_DIR/genisoimage" FAKETIME_HOST_PROGS="" FAKETIME_PROGS="ar ranlib date dmg genisoimage" @@ -45,7 +45,7 @@ script: | export QT_RCC_TEST=1 export QT_RCC_SOURCE_DATE_OVERRIDE=1 export TZ="UTC" - export BUILD_DIR=`pwd` + export BUILD_DIR="$PWD" mkdir -p ${WRAP_DIR} if test -n "$GBUILD_CACHE_ENABLED"; then export SOURCES_PATH=${GBUILD_COMMON_CACHE} @@ -87,7 +87,7 @@ script: | export PATH=${WRAP_DIR}:${PATH} cd bitcoin - BASEPREFIX=`pwd`/depends + BASEPREFIX="${PWD}/depends" mkdir -p ${BASEPREFIX}/SDKs tar -C ${BASEPREFIX}/SDKs -xf ${BUILD_DIR}/MacOSX10.11.sdk.tar.gz @@ -105,10 +105,10 @@ script: | # Create the release tarball using (arbitrarily) the first host ./autogen.sh - CONFIG_SITE=${BASEPREFIX}/`echo "${HOSTS}" | awk '{print $1;}'`/share/config.site ./configure --prefix=/ + CONFIG_SITE=${BASEPREFIX}/$(echo "${HOSTS}" | awk '{print $1;}')/share/config.site ./configure --prefix=/ make dist - SOURCEDIST=`echo bitcoin-*.tar.gz` - DISTNAME=`echo ${SOURCEDIST} | sed 's/.tar.*//'` + SOURCEDIST=$(echo bitcoin-*.tar.gz) + DISTNAME=${SOURCEDIST/%.tar.gz} # Correct tar file order mkdir -p temp @@ -126,7 +126,7 @@ script: | export PATH=${BASEPREFIX}/${i}/native/bin:${ORIGPATH} mkdir -p distsrc-${i} cd distsrc-${i} - INSTALLPATH=`pwd`/installed/${DISTNAME} + INSTALLPATH="${PWD}/installed/${DISTNAME}" mkdir -p ${INSTALLPATH} tar --strip-components=1 -xf ../$SOURCEDIST diff --git a/contrib/gitian-descriptors/gitian-win-signer.yml b/contrib/gitian-descriptors/gitian-win-signer.yml index 8076fe13af..6a52db1f9f 100644 --- a/contrib/gitian-descriptors/gitian-win-signer.yml +++ b/contrib/gitian-descriptors/gitian-win-signer.yml @@ -6,37 +6,36 @@ suites: architectures: - "linux64" packages: -# Once osslsigncode supports openssl 1.1, we can change this back to libssl-dev -- "libssl1.0-dev" +- "libssl-dev" - "autoconf" +- "libtool" +- "pkg-config" remotes: - "url": "https://github.com/bitcoin-core/bitcoin-detached-sigs.git" "dir": "signature" files: -- "osslsigncode-1.7.1.tar.gz" -- "osslsigncode-Backports-to-1.7.1.patch" +- "osslsigncode-2.0.tar.gz" - "bitcoin-win-unsigned.tar.gz" script: | set -e -o pipefail - BUILD_DIR=`pwd` + BUILD_DIR="$PWD" SIGDIR=${BUILD_DIR}/signature/win UNSIGNED_DIR=${BUILD_DIR}/unsigned - echo "f9a8cdb38b9c309326764ebc937cba1523a3a751a7ab05df3ecc99d18ae466c9 osslsigncode-1.7.1.tar.gz" | sha256sum -c - echo "a8c4e9cafba922f89de0df1f2152e7be286aba73f78505169bc351a7938dd911 osslsigncode-Backports-to-1.7.1.patch" | sha256sum -c + echo "5a60e0a4b3e0b4d655317b2f12a810211c50242138322b16e7e01c6fbb89d92f osslsigncode-2.0.tar.gz" | sha256sum -c mkdir -p ${UNSIGNED_DIR} tar -C ${UNSIGNED_DIR} -xf bitcoin-win-unsigned.tar.gz - tar xf osslsigncode-1.7.1.tar.gz - cd osslsigncode-1.7.1 - patch -p1 < ${BUILD_DIR}/osslsigncode-Backports-to-1.7.1.patch + tar xf osslsigncode-2.0.tar.gz + cd osslsigncode-2.0 + ./autogen.sh ./configure --without-gsf --without-curl --disable-dependency-tracking make find ${UNSIGNED_DIR} -name "*-unsigned.exe" | while read i; do - INFILE="`basename "${i}"`" - OUTFILE="`echo "${INFILE}" | sed s/-unsigned//`" + INFILE="$(basename "${i}")" + OUTFILE="${INFILE/%-unsigned}" ./osslsigncode attach-signature -in "${i}" -out "${OUTDIR}/${OUTFILE}" -sigin "${SIGDIR}/${INFILE}.pem" done diff --git a/contrib/gitian-descriptors/gitian-win.yml b/contrib/gitian-descriptors/gitian-win.yml index 4259a10e14..b772404ae5 100644 --- a/contrib/gitian-descriptors/gitian-win.yml +++ b/contrib/gitian-descriptors/gitian-win.yml @@ -40,7 +40,7 @@ script: | export QT_RCC_TEST=1 export QT_RCC_SOURCE_DATE_OVERRIDE=1 export TZ="UTC" - export BUILD_DIR=`pwd` + export BUILD_DIR="$PWD" mkdir -p ${WRAP_DIR} if test -n "$GBUILD_CACHE_ENABLED"; then export SOURCES_PATH=${GBUILD_COMMON_CACHE} @@ -97,7 +97,7 @@ script: | export PATH=${WRAP_DIR}:${PATH} cd bitcoin - BASEPREFIX=`pwd`/depends + BASEPREFIX="${PWD}/depends" # Build dependencies for each host for i in $HOSTS; do make ${MAKEOPTS} -C ${BASEPREFIX} HOST="${i}" @@ -112,10 +112,11 @@ script: | # Create the release tarball using (arbitrarily) the first host ./autogen.sh - CONFIG_SITE=${BASEPREFIX}/`echo "${HOSTS}" | awk '{print $1;}'`/share/config.site ./configure --prefix=/ + CONFIG_SITE=${BASEPREFIX}/$(echo "${HOSTS}" | awk '{print $1;}')/share/config.site ./configure --prefix=/ make dist - SOURCEDIST=`echo bitcoin-*.tar.gz` - DISTNAME=`echo ${SOURCEDIST} | sed 's/.tar.*//'` + SOURCEDIST=$(echo bitcoin-*.tar.gz) + DISTNAME=${SOURCEDIST/%.tar.gz} + # Correct tar file order mkdir -p temp pushd temp @@ -132,7 +133,7 @@ script: | export PATH=${BASEPREFIX}/${i}/native/bin:${ORIGPATH} mkdir -p distsrc-${i} cd distsrc-${i} - INSTALLPATH=`pwd`/installed/${DISTNAME} + INSTALLPATH="${PWD}/installed/${DISTNAME}" mkdir -p ${INSTALLPATH} tar --strip-components=1 -xf ../$SOURCEDIST diff --git a/contrib/gitian-keys/keys.txt b/contrib/gitian-keys/keys.txt index 9222a40b17..ba3036a89f 100644 --- a/contrib/gitian-keys/keys.txt +++ b/contrib/gitian-keys/keys.txt @@ -27,6 +27,7 @@ D62A803E27E7F43486035ADBBCD04D8E9CCCAC2A Paul Rabahy 37EC7D7B0A217CDB4B4E007E7FAB114267E4FA04 Peter Todd D762373D24904A3E42F33B08B9A408E71DAAC974 Pieter Wuille (Location: Leuven, Belgium) 133EAC179436F14A5CF1B794860FEB804E669320 Pieter Wuille +A8FC55F3B04BA3146F3492E79303B33A305224CB Sebastian Kung (TheCharlatan) ED9BDF7AD6A55E232E84524257FF9BDBCC301009 Sjors Provoost AEC1884398647C47413C1C3FB1179EB7347DC10D Warren Togami 79D00BAC68B56D422F945A8F8E3A8F3247DBCBBF Willy Ko diff --git a/contrib/verify-commits/README.md b/contrib/verify-commits/README.md index 1215962a16..e95a57586f 100644 --- a/contrib/verify-commits/README.md +++ b/contrib/verify-commits/README.md @@ -40,7 +40,7 @@ Import trusted keys In order to check the commit signatures, you must add the trusted PGP keys to your machine. [GnuPG](https://gnupg.org/) may be used to import the trusted keys by running the following command: ```sh -gpg --recv-keys $(<contrib/verify-commits/trusted-keys) +gpg --keyserver hkp://keyserver.ubuntu.com --recv-keys $(<contrib/verify-commits/trusted-keys) ``` Key expiry/revocation diff --git a/depends/README.md b/depends/README.md index e5e2a8a653..b56302b6c7 100644 --- a/depends/README.md +++ b/depends/README.md @@ -25,7 +25,7 @@ Common `host-platform-triplets` for cross compilation are: - `i686-pc-linux-gnu` for Linux 32 bit - `x86_64-pc-linux-gnu` for x86 Linux - `x86_64-w64-mingw32` for Win64 -- `x86_64-apple-darwin14` for macOS +- `x86_64-apple-darwin16` for macOS - `arm-linux-gnueabihf` for Linux ARM 32 bit - `aarch64-linux-gnu` for Linux ARM 64 bit - `riscv32-linux-gnu` for Linux RISC-V 32 bit diff --git a/depends/hosts/darwin.mk b/depends/hosts/darwin.mk index a1c943d60b..1f88c209cf 100644 --- a/depends/hosts/darwin.mk +++ b/depends/hosts/darwin.mk @@ -1,4 +1,4 @@ -OSX_MIN_VERSION=10.10 +OSX_MIN_VERSION=10.12 OSX_SDK_VERSION=10.11 OSX_SDK=$(SDK_PATH)/MacOSX$(OSX_SDK_VERSION).sdk LD64_VERSION=253.9 diff --git a/depends/packages/libevent.mk b/depends/packages/libevent.mk index b4333abaf0..eb45e14f6f 100644 --- a/depends/packages/libevent.mk +++ b/depends/packages/libevent.mk @@ -1,19 +1,12 @@ package=libevent -$(package)_version=2.1.8-stable +$(package)_version=2.1.11-stable $(package)_download_path=https://github.com/libevent/libevent/archive/ $(package)_file_name=release-$($(package)_version).tar.gz -$(package)_sha256_hash=316ddb401745ac5d222d7c529ef1eada12f58f6376a66c1118eee803cb70f83d -$(package)_patches=fix_android_arc4random_addrandom.patch +$(package)_sha256_hash=229393ab2bf0dc94694f21836846b424f3532585bac3468738b7bf752c03901e -ifneq (,$(findstring android,$(host))) - define $(package)_preprocess_cmds - ./autogen.sh && patch -p1 < $($(package)_patch_dir)/fix_android_arc4random_addrandom.patch - endef -else - define $(package)_preprocess_cmds - ./autogen.sh - endef -endif +define $(package)_preprocess_cmds + ./autogen.sh +endef define $(package)_set_vars $(package)_config_opts=--disable-shared --disable-openssl --disable-libevent-regress --disable-samples diff --git a/depends/packages/openssl.mk b/depends/packages/openssl.mk deleted file mode 100644 index e3b3647dd9..0000000000 --- a/depends/packages/openssl.mk +++ /dev/null @@ -1,88 +0,0 @@ -package=openssl -$(package)_version=1.0.1k -$(package)_download_path=https://www.openssl.org/source -$(package)_file_name=$(package)-$($(package)_version).tar.gz -$(package)_sha256_hash=8f9faeaebad088e772f4ef5e38252d472be4d878c6b3a2718c10a4fcebe7a41c -$(package)_patches=0001-Add-OpenSSL-termios-fix-for-musl-libc.patch - -define $(package)_set_vars -$(package)_config_env=AR="$($(package)_ar)" RANLIB="$($(package)_ranlib)" CC="$($(package)_cc)" -$(package)_config_opts=--prefix=$(host_prefix) --openssldir=$(host_prefix)/etc/openssl -$(package)_config_opts+=no-camellia -$(package)_config_opts+=no-capieng -$(package)_config_opts+=no-cast -$(package)_config_opts+=no-comp -$(package)_config_opts+=no-dso -$(package)_config_opts+=no-dtls1 -$(package)_config_opts+=no-ec_nistp_64_gcc_128 -$(package)_config_opts+=no-gost -$(package)_config_opts+=no-gmp -$(package)_config_opts+=no-heartbeats -$(package)_config_opts+=no-idea -$(package)_config_opts+=no-jpake -$(package)_config_opts+=no-krb5 -$(package)_config_opts+=no-libunbound -$(package)_config_opts+=no-md2 -$(package)_config_opts+=no-mdc2 -$(package)_config_opts+=no-rc4 -$(package)_config_opts+=no-rc5 -$(package)_config_opts+=no-rdrand -$(package)_config_opts+=no-rfc3779 -$(package)_config_opts+=no-rsax -$(package)_config_opts+=no-sctp -$(package)_config_opts+=no-seed -$(package)_config_opts+=no-sha0 -$(package)_config_opts+=no-shared -$(package)_config_opts+=no-ssl-trace -$(package)_config_opts+=no-ssl2 -$(package)_config_opts+=no-ssl3 -$(package)_config_opts+=no-static_engine -$(package)_config_opts+=no-store -$(package)_config_opts+=no-unit-test -$(package)_config_opts+=no-weak-ssl-ciphers -$(package)_config_opts+=no-whirlpool -$(package)_config_opts+=no-zlib -$(package)_config_opts+=no-zlib-dynamic -$(package)_config_opts+=$($(package)_cflags) $($(package)_cppflags) -$(package)_config_opts_linux=-fPIC -Wa,--noexecstack -$(package)_config_opts_x86_64_linux=linux-x86_64 -$(package)_config_opts_i686_linux=linux-generic32 -$(package)_config_opts_arm_linux=linux-generic32 -$(package)_config_opts_armv7l_linux=linux-generic32 -$(package)_config_opts_aarch64_linux=linux-generic64 -$(package)_config_opts_mipsel_linux=linux-generic32 -$(package)_config_opts_mips_linux=linux-generic32 -$(package)_config_opts_powerpc_linux=linux-generic32 -$(package)_config_opts_riscv32_linux=linux-generic32 -$(package)_config_opts_riscv64_linux=linux-generic64 -$(package)_config_opts_x86_64_darwin=darwin64-x86_64-cc -$(package)_config_opts_x86_64_mingw32=mingw64 -$(package)_config_opts_i686_mingw32=mingw -$(package)_config_opts_android=-fPIC -$(package)_config_opts_aarch64_android=linux-generic64 -$(package)_config_opts_x86_64_android=linux-generic64 -$(package)_config_opts_armv7a_android=linux-generic32 -$(package)_config_opts_i686_android=linux-generic32 -endef - -define $(package)_preprocess_cmds - patch -p1 < $($(package)_patch_dir)/0001-Add-OpenSSL-termios-fix-for-musl-libc.patch && \ - sed -i.old "/define DATE/d" util/mkbuildinf.pl && \ - sed -i.old "s|engines apps test|engines|" Makefile.org -endef - -define $(package)_config_cmds - ./Configure $($(package)_config_opts) -endef - -define $(package)_build_cmds - $(MAKE) -j1 build_crypto libcrypto.pc libssl.pc openssl.pc -endef - -define $(package)_stage_cmds - $(MAKE) INSTALL_PREFIX=$($(package)_staging_dir) -j1 install_sw -endef - -define $(package)_postprocess_cmds - rm -rf share bin etc -endef diff --git a/depends/packages/packages.mk b/depends/packages/packages.mk index 09734c7e6f..09f3187ac4 100644 --- a/depends/packages/packages.mk +++ b/depends/packages/packages.mk @@ -1,4 +1,4 @@ -packages:=boost openssl libevent +packages:=boost libevent qt_packages = qrencode zlib diff --git a/depends/packages/qt.mk b/depends/packages/qt.mk index a0f7cda2c0..c9ffc1036c 100644 --- a/depends/packages/qt.mk +++ b/depends/packages/qt.mk @@ -25,7 +25,6 @@ $(package)_config_opts_debug = -debug $(package)_config_opts += -bindir $(build_prefix)/bin $(package)_config_opts += -c++std c++11 $(package)_config_opts += -confirm-license -$(package)_config_opts += -dbus-runtime $(package)_config_opts += -hostprefix $(build_prefix) $(package)_config_opts += -no-compile-examples $(package)_config_opts += -no-cups @@ -105,8 +104,10 @@ $(package)_config_opts += -no-feature-vnc $(package)_config_opts += -no-feature-wizard $(package)_config_opts += -no-feature-xml +$(package)_config_opts_darwin = -no-dbus + ifneq ($(build_os),darwin) -$(package)_config_opts_darwin = -xplatform macx-clang-linux +$(package)_config_opts_darwin += -xplatform macx-clang-linux $(package)_config_opts_darwin += -device-option MAC_SDK_PATH=$(OSX_SDK) $(package)_config_opts_darwin += -device-option MAC_SDK_VERSION=$(OSX_SDK_VERSION) $(package)_config_opts_darwin += -device-option CROSS_COMPILE="$(host)-" @@ -122,12 +123,17 @@ $(package)_config_opts_linux += -no-feature-xlib $(package)_config_opts_linux += -system-freetype $(package)_config_opts_linux += -fontconfig $(package)_config_opts_linux += -no-opengl +$(package)_config_opts_linux += -dbus-runtime $(package)_config_opts_arm_linux += -platform linux-g++ -xplatform bitcoin-linux-g++ $(package)_config_opts_i686_linux = -xplatform linux-g++-32 $(package)_config_opts_x86_64_linux = -xplatform linux-g++-64 $(package)_config_opts_aarch64_linux = -xplatform linux-aarch64-gnu-g++ $(package)_config_opts_riscv64_linux = -platform linux-g++ -xplatform bitcoin-linux-g++ -$(package)_config_opts_mingw32 = -no-opengl -xplatform win32-g++ -device-option CROSS_COMPILE="$(host)-" + +$(package)_config_opts_mingw32 = -no-opengl +$(package)_config_opts_mingw32 += -no-dbus +$(package)_config_opts_mingw32 += -xplatform win32-g++ +$(package)_config_opts_mingw32 += -device-option CROSS_COMPILE="$(host)-" $(package)_config_opts_android = -xplatform android-clang $(package)_config_opts_android += -android-sdk $(ANDROID_SDK) @@ -137,6 +143,7 @@ $(package)_config_opts_android += -device-option CROSS_COMPILE="$(host)-" $(package)_config_opts_android += -egl $(package)_config_opts_android += -qpa xcb $(package)_config_opts_android += -no-eglfs +$(package)_config_opts_android += -no-dbus $(package)_config_opts_android += -opengl es2 $(package)_config_opts_android += -qt-freetype $(package)_config_opts_android += -no-fontconfig @@ -202,6 +209,8 @@ define $(package)_preprocess_cmds sed -i.old "s|QMAKE_CFLAGS += |!host_build: QMAKE_CFLAGS = $($(package)_cflags) $($(package)_cppflags) |" qtbase/mkspecs/win32-g++/qmake.conf && \ sed -i.old "s|QMAKE_CXXFLAGS += |!host_build: QMAKE_CXXFLAGS = $($(package)_cxxflags) $($(package)_cppflags) |" qtbase/mkspecs/win32-g++/qmake.conf && \ sed -i.old "0,/^QMAKE_LFLAGS_/s|^QMAKE_LFLAGS_|!host_build: QMAKE_LFLAGS = $($(package)_ldflags)\n&|" qtbase/mkspecs/win32-g++/qmake.conf && \ + sed -i.old "s|QMAKE_CC = clang|QMAKE_CC = $($(package)_cc)|" qtbase/mkspecs/common/clang.conf && \ + sed -i.old "s|QMAKE_CXX = clang++|QMAKE_CXX = $($(package)_cxx)|" qtbase/mkspecs/common/clang.conf && \ sed -i.old "s/LIBRARY_PATH/(CROSS_)?\0/g" qtbase/mkspecs/features/toolchain.prf endef diff --git a/depends/patches/libevent/fix_android_arc4random_addrandom.patch b/depends/patches/libevent/fix_android_arc4random_addrandom.patch deleted file mode 100644 index 5bcc64bef6..0000000000 --- a/depends/patches/libevent/fix_android_arc4random_addrandom.patch +++ /dev/null @@ -1,68 +0,0 @@ -From cadae3ab7abf45e61ecae8aac39d97d1f3cbd336 Mon Sep 17 00:00:00 2001 -From: Lawrence Nahum <lawrence@greenaddress.it> -Date: Sun, 3 Dec 2017 22:56:09 +0100 -Subject: [PATCH] fixup - ---- - configure.ac | 1 + - evutil_rand.c | 3 +++ - include/event2/util.h | 4 ++-- - 3 files changed, 6 insertions(+), 2 deletions(-) - -diff --git a/configure.ac b/configure.ac -index 7528d37..3bb2121 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -341,6 +341,7 @@ dnl Checks for library functions. - AC_CHECK_FUNCS([ \ - accept4 \ - arc4random \ -+ arc4random_addrandom \ - arc4random_buf \ - eventfd \ - epoll_create1 \ -diff --git a/evutil_rand.c b/evutil_rand.c -index 046a14b..3f0bf2c 100644 ---- a/evutil_rand.c -+++ b/evutil_rand.c -@@ -191,6 +191,7 @@ evutil_secure_rng_get_bytes(void *buf, size_t n) - { - ev_arc4random_buf(buf, n); - } -+#ifdef HAVE_ARC4RANDOM_ADDRANDOM - - void - evutil_secure_rng_add_bytes(const char *buf, size_t n) -@@ -199,6 +200,8 @@ evutil_secure_rng_add_bytes(const char *buf, size_t n) - n>(size_t)INT_MAX ? INT_MAX : (int)n); - } - -+#endif -+ - void - evutil_free_secure_rng_globals_(void) - { -diff --git a/include/event2/util.h b/include/event2/util.h -index dd4bbb6..a9a169d 100644 ---- a/include/event2/util.h -+++ b/include/event2/util.h -@@ -841,7 +841,7 @@ int evutil_secure_rng_init(void); - */ - EVENT2_EXPORT_SYMBOL - int evutil_secure_rng_set_urandom_device_file(char *fname); -- -+#ifdef HAVE_ARC4RANDOM_ADDRANDOM - /** Seed the random number generator with extra random bytes. - - You should almost never need to call this function; it should be -@@ -858,7 +858,7 @@ int evutil_secure_rng_set_urandom_device_file(char *fname); - */ - EVENT2_EXPORT_SYMBOL - void evutil_secure_rng_add_bytes(const char *dat, size_t datlen); -- -+#endif - #ifdef __cplusplus - } - #endif --- -2.14.3 diff --git a/depends/patches/openssl/0001-Add-OpenSSL-termios-fix-for-musl-libc.patch b/depends/patches/openssl/0001-Add-OpenSSL-termios-fix-for-musl-libc.patch deleted file mode 100644 index 003099bdc2..0000000000 --- a/depends/patches/openssl/0001-Add-OpenSSL-termios-fix-for-musl-libc.patch +++ /dev/null @@ -1,17 +0,0 @@ -diff --git a/crypto/ui/ui_openssl.c b/crypto/ui/ui_openssl.c -index a38c758..d99edc2 100644 ---- a/crypto/ui/ui_openssl.c -+++ b/crypto/ui/ui_openssl.c -@@ -190,9 +190,9 @@ - # undef SGTTY - #endif - --#if defined(linux) && !defined(TERMIO) --# undef TERMIOS --# define TERMIO -+#if defined(linux) -+# define TERMIOS -+# undef TERMIO - # undef SGTTY - #endif - diff --git a/doc/README.md b/doc/README.md index d3017de2ab..4dd21c4620 100644 --- a/doc/README.md +++ b/doc/README.md @@ -54,7 +54,7 @@ The Bitcoin repo's [root README](/README.md) contains relevant information on th - [Productivity Notes](productivity.md) - [Release Notes](release-notes.md) - [Release Process](release-process.md) -- [Source Code Documentation (External Link)](https://dev.visucore.com/bitcoin/doxygen/) +- [Source Code Documentation (External Link)](https://doxygen.bitcoincore.org/) - [Translation Process](translation_process.md) - [Translation Strings Policy](translation_strings_policy.md) - [JSON-RPC Interface](JSON-RPC-interface.md) @@ -84,5 +84,3 @@ The Bitcoin repo's [root README](/README.md) contains relevant information on th License --------------------- Distributed under the [MIT software license](/COPYING). -This product includes software developed by the OpenSSL Project for use in the [OpenSSL Toolkit](https://www.openssl.org/). This product includes -cryptographic software written by Eric Young ([eay@cryptsoft.com](mailto:eay@cryptsoft.com)), and UPnP software written by Thomas Bernard. diff --git a/doc/build-freebsd.md b/doc/build-freebsd.md index d22b6e8383..4831623504 100644 --- a/doc/build-freebsd.md +++ b/doc/build-freebsd.md @@ -11,7 +11,7 @@ This guide does not contain instructions for building the GUI. You will need the following dependencies, which can be installed as root via pkg: ```shell -pkg install autoconf automake boost-libs git gmake libevent libtool openssl pkgconf +pkg install autoconf automake boost-libs git gmake libevent libtool pkgconf git clone https://github.com/bitcoin/bitcoin.git ``` diff --git a/doc/build-osx.md b/doc/build-osx.md index 9942449bf6..bf655538c7 100644 --- a/doc/build-osx.md +++ b/doc/build-osx.md @@ -19,7 +19,7 @@ Then install [Homebrew](https://brew.sh). ## Dependencies ```shell -brew install automake berkeley-db4 libtool boost miniupnpc openssl pkg-config python qt libevent qrencode +brew install automake berkeley-db4 libtool boost miniupnpc pkg-config python qt libevent qrencode ``` See [dependencies.md](dependencies.md) for a complete overview. @@ -110,7 +110,7 @@ tail -f $HOME/Library/Application\ Support/Bitcoin/debug.log ``` ## Notes -* Tested on OS X 10.10 Yosemite through macOS 10.14 Mojave on 64-bit Intel +* Tested on OS X 10.12 Sierra through macOS 10.15 Catalina on 64-bit Intel processors only. * Building with downloaded Qt binaries is not officially supported. See the notes in [#7714](https://github.com/bitcoin/bitcoin/issues/7714). diff --git a/doc/build-unix.md b/doc/build-unix.md index d048bdeff5..e799e709fa 100644 --- a/doc/build-unix.md +++ b/doc/build-unix.md @@ -33,7 +33,6 @@ These dependencies are required: Library | Purpose | Description ------------|------------------|---------------------- - libssl | Crypto | Random Number Generation, Elliptic Curve Cryptography libboost | Utility | Library for threading, data structures, etc libevent | Networking | OS independent asynchronous networking @@ -81,7 +80,7 @@ Build requirements: Now, you can either build from self-compiled [depends](/depends/README.md) or install the required dependencies: - sudo apt-get install libssl-dev libevent-dev libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-test-dev libboost-thread-dev + sudo apt-get install libevent-dev libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-test-dev libboost-thread-dev BerkeleyDB is required for the wallet. @@ -127,7 +126,7 @@ built by default. Build requirements: - sudo dnf install gcc-c++ libtool make autoconf automake openssl-devel libevent-devel boost-devel libdb4-devel libdb4-cxx-devel python3 + sudo dnf install gcc-c++ libtool make autoconf automake libevent-devel boost-devel libdb4-devel libdb4-cxx-devel python3 Optional (see `--with-miniupnpc` and `--enable-upnp-default`): diff --git a/doc/dependencies.md b/doc/dependencies.md index dc88626761..4b57ef2e91 100644 --- a/doc/dependencies.md +++ b/doc/dependencies.md @@ -13,11 +13,10 @@ These are the dependencies currently used by Bitcoin Core. You can find instruct | FreeType | [2.7.1](https://download.savannah.gnu.org/releases/freetype) | | No | | | | GCC | | [4.8+](https://gcc.gnu.org/) (C++11 support) | | | | | HarfBuzz-NG | | | | | | -| libevent | [2.1.8-stable](https://github.com/libevent/libevent/releases) | 2.0.22 | No | | | +| libevent | [2.1.11-stable](https://github.com/libevent/libevent/releases) | 2.0.22 | No | | | | libpng | | | | | [Yes](https://github.com/bitcoin/bitcoin/blob/master/depends/packages/qt.mk) | | librsvg | | | | | | | 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) | | Python (tests) | | [3.5](https://www.python.org/downloads) | | | | | qrencode | [3.4.4](https://fukuchi.org/works/qrencode) | | No | | | diff --git a/doc/developer-notes.md b/doc/developer-notes.md index e7fd8102a4..49f60c54ec 100644 --- a/doc/developer-notes.md +++ b/doc/developer-notes.md @@ -12,12 +12,13 @@ Developer Notes - [Development tips and tricks](#development-tips-and-tricks) - [Compiling for debugging](#compiling-for-debugging) - [Compiling for gprof profiling](#compiling-for-gprof-profiling) - - [debug.log](#debuglog) + - [`debug.log`](#debuglog) - [Testnet and Regtest modes](#testnet-and-regtest-modes) - [DEBUG_LOCKORDER](#debug_lockorder) - [Valgrind suppressions file](#valgrind-suppressions-file) - [Compiling for test coverage](#compiling-for-test-coverage) - [Performance profiling with perf](#performance-profiling-with-perf) + - [Sanitizers](#sanitizers) - [Locking/mutex usage notes](#lockingmutex-usage-notes) - [Threads](#threads) - [Ignoring IDE/editor files](#ignoring-ideeditor-files) @@ -35,6 +36,7 @@ Developer Notes - [GUI](#gui) - [Subtrees](#subtrees) - [Scripted diffs](#scripted-diffs) + - [Suggestions and examples](#suggestions-and-examples) - [Release notes](#release-notes) - [RPC interface guidelines](#rpc-interface-guidelines) @@ -62,7 +64,7 @@ tool to clean up patches automatically before submission. - Braces on the same line for everything else. - 4 space indentation (no tabs) for every block except namespaces. - No indentation for `public`/`protected`/`private` or for `namespace`. - - No extra spaces inside parenthesis; don't do ( this ). + - No extra spaces inside parenthesis; don't do `( this )`. - No space after function names; one space after `if`, `for` and `while`. - If an `if` only has a single-statement `then`-clause, it can appear on the same line as the `if`, without braces. In every other case, @@ -76,7 +78,7 @@ code. separate words (snake_case). - Class member variables have a `m_` prefix. - Global variables have a `g_` prefix. - - Constant names are all uppercase, and use `_` to separate words. + - Compile-time constant names are all uppercase, and use `_` to separate words. - Class names, function names, and method names are UpperCamelCase (PascalCase). Do not prefix class names with `C`. - Test suite naming convention: The Boost test suite in file @@ -207,15 +209,15 @@ produce better debugging builds. Run configure with the `--enable-gprof` option, then make. -### debug.log +### `debug.log` -If the code is behaving strangely, take a look in the debug.log file in the data directory; +If the code is behaving strangely, take a look in the `debug.log` file in the data directory; error and debugging messages are written there. The `-debug=...` command-line option controls debugging; running with just `-debug` or `-debug=1` will turn -on all categories (and give you a very large debug.log file). +on all categories (and give you a very large `debug.log` file). -The Qt code routes `qDebug()` output to debug.log under category "qt": run with `-debug=qt` +The Qt code routes `qDebug()` output to `debug.log` under category "qt": run with `-debug=qt` to see it. ### Testnet and Regtest modes @@ -233,7 +235,7 @@ Bitcoin Core is a multi-threaded application, and deadlocks or other multi-threading bugs can be very difficult to track down. The `--enable-debug` configure option adds `-DDEBUG_LOCKORDER` to the compiler flags. This inserts run-time checks to keep track of which locks are held and adds warnings to the -debug.log file if inconsistencies are detected. +`debug.log` file if inconsistencies are detected. ### Valgrind suppressions file @@ -275,8 +277,7 @@ the functional test framework. Perf can observe a running process and sample (at some frequency) where its execution is. Perf installation is contingent on which kernel version you're running; see -[this StackExchange -thread](https://askubuntu.com/questions/50145/how-to-install-perf-monitoring-tool) +[this thread](https://askubuntu.com/questions/50145/how-to-install-perf-monitoring-tool) for specific instructions. Certain kernel parameters may need to be set for perf to be able to inspect the @@ -311,7 +312,7 @@ or using a graphical tool like [Hotspot](https://github.com/KDAB/hotspot). See the functional test documentation for how to invoke perf within tests. -**Sanitizers** +### Sanitizers Bitcoin Core can be compiled with various "sanitizers" enabled, which add instrumentation for issues regarding things like memory safety, thread race @@ -372,7 +373,7 @@ Deadlocks due to inconsistent lock ordering (thread 1 locks `cs_main` and then `cs_wallet`, while thread 2 locks them in the opposite order: result, deadlock as each waits for the other to release its lock) are a problem. Compile with `-DDEBUG_LOCKORDER` (or use `--enable-debug`) to get lock order inconsistencies -reported in the debug.log file. +reported in the `debug.log` file. Re-architecting the core code so there are better-defined interfaces between the various components is a goal, with any necessary locking @@ -386,8 +387,6 @@ Threads - ThreadImport : Loads blocks from `blk*.dat` files or `-loadblock=<file>`. -- StartNode : Starts other threads. - - ThreadDNSAddressSeed : Loads addresses of peers from the DNS. - ThreadMapPort : Universal plug-and-play startup/shutdown. @@ -400,7 +399,7 @@ Threads - ThreadMessageHandler : Higher-level message handling (sending and receiving). -- DumpAddresses : Dumps IP addresses of nodes to peers.dat. +- DumpAddresses : Dumps IP addresses of nodes to `peers.dat`. - ThreadRPCServer : Remote procedure call handler, listens on port 8332 for connections and services them. @@ -466,11 +465,6 @@ Wallet - Make sure that no crashes happen with run-time option `-disablewallet`. - - *Rationale*: In RPC code that conditionally uses the wallet (such as - `validateaddress`), it is easy to forget that global pointer `pwalletMain` - can be nullptr. See `test/functional/disablewallet.py` for functional tests - exercising the API with `-disablewallet`. - - Include `db_cxx.h` (BerkeleyDB header) only when `ENABLE_WALLET` is set. - *Rationale*: Otherwise compilation of the disable-wallet build will fail in environments without BerkeleyDB. @@ -545,11 +539,10 @@ class A } ``` -- By default, declare single-argument constructors `explicit`. +- By default, declare constructors `explicit`. - - *Rationale*: This is a precaution to avoid unintended conversions that might - arise when single-argument constructors are used as implicit conversion - functions. + - *Rationale*: This is a precaution to avoid unintended + [conversions](https://en.cppreference.com/w/cpp/language/converting_constructor). - Use explicitly signed or unsigned `char`s, or even better `uint8_t` and `int8_t`. Do not use bare `char` unless it is to pass to a third-party API. @@ -889,7 +882,7 @@ Scripted diffs For reformatting and refactoring commits where the changes can be easily automated using a bash script, we use scripted-diff commits. The bash script is included in the commit message and our Travis CI job checks that the result of the script is identical to the commit. This aids reviewers since they can verify that the script -does exactly what it's supposed to do. It is also helpful for rebasing (since the same script can just be re-run +does exactly what it is supposed to do. It is also helpful for rebasing (since the same script can just be re-run on the new master commit). To create a scripted-diff: @@ -910,7 +903,35 @@ For development, it might be more convenient to verify all scripted-diffs in a r test/lint/commit-script-check.sh origin/master..HEAD ``` -Commit [`bb81e173`](https://github.com/bitcoin/bitcoin/commit/bb81e173) is an example of a scripted-diff. +### Suggestions and examples + +If you need to replace in multiple files, prefer `git ls-files` to `find` or globbing, and `git grep` to `grep`, to +avoid changing files that are not under version control. + +For efficient replacement scripts, reduce the selection to the files that potentially need to be modified, so for +example, instead of a blanket `git ls-files src | xargs sed -i s/apple/orange/`, use +`git grep -l apple src | xargs sed -i s/apple/orange/`. + +Also, it is good to keep the selection of files as specific as possible — for example, replace only in directories where +you expect replacements — because it reduces the risk that a rebase of your commit by re-running the script will +introduce accidental changes. + +Some good examples of scripted-diff: + +- [scripted-diff: Rename InitInterfaces to NodeContext](https://github.com/bitcoin/bitcoin/commit/301bd41a2e6765b185bd55f4c541f9e27aeea29d) +uses an elegant script to replace occurences of multiple terms in all source files. + +- [scripted-diff: Remove g_connman, g_banman globals](https://github.com/bitcoin/bitcoin/commit/301bd41a2e6765b185bd55f4c541f9e27aeea29d) +replaces specific terms in a list of specific source files. + +- [scripted-diff: Replace fprintf with tfm::format](https://github.com/bitcoin/bitcoin/commit/fac03ec43a15ad547161e37e53ea82482cc508f9) +does a global replacement but excludes certain directories. + +To find all previous uses of scripted diffs in the repository, do: + +``` +git log --grep="-BEGIN VERIFY SCRIPT-" +``` Release notes ------------- diff --git a/doc/man/bitcoin-cli.1 b/doc/man/bitcoin-cli.1 index 95c1d24dff..129651d8e9 100644 --- a/doc/man/bitcoin-cli.1 +++ b/doc/man/bitcoin-cli.1 @@ -113,7 +113,3 @@ The source code is available from <https://github.com/bitcoin/bitcoin>. This is experimental software. Distributed under the MIT software license, see the accompanying file COPYING or <https://opensource.org/licenses/MIT> - -This product includes software developed by the OpenSSL Project for use in the -OpenSSL Toolkit <https://www.openssl.org> and cryptographic software written by -Eric Young and UPnP software written by Thomas Bernard. diff --git a/doc/man/bitcoin-qt.1 b/doc/man/bitcoin-qt.1 index 1957fb736e..f68be21e8d 100644 --- a/doc/man/bitcoin-qt.1 +++ b/doc/man/bitcoin-qt.1 @@ -608,7 +608,3 @@ The source code is available from <https://github.com/bitcoin/bitcoin>. This is experimental software. Distributed under the MIT software license, see the accompanying file COPYING or <https://opensource.org/licenses/MIT> - -This product includes software developed by the OpenSSL Project for use in the -OpenSSL Toolkit <https://www.openssl.org> and cryptographic software written by -Eric Young and UPnP software written by Thomas Bernard. diff --git a/doc/man/bitcoin-tx.1 b/doc/man/bitcoin-tx.1 index 6b6071d9b7..b4c7698896 100644 --- a/doc/man/bitcoin-tx.1 +++ b/doc/man/bitcoin-tx.1 @@ -114,7 +114,3 @@ The source code is available from <https://github.com/bitcoin/bitcoin>. This is experimental software. Distributed under the MIT software license, see the accompanying file COPYING or <https://opensource.org/licenses/MIT> - -This product includes software developed by the OpenSSL Project for use in the -OpenSSL Toolkit <https://www.openssl.org> and cryptographic software written by -Eric Young and UPnP software written by Thomas Bernard. diff --git a/doc/man/bitcoin-wallet.1 b/doc/man/bitcoin-wallet.1 index 1cb8cdebcd..aadea09a2b 100644 --- a/doc/man/bitcoin-wallet.1 +++ b/doc/man/bitcoin-wallet.1 @@ -61,7 +61,3 @@ The source code is available from <https://github.com/bitcoin/bitcoin>. This is experimental software. Distributed under the MIT software license, see the accompanying file COPYING or <https://opensource.org/licenses/MIT> - -This product includes software developed by the OpenSSL Project for use in the -OpenSSL Toolkit <https://www.openssl.org> and cryptographic software written by -Eric Young and UPnP software written by Thomas Bernard. diff --git a/doc/man/bitcoind.1 b/doc/man/bitcoind.1 index b0aff99ca2..211ba10285 100644 --- a/doc/man/bitcoind.1 +++ b/doc/man/bitcoind.1 @@ -581,7 +581,3 @@ The source code is available from <https://github.com/bitcoin/bitcoin>. This is experimental software. Distributed under the MIT software license, see the accompanying file COPYING or <https://opensource.org/licenses/MIT> - -This product includes software developed by the OpenSSL Project for use in the -OpenSSL Toolkit <https://www.openssl.org> and cryptographic software written by -Eric Young and UPnP software written by Thomas Bernard. diff --git a/doc/release-notes.md b/doc/release-notes.md index a47c8802b0..07caf0e53a 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -46,16 +46,15 @@ Compatibility ============== Bitcoin Core is supported and extensively tested on operating systems using -the Linux kernel, macOS 10.10+, and Windows 7 and newer. It is not recommended +the Linux kernel, macOS 10.12+, and Windows 7 and newer. It is not recommended to use Bitcoin Core on unsupported systems. Bitcoin Core should also work on most other Unix-like systems but is not as frequently tested on them. -From Bitcoin Core 0.17.0 onwards, macOS versions earlier than 10.10 are no -longer supported, as Bitcoin Core is now built using Qt 5.9.x which requires -macOS 10.10+. Additionally, Bitcoin Core does not yet change appearance when -macOS "dark mode" is activated. +From Bitcoin Core 0.20.0 onwards, macOS versions earlier than 10.12 are no +longer supported. Additionally, Bitcoin Core does not yet change appearance +when macOS "dark mode" is activated. In addition to previously supported CPU platforms, this release's pre-compiled distribution provides binaries for the RISC-V platform. @@ -63,6 +62,16 @@ distribution provides binaries for the RISC-V platform. Notable changes =============== +Build System +------------ + +- OpenSSL is no longer used by Bitcoin Core. The last usage of the library +was removed in #17265. + +- glibc 2.17 or greater is now required to run the release binaries. This +retains compatibility with RHEL 7, CentOS 7, Debian 8 and Ubuntu 14.04 LTS. +Further details can be found in #17538. + New RPCs -------- @@ -81,6 +90,8 @@ Low-level Changes section below. GUI changes ----------- +- The "Start Bitcoin Core on system login" option has been removed on macOS. + Wallet ------ diff --git a/doc/release-notes/release-notes-0.19.0.1.md b/doc/release-notes/release-notes-0.19.0.1.md new file mode 100644 index 0000000000..70b8ec589f --- /dev/null +++ b/doc/release-notes/release-notes-0.19.0.1.md @@ -0,0 +1,1089 @@ +Bitcoin Core version 0.19.0.1 is now available from: + + <https://bitcoincore.org/bin/bitcoin-core-0.19.0.1/> + +This release includes new features, various bug fixes and performance +improvements, as well as updated translations. + +Please report bugs using the issue tracker at GitHub: + + <https://github.com/bitcoin/bitcoin/issues> + +To receive security and update notifications, please subscribe to: + + <https://bitcoincore.org/en/list/announcements/join/> + +How to Upgrade +============== + +If you are running an older version, shut it down. Wait until it has completely +shut down (which might take a few minutes for older versions), then run the +installer (on Windows) or just copy over `/Applications/Bitcoin-Qt` (on Mac) +or `bitcoind`/`bitcoin-qt` (on Linux). + +Upgrading directly from a version of Bitcoin Core that has reached its EOL is +possible, but might take some time if the datadir needs to be migrated. Old +wallet versions of Bitcoin Core are generally supported. + +Compatibility +============== + +Bitcoin Core is supported and extensively tested on operating systems using +the Linux kernel, macOS 10.10+, and Windows 7 and newer. It is not recommended +to use Bitcoin Core on unsupported systems. + +Bitcoin Core should also work on most other Unix-like systems but is not +as frequently tested on them. + +From 0.17.0 onwards, macOS <10.10 is no longer supported. 0.17.0 is +built using Qt 5.9.x, which doesn't support versions of macOS older than +10.10. Additionally, Bitcoin Core does not yet change appearance when +macOS "dark mode" is activated. + +Users running macOS Catalina may need to "right-click" and then choose "Open" +to open the Bitcoin Core .dmg. This is due to new signing requirements +imposed by Apple, which the Bitcoin Core project does not yet adhere too. + +Notable changes +=============== + +New user documentation +---------------------- + +- [Reduce memory](https://github.com/bitcoin/bitcoin/blob/master/doc/reduce-memory.md) + suggests configuration tweaks for running Bitcoin Core on systems with + limited memory. (#16339) + +New RPCs +-------- + +- `getbalances` returns an object with all balances (`mine`, + `untrusted_pending` and `immature`). Please refer to the RPC help of + `getbalances` for details. The new RPC is intended to replace + `getbalance`, `getunconfirmedbalance`, and the balance fields in + `getwalletinfo`. These old calls and fields may be removed in a + future version. (#15930, #16239) + +- `setwalletflag` sets and unsets wallet flags that enable or disable + features specific to that existing wallet, such as the new + `avoid_reuse` feature documented elsewhere in these release notes. + (#13756) + +- `getblockfilter` gets the BIP158 filter for the specified block. This + RPC is only enabled if block filters have been created using the + `-blockfilterindex` configuration option. (#14121) + +New settings +------------ + +- `-blockfilterindex` enables the creation of BIP158 block filters for + the entire blockchain. Filters will be created in the background and + currently use about 4 GiB of space. Note: this version of Bitcoin + Core does not serve block filters over the P2P network, although the + local user may obtain block filters using the `getblockfilter` RPC. + (#14121) + +Updated settings +---------------- + +- `whitebind` and `whitelist` now accept a list of permissions to + provide peers connecting using the indicated interfaces or IP + addresses. If no permissions are specified with an address or CIDR + network, the implicit default permissions are the same as previous + releases. See the `bitcoind -help` output for these two options for + details about the available permissions. (#16248) + +- Users setting custom `dbcache` values can increase their setting slightly + without using any more real memory. Recent changes reduced the memory use + by about 9% and made chainstate accounting more accurate (it was underestimating + the use of memory before). For example, if you set a value of "450" before, you + may now set a value of "500" to use about the same real amount of memory. (#16957) + + +Updated RPCs +------------ + +Note: some low-level RPC changes mainly useful for testing are described in the +Low-level Changes section below. + +- `sendmany` no longer has a `minconf` argument. This argument was not + well-specified and would lead to RPC errors even when the wallet's + coin selection succeeded. Users who want to influence coin selection + can use the existing `-spendzeroconfchange`, `-limitancestorcount`, + `-limitdescendantcount` and `-walletrejectlongchains` configuration + arguments. (#15596) + +- `getbalance` and `sendtoaddress`, plus the new RPCs `getbalances` and + `createwallet`, now accept an "avoid_reuse" parameter that controls + whether already used addresses should be included in the operation. + Additionally, `sendtoaddress` will avoid partial spends when + `avoid_reuse` is enabled even if this feature is not already enabled + via the `-avoidpartialspends` command line flag because not doing so + would risk using up the "wrong" UTXO for an address reuse case. + (#13756) + +- RPCs which have an `include_watchonly` argument or `includeWatching` option now default to `true` for watch-only + wallets. Affected RPCs are: `getbalance`, `listreceivedbyaddress`, `listreceivedbylabel`, `listtransactions`, + `listsinceblock`, `gettransaction`, `walletcreatefundedpsbt`, and `fundrawtransaction`. (#16383) + +- `listunspent` now returns a "reused" bool for each output if the + wallet flag "avoid_reuse" is enabled. (#13756) + +- `getblockstats` now uses BlockUndo data instead of the transaction + index, making it much faster, no longer dependent on the `-txindex` + configuration option, and functional for all non-pruned blocks. + (#14802) + +- `utxoupdatepsbt` now accepts a `descriptors` parameter that will fill + out input and output scripts and keys when known. P2SH-witness inputs + will be filled in from the UTXO set when a descriptor is provided that + shows they're spending segwit outputs. See the RPC help text for full + details. (#15427) + +- `sendrawtransaction` and `testmempoolaccept` no longer accept a + `allowhighfees` parameter to fail mempool acceptance if the + transaction fee exceeds the value of the configuration option + `-maxtxfee`. Now there is a hardcoded default maximum feerate that + can be changed when calling either RPC using a `maxfeerate` parameter. + (#15620) + +- `getmempoolancestors`, `getmempooldescendants`, `getmempoolentry`, and + `getrawmempool` no longer return a `size` field unless the + configuration option `-deprecatedrpc=size` is used. Instead a new + `vsize` field is returned with the transaction's virtual size + (consistent with other RPCs such as `getrawtransaction`). (#15637) + +- `getwalletinfo` now includes a `scanning` field that is either `false` + (no scanning) or an object with information about the duration and + progress of the wallet's scanning historical blocks for transactions + affecting its balances. (#15730) + +- `gettransaction` now accepts a third (boolean) argument `verbose`. If + set to `true`, a new `decoded` field will be added to the response containing + the decoded transaction. This field is equivalent to RPC `decoderawtransaction`, + or RPC `getrawtransaction` when `verbose` is passed. (#16185, #16866, #16873) + +- `createwallet` accepts a new `passphrase` parameter. If set, this + will create the new wallet encrypted with the given passphrase. If + unset (the default) or set to an empty string, no encryption will be + used. (#16394) + +- `getchaintxstats` RPC now returns the additional key of + `window_final_block_height`. (#16695) + +- `getmempoolentry` now provides a `weight` field containing the + transaction weight as defined in BIP141. (#16647) + +- The `getnetworkinfo` and `getpeerinfo` commands now contain a new field with decoded network service flags. (#16786) + +- `getdescriptorinfo` now returns an additional `checksum` field + containing the checksum for the unmodified descriptor provided by the + user (that is, before the descriptor is normalized for the + `descriptor` field). (#15986) + +- `joinpsbts` now shuffles the order of the inputs and outputs of the resulting + joined PSBT. Previously, inputs and outputs were added in the order PSBTs were + provided. This made it easy to correlate inputs to outputs, representing a + privacy leak. (#16512) + +- `walletcreatefundedpsbt` now signals BIP125 Replace-by-Fee if the + `-walletrbf` configuration option is set to true. (#15911) + +GUI changes +----------- + +- The GUI wallet now provides bech32 addresses by default. The user may change the address type + during invoice generation using a GUI toggle, or the default address + type may be changed with the `-addresstype` configuration option. + (#15711, #16497) + +- In 0.18.0, a `./configure` flag was introduced to allow disabling BIP70 support in the GUI (support was enabled by default). In 0.19.0, this flag is now __disabled__ by default. If you want to compile Bitcoin Core with BIP70 support in the GUI, you can pass `--enable-bip70` to `./configure`. (#15584) + +Deprecated or removed configuration options +------------------------------------------- + +- `-mempoolreplacement` is removed, although default node behavior + remains the same. This option previously allowed the user to prevent + the node from accepting or relaying BIP125 transaction replacements. + This is different from the remaining configuration option + `-walletrbf`. (#16171) + +Deprecated or removed RPCs +-------------------------- + +- `bumpfee` no longer accepts a `totalFee` option unless the + configuration parameter `deprecatedrpc=totalFee` is specified. This + parameter will be fully removed in a subsequent release. (#15996) + +- `bumpfee` has a new `fee_rate` option as a replacement for the deprecated `totalFee`. (#16727) + +- `generate` is now removed after being deprecated in Bitcoin Core 0.18. + Use the `generatetoaddress` RPC instead. (#15492) + +P2P changes +----------- + +- BIP 61 reject messages were deprecated in v0.18. They are now disabled + by default, but can be enabled by setting the `-enablebip61` command + line option. BIP 61 reject messages will be removed entirely in a + future version of Bitcoin Core. (#14054) + +- To eliminate well-known denial-of-service vectors in Bitcoin Core, + especially for nodes with spinning disks, the default value for the + `-peerbloomfilters` configuration option has been changed to false. + This prevents Bitcoin Core from sending the BIP111 NODE_BLOOM service + flag, accepting BIP37 bloom filters, or serving merkle blocks or + transactions matching a bloom filter. Users who still want to provide + bloom filter support may either set the configuration option to true + to re-enable both BIP111 and BIP37 support or enable just BIP37 + support for specific peers using the updated `-whitelist` and + `-whitebind` configuration options described elsewhere in these + release notes. For the near future, lightweight clients using public + BIP111/BIP37 nodes should still be able to connect to older versions + of Bitcoin Core and nodes that have manually enabled BIP37 support, + but developers of such software should consider migrating to either + using specific BIP37 nodes or an alternative transaction filtering + system. (#16152) + +- By default, Bitcoin Core will now make two additional outbound connections that are exclusively used for block-relay. No transactions or addr messages will be processed on these connections. These connections are designed to add little additional memory or bandwidth resource requirements but should make some partitioning attacks more difficult to carry out. (#15759) + +Miscellaneous CLI Changes +------------------------- + +- The `testnet` field in `bitcoin-cli -getinfo` has been renamed to + `chain` and now returns the current network name as defined in BIP70 + (main, test, regtest). (#15566) + +Low-level changes +================= + +RPC +--- + +- `getblockchaininfo` no longer returns a `bip9_softforks` object. + Instead, information has been moved into the `softforks` object and + an additional `type` field describes how Bitcoin Core determines + whether that soft fork is active (e.g. BIP9 or BIP90). See the RPC + help for details. (#16060) + +- `getblocktemplate` no longer returns a `rules` array containing `CSV` + and `segwit` (the BIP9 deployments that are currently in active + state). (#16060) + +- `getrpcinfo` now returns a `logpath` field with the path to + `debug.log`. (#15483) + +Tests +----- + +- The regression test chain enabled by the `-regtest` command line flag + now requires transactions to not violate standard policy by default. + This is the same default used for mainnet and makes it easier to test + mainnet behavior on regtest. Note that the testnet still allows + non-standard txs by default and that the policy can be locally + adjusted with the `-acceptnonstdtxn` command line flag for both test + chains. (#15891) + +Configuration +------------ + +- A setting specified in the default section but not also specified in a + network-specific section (e.g. testnet) will now produce an error + preventing startup instead of just a warning unless the network is + mainnet. This prevents settings intended for mainnet from being + applied to testnet or regtest. (#15629) + +- On platforms supporting `thread_local`, log lines can be prefixed with + the name of the thread that caused the log. To enable this behavior, + use `-logthreadnames=1`. (#15849) + +Network +------- + +- When fetching a transaction announced by multiple peers, previous versions of + Bitcoin Core would sequentially attempt to download the transaction from each + announcing peer until the transaction is received, in the order that those + peers' announcements were received. In this release, the download logic has + changed to randomize the fetch order across peers and to prefer sending + download requests to outbound peers over inbound peers. This fixes an issue + where inbound peers could prevent a node from getting a transaction. + (#14897, #15834) + +- If a Tor hidden service is being used, Bitcoin Core will be bound to + the standard port 8333 even if a different port is configured for + clearnet connections. This prevents leaking node identity through use + of identical non-default port numbers. (#15651) + +Mempool and transaction relay +----------------------------- + +- Allows one extra single-ancestor transaction per package. Previously, + if a transaction in the mempool had 25 descendants, or it and all of + its descendants were over 101,000 vbytes, any newly-received + transaction that was also a descendant would be ignored. Now, one + extra descendant will be allowed provided it is an immediate + descendant (child) and the child's size is 10,000 vbytes or less. + This makes it possible for two-party contract protocols such as + Lightning Network to give each participant an output they can spend + immediately for Child-Pays-For-Parent (CPFP) fee bumping without + allowing one malicious participant to fill the entire package and thus + prevent the other participant from spending their output. (#15681) + +- Transactions with outputs paying v1 to v16 witness versions (future + segwit versions) are now accepted into the mempool, relayed, and + mined. Attempting to spend those outputs remains forbidden by policy + ("non-standard"). When this change has been widely deployed, wallets + and services can accept any valid bech32 Bitcoin address without + concern that transactions paying future segwit versions will become + stuck in an unconfirmed state. (#15846) + +- Legacy transactions (transactions with no segwit inputs) must now be + sent using the legacy encoding format, enforcing the rule specified in + BIP144. (#14039) + +Wallet +------ + +- When in pruned mode, a rescan that was triggered by an `importwallet`, + `importpubkey`, `importaddress`, or `importprivkey` RPC will only fail + when blocks have been pruned. Previously it would fail when `-prune` + has been set. This change allows setting `-prune` to a high value + (e.g. the disk size) without the calls to any of the import RPCs + failing until the first block is pruned. (#15870) + +- When creating a transaction with a fee above `-maxtxfee` (default 0.1 + BTC), the RPC commands `walletcreatefundedpsbt` and + `fundrawtransaction` will now fail instead of rounding down the fee. + Be aware that the `feeRate` argument is specified in BTC per 1,000 + vbytes, not satoshi per vbyte. (#16257) + +- A new wallet flag `avoid_reuse` has been added (default off). When + enabled, a wallet will distinguish between used and unused addresses, + and default to not use the former in coin selection. When setting + this flag on an existing wallet, rescanning the blockchain is required + to correctly mark previously used destinations. Together with "avoid + partial spends" (added in Bitcoin Core v0.17.0), this can eliminate a + serious privacy issue where a malicious user can track spends by + sending small payments to a previously-paid address that would then + be included with unrelated inputs in future payments. (#13756) + +Build system changes +-------------------- + +- Python >=3.5 is now required by all aspects of the project. This + includes the build systems, test framework and linters. The previously + supported minimum (3.4), was EOL in March 2019. (#14954) + +- The minimum supported miniUPnPc API version is set to 10. This keeps + compatibility with Ubuntu 16.04 LTS and Debian 8 `libminiupnpc-dev` + packages. Please note, on Debian this package is still vulnerable to + [CVE-2017-8798](https://security-tracker.debian.org/tracker/CVE-2017-8798) + (in jessie only) and + [CVE-2017-1000494](https://security-tracker.debian.org/tracker/CVE-2017-1000494) + (both in jessie and in stretch). (#15993) + +0.19.0 change log +================= + +### Consensus +- #16128 Delete error-prone CScript constructor only used with FindAndDelete (instagibbs) +- #16060 Bury bip9 deployments (jnewbery) + +### Policy +- #15557 Enhance `bumpfee` to include inputs when targeting a feerate (instagibbs) +- #15846 Make sending to future native witness outputs standard (sipa) + +### Block and transaction handling +- #15632 Remove ResendWalletTransactions from the Validation Interface (jnewbery) +- #14121 Index for BIP 157 block filters (jimpo) +- #15141 Rewrite DoS interface between validation and net_processing (sdaftuar) +- #15880 utils and libraries: Replace deprecated Boost Filesystem functions (hebasto) +- #15971 validation: Add compile-time checking for negative locking requirement in LimitValidationInterfaceQueue (practicalswift) +- #15999 init: Remove dead code in LoadChainTip (MarcoFalke) +- #16015 validation: Hold cs_main when reading chainActive in RewindBlockIndex (practicalswift) +- #16056 remove unused magic number from consistency check (instagibbs) +- #16171 Remove -mempoolreplacement to prevent needless block prop slowness (TheBlueMatt) +- #15894 Remove duplicated "Error: " prefix in logs (hebasto) +- #14193 validation: Add missing mempool locks (MarcoFalke) +- #15681 Allow one extra single-ancestor transaction per package (TheBlueMatt) +- #15305 [validation] Crash if disconnecting a block fails (sdaftuar) +- #16471 log correct messages when CPFP fails (jnewbery) +- #16433 txmempool: Remove unused default value MemPoolRemovalReason::UNKNOWN (MarcoFalke) +- #13868 Remove unused fScriptChecks parameter from CheckInputs (Empact) +- #16421 Conservatively accept RBF bumps bumping one tx at the package limits (TheBlueMatt) +- #16854 Prevent UpdateTip log message from being broken up (stevenroose) +- #16956 validation: Make GetWitnessCommitmentIndex public (MarcoFalke) +- #16713 Ignore old versionbit activations to avoid 'unknown softforks' warning (jnewbery) +- #17002 chainparams: Bump assumed chain params (MarcoFalke) +- #16849 Fix block index inconsistency in InvalidateBlock() (sdaftuar) + +### P2P protocol and network code +- #15597 Generate log entry when blocks messages are received unexpectedly (pstratem) +- #15654 Remove unused unsanitized user agent string CNode::strSubVer (MarcoFalke) +- #15689 netaddress: Update CNetAddr for ORCHIDv2 (dongcarl) +- #15834 Fix transaction relay bugs introduced in #14897 and expire transactions from peer in-flight map (sdaftuar) +- #15651 torcontrol: Use the default/standard network port for Tor hidden services, even if the internal port is set differently (luke-jr) +- #16188 Document what happens to getdata of unknown type (MarcoFalke) +- #15649 Add ChaCha20Poly1305@Bitcoin AEAD (jonasschnelli) +- #16152 Disable bloom filtering by default (TheBlueMatt) +- #15993 Drop support of the insecure miniUPnPc versions (hebasto) +- #16197 Use mockable time for tx download (MarcoFalke) +- #16248 Make whitebind/whitelist permissions more flexible (NicolasDorier) +- #16618 [Fix] Allow connection of a noban banned peer (NicolasDorier) +- #16631 Restore default whitelistrelay to true (NicolasDorier) +- #15759 Add 2 outbound block-relay-only connections (sdaftuar) +- #15558 Don't query all DNS seeds at once (sipa) +- #16999 0.19 seeds update (laanwj) + +### Wallet +- #15288 Remove wallet -> node global function calls (ryanofsky) +- #15491 Improve log output for errors during load (gwillen) +- #13541 wallet/rpc: sendrawtransaction maxfeerate (kallewoof) +- #15680 Remove resendwallettransactions RPC method (jnewbery) +- #15508 Refactor analyzepsbt for use outside RPC code (gwillen) +- #15747 Remove plethora of Get*Balance (MarcoFalke) +- #15728 Refactor relay transactions (jnewbery) +- #15639 bitcoin-wallet tool: Drop libbitcoin_server.a dependency (ryanofsky) +- #15853 Remove unused import checkpoints.h (MarcoFalke) +- #15780 add cachable amounts for caching credit/debit values (kallewoof) +- #15778 Move maxtxfee from node to wallet (jnewbery) +- #15901 log on rescan completion (andrewtoth) +- #15917 Avoid logging no_such_file_or_directory error (promag) +- #15452 Replace CScriptID and CKeyID in CTxDestination with dedicated types (instagibbs) +- #15870 Only fail rescan when blocks have actually been pruned (MarcoFalke) +- #15006 Add option to create an encrypted wallet (achow101) +- #16001 Give WalletModel::UnlockContext move semantics (sipa) +- #15741 Batch write imported stuff in importmulti (achow101) +- #16144 do not encrypt wallets with disabled private keys (mrwhythat) +- #15024 Allow specific private keys to be derived from descriptor (meshcollider) +- #13756 "avoid_reuse" wallet flag for improved privacy (kallewoof) +- #16226 Move ismine to the wallet module (achow101) +- #16239 wallet/rpc: follow-up clean-up/fixes to avoid_reuse (kallewoof) +- #16286 refactoring: wallet: Fix GCC 7.4.0 warning (hebasto) +- #16257 abort when attempting to fund a transaction above -maxtxfee (Sjors) +- #16237 Have the wallet give out destinations instead of keys (achow101) +- #16322 Fix -maxtxfee check by moving it to CWallet::CreateTransaction (promag) +- #16361 Remove redundant pre-TopUpKeypool check (instagibbs) +- #16244 Move wallet creation out of the createwallet rpc into its own function (achow101) +- #16227 Refactor CWallet's inheritance chain (achow101) +- #16208 Consume ReserveDestination on successful CreateTransaction (instagibbs) +- #16301 Use CWallet::Import* functions in all import* RPCs (achow101) +- #16402 Remove wallet settings from chainparams (MarcoFalke) +- #16415 Get rid of PendingWalletTx class (ryanofsky) +- #15588 Log the actual wallet file version and no longer publicly expose the "version" record (achow101) +- #16399 Improve wallet creation (fjahr) +- #16475 Enumerate walletdb keys (MarcoFalke) +- #15709 Do not add "setting" key as unknown (Bushstar) +- #16451 Remove CMerkleTx (jnewbery) +- #15906 Move min_depth and max_depth to coin control (amitiuttarwar) +- #16502 Drop unused OldKey (promag) +- #16394 Allow createwallet to take empty passwords to make unencrypted wallets (achow101) +- #15911 Use wallet RBF default for walletcreatefundedpsbt (Sjors) +- #16503 Remove p2pEnabled from Chain interface (ariard) +- #16557 restore coinbase and confirmed/conflicted checks in SubmitMemoryPoolAndRelay() (jnewbery) +- #14934 Descriptor expansion cache clarifications (Sjors) +- #16383 rpcwallet: default include_watchonly to true for watchonly wallets (jb55) +- #16542 Return more specific errors about invalid descriptors (achow101) +- #16572 Fix Char as Bool in Wallet (JeremyRubin) +- #16753 extract PubKey from P2PK script with Solver (theStack) +- #16716 Use wallet name instead of pointer on unload/release (promag) +- #16185 gettransaction: add an argument to decode the transaction (darosior) +- #16745 Translate all initErrors in CreateWalletFromFile (MarcoFalke) +- #16792 Assert that the HRP is lowercase in Bech32::Encode (meshcollider) +- #16624 encapsulate transactions state (ariard) +- #16830 Cleanup walletinitinterface.h (hebasto) +- #16796 Fix segfault in CreateWalletFromFile (MarcoFalke) +- #16866 Rename 'decode' argument in gettransaction method to 'verbose' (jnewbery) +- #16727 Explicit feerate for bumpfee (instagibbs) +- #16609 descriptor: fix missed m_script_arg arg renaming in #14934 (fanquake) + +### RPC and other APIs +- #15492 remove deprecated generate method (Sjors) +- #15566 cli: Replace testnet with chain and return network name as per bip70 (fanquake) +- #15564 cli: Remove duplicate wallet fields from -getinfo (fanquake) +- #15642 Remove deprecated rpc warnings (jnewbery) +- #15637 Rename size to vsize in mempool related calls (fanquake) +- #15620 Uncouple non-wallet rpcs from maxTxFee global (MarcoFalke) +- #15616 Clarify decodescript RPCResult doc (MarcoFalke) +- #15669 Fix help text for signtransactionwithXXX (torkelrogstad) +- #15596 Ignore sendmany::minconf as dummy value (MarcoFalke) +- #15755 remove unused var in rawtransaction.cpp (Bushstar) +- #15746 RPCHelpMan: Always name dictionary keys (MarcoFalke) +- #15748 remove dead mining code (jnewbery) +- #15751 Speed up deriveaddresses for large ranges (sipa) +- #15770 Validate maxfeerate with AmountFromValue (promag) +- #15474 rest/rpc: Make mempoolinfo atomic (promag) +- #15463 Speedup getaddressesbylabel (promag) +- #15784 Remove dependency on interfaces::Chain in SignTransaction (ariard) +- #15323 Expose g_is_mempool_loaded via getmempoolinfo (Empact) +- #15932 Serialize in getblock without cs_main (MarcoFalke) +- #15930 Add balances RPC (MarcoFalke) +- #15730 Show scanning details in getwalletinfo (promag) +- #14802 faster getblockstats using BlockUndo data (FelixWeis) +- #14984 Speedup getrawmempool when verbose=true (promag) +- #16071 Hint for importmulti in help output of importpubkey and importaddress (kristapsk) +- #16063 Mention getwalletinfo where a rescan is triggered (promag) +- #16024 deriveaddresses: Correction of descriptor checksum in RPC example (ccapo) +- #16217 getrawtransaction: inform about blockhash argument when lookup fails (darosior) +- #15427 Add support for descriptors to utxoupdatepsbt (sipa) +- #16262 Allow shutdown while in generateblocks (pstratem) +- #15483 Adding a 'logpath' entry to getrpcinfo (darosior) +- #16325 Clarify that block count means height excl genesis (MarcoFalke) +- #16326 add new utxoupdatepsbt arguments to the CRPCCommand and CPRCCvertParam tables (jnewbery) +- #16332 Add logpath description for getrpcinfo (instagibbs) +- #16240 JSONRPCRequest-aware RPCHelpMan (kallewoof) +- #15996 Deprecate totalfee argument in `bumpfee` (instagibbs) +- #16467 sendrawtransaction help privacy note (jonatack) +- #16596 Fix getblocktemplate CLI example (emilengler) +- #15986 Add checksum to getdescriptorinfo (sipa) +- #16647 add weight to getmempoolentry output (fanquake) +- #16695 Add window final block height to getchaintxstats (leto) +- #16798 Refactor rawtransaction_util's SignTransaction to separate prevtx parsing (achow101) +- #16285 Improve scantxoutset response and help message (promag) +- #16725 Don't show addresses or P2PK in decoderawtransaction (NicolasDorier) +- #16787 Human readable network services (darosior) +- #16251 Improve signrawtransaction error reporting (ajtowns) +- #16873 fix regression in gettransaction (jonatack) +- #16512 Shuffle inputs and outputs after joining psbts (achow101) +- #16521 Use the default maxfeerate value as BTC/kB (Remagpie) +- #16817 Fix casing in getblockchaininfo to be inline with other fields (dangershony) +- #17131 fix -rpcclienttimeout 0 option (fjahr) +- #17249 Add missing deque include to fix build (jbeich) +- #17368 cli: fix -getinfo output when compiled with no wallet (fanquake) + +### GUI +- #15464 Drop unused return values in WalletFrame (promag) +- #15614 Defer removeAndDeleteWallet when no modal widget is active (promag) +- #15711 Generate bech32 addresses by default (MarcoFalke) +- #15829 update request payment button text and tab description (fanquake) +- #15874 Resolve the qt/guiutil <-> qt/optionsmodel CD (251Labs) +- #15371 Uppercase bech32 addresses in qr codes (benthecarman) +- #15928 Move QRImageWidget to its own file-pair (luke-jr) +- #16113 move coin control "OK" to the right hand side of the dialog (fanquake) +- #16090 Add vertical spacer to peer detail widget (JosuGZ) +- #15886 qt, wallet: Revamp SendConfirmationDialog (hebasto) +- #16263 Use qInfo() if no error occurs (hebasto) +- #16153 Add antialiasing to traffic graph widget (JosuGZ) +- #16350 Remove unused guard (hebasto) +- #16106 Sort wallets in open wallet menu (promag) +- #16291 Stop translating PACKAGE_NAME (MarcoFalke) +- #16380 Remove unused bits from the service flags enum (MarcoFalke) +- #16379 Fix autostart filenames on Linux for testnet/regtest (hebasto) +- #16366 init: Use InitError for all errors in bitcoind/qt (MarcoFalke) +- #16436 Do not create payment server if -disablewallet option provided (hebasto) +- #16514 Remove unused RPCConsole::tabFocus (promag) +- #16497 Generate bech32 addresses by default (take 2, fixup) (MarcoFalke) +- #16349 Remove redundant WalletController::addWallet slot (hebasto) +- #16578 Do not pass in command line arguments to QApplication (achow101) +- #16612 Remove menu icons (laanwj) +- #16677 remove unused PlatformStyle::TextColorIcon (fanquake) +- #16694 Ensure transaction send error is always visible (fanquake) +- #14879 Add warning messages to the debug window (hebasto) +- #16708 Replace obsolete functions of QSslSocket (hebasto) +- #16701 Replace functions deprecated in Qt 5.13 (hebasto) +- #16706 Replace deprecated QSignalMapper by lambda expressions (hebasto) +- #16707 Remove obsolete QModelIndex::child() (hebasto) +- #16758 Replace QFontMetrics::width() with TextWidth() (hebasto) +- #16760 Change uninstall icon on Windows (GChuf) +- #16720 Replace objc_msgSend() function calls with the native Objective-C syntax (hebasto) +- #16788 Update transifex slug for 0.19 (laanwj) +- #15450 Create wallet menu option (achow101) +- #16735 Remove unused menu items for Windows and Linux (GChuf) +- #16826 Do additional character escaping for wallet names and address labels (achow101) +- #15529 Add Qt programs to msvc build (updated, no code changes) (sipsorcery) +- #16714 add prune to intro screen with smart default (Sjors) +- #16858 advise users not to switch wallets when opening a BIP70 URI (jameshilliard) +- #16822 Create wallet menu option follow-ups (jonatack) +- #16882 Re-generate translations before 0.19.0 (MarcoFalke) +- #16928 Rename address checkbox back to bech32 (MarcoFalke) +- #16837 Fix {C{,XX},LD}FLAGS pickup (dongcarl) +- #16971 Change default size of intro frame (emilengler) +- #16988 Periodic translations update (laanwj) +- #16852 When BIP70 is disabled, get PaymentRequest merchant using string search (achow101) +- #16952 make sure to update the UI when deleting a transaction (jonasschnelli) +- #17031 Prevent processing duplicate payment requests (promag) +- #17135 Make polling in ClientModel asynchronous (promag) +- #17120 Fix start timer from non QThread (promag) +- #17257 disable font antialiasing for QR image address (fanquake) + +### Build system +- #14954 Require python 3.5 (MarcoFalke) +- #15580 native_protobuf: avoid system zlib (dongcarl) +- #15601 Switch to python3 (take 3) (MarcoFalke) +- #15581 Make less assumptions about build env (dongcarl) +- #14853 latest RapidCheck (fanquake) +- #15446 Improve depends debuggability (dongcarl) +- #13788 Fix --disable-asm for newer assembly checks/code (luke-jr) +- #12051 add missing debian contrib file to tarball (puchu) +- #15919 Remove unused OpenSSL includes to make it more clear where OpenSSL is used (practicalswift) +- #15978 .gitignore: Don't ignore depends patches (dongcarl) +- #15939 gitian: Remove windows 32 bit build (MarcoFalke) +- #15239 scripts and tools: Move non-linux build source tarballs to "bitcoin-binaries/version" directory (hebasto) +- #14047 Add HKDF_HMAC256_L32 and method to negate a private key (jonasschnelli) +- #16051 add patch to common dependencies (fanquake) +- #16049 switch to secure download of all dependencies (Kemu) +- #16059 configure: Fix thread_local detection (dongcarl) +- #16089 add ability to skip building zeromq (fanquake) +- #15844 Purge libtool archives (dongcarl) +- #15461 update to Boost 1.70 (Sjors) +- #16141 remove GZIP export from gitian descriptors (fanquake) +- #16235 Cleaned up and consolidated msbuild files (no code changes) (sipsorcery) +- #16246 MSVC: Fix error in debug mode (Fix #16245) (NicolasDorier) +- #16183 xtrans: Configure flags cleanup (dongcarl) +- #16258 [MSVC]: Create the config.ini as part of bitcoind build (NicolasDorier) +- #16271 remove -Wall from rapidcheck build flags (fanquake) +- #16309 [MSVC] allow user level project customization (NicolasDorier) +- #16308 [MSVC] Copy build output to src/ automatically after build (NicolasDorier) +- #15457 Check std::system for -[alert|block|wallet]notify (Sjors) +- #16344 use #if HAVE_SYSTEM instead of defined(HAVE_SYSTEM) (Sjors) +- #16352 prune dbus from depends (fanquake) +- #16270 expat 2.2.7 (fanquake) +- #16408 Prune X packages (dongcarl) +- #16386 disable unused Qt features (fanquake) +- #16424 Treat -Wswitch as error when --enable-werror (MarcoFalke) +- #16441 remove qt libjpeg check from bitcoin_qt.m4 (fanquake) +- #16434 Specify AM_CPPFLAGS for ZMQ (domob1812) +- #16534 add Qt Creator Makefile.am.user to .gitignore (Bushstar) +- #16573 disable building libsecp256k1 benchmarks (fanquake) +- #16533 disable libxcb extensions (fanquake) +- #16589 Remove unused src/obj-test folder (MarcoFalke) +- #16435 autoconf: Sane `--enable-debug` defaults (dongcarl) +- #16622 echo property tests status during build (jonatack) +- #16611 Remove src/obj directory from repository (laanwj) +- #16371 ignore macOS make deploy artefacts & add them to clean-local (fanquake) +- #16654 build: update RapidCheck Makefile (jonatack) +- #16370 cleanup package configure flags (fanquake) +- #16746 msbuild: Ignore linker warning (sipsorcery) +- #16750 msbuild: adds bench_bitcoin to auto generated project files (sipsorcery) +- #16810 guix: Remove ssp spec file hack (dongcarl) +- #16477 skip deploying plugins we dont use in macdeployqtplus (fanquake) +- #16413 Bump QT to LTS release 5.9.8 (THETCR) +- #15584 disable BIP70 support by default (fanquake) +- #16871 make building protobuf optional in depends (fanquake) +- #16879 remove redundant sed patching (fanquake) +- #16809 zlib: Move toolchain options to configure (dongcarl) +- #15146 Solve SmartOS FD_ZERO build issue (Empact) +- #16870 update boost macros to latest upstream for improved error reporting (fanquake) +- #16982 Factor out qt translations from build system (laanwj) +- #16926 Add OpenSSL termios fix for musl libc (nmarley) +- #16927 Refresh ZeroMQ 4.3.1 patch (nmarley) +- #17005 Qt version appears only if GUI is being built (ch4ot1c) +- #16468 Exclude depends/Makefile in .gitignore (promag) + +### Tests and QA +- #15296 Add script checking for deterministic line coverage in unit tests (practicalswift) +- #15338 ci: Build and run tests once on freebsd (MarcoFalke) +- #15479 Add .style.yapf (MarcoFalke) +- #15534 lint-format-strings: open files sequentially (fix for OS X) (gwillen) +- #15504 fuzz: Link BasicTestingSetup (shared with unit tests) (MarcoFalke) +- #15473 bench: Benchmark mempooltojson (MarcoFalke) +- #15466 Print remaining jobs in test_runner.py (stevenroose) +- #15631 mininode: Clearer error message on invalid magic bytes (MarcoFalke) +- #15255 Remove travis_wait from lint script (gkrizek) +- #15686 make pruning test faster (jnewbery) +- #15533 .style.yapf: Set column_limit=160 (MarcoFalke) +- #15660 Overhaul p2p_compactblocks.py (sdaftuar) +- #15495 Add regtests for HTTP status codes (domob1812) +- #15772 Properly log named args in authproxy (MarcoFalke) +- #15771 Prevent concurrency issues reading .cookie file (promag) +- #15693 travis: Switch to ubuntu keyserver to avoid timeouts (MarcoFalke) +- #15629 init: Throw error when network specific config is ignored (MarcoFalke) +- #15773 Add BitcoinTestFramework::sync_* methods (MarcoFalke) +- #15797 travis: Bump second timeout to 33 minutes, add rationale (MarcoFalke) +- #15788 Unify testing setups for fuzz, bench, and unit tests (MarcoFalke) +- #15352 Reduce noise level in test_bitcoin output (practicalswift) +- #15779 Add wallet_balance benchmark (MarcoFalke) +- #15843 fix outdated include in blockfilter_index_tests (jamesob) +- #15866 Add missing syncwithvalidationinterfacequeue to wallet_import_rescan (MarcoFalke) +- #15697 Make swap_magic_bytes in p2p_invalid_messages atomic (MarcoFalke) +- #15895 Avoid re-reading config.ini unnecessarily (luke-jr) +- #15896 feature_filelock, interface_bitcoin_cli: Use PACKAGE_NAME in messages rather than hardcoding Bitcoin Core (luke-jr) +- #15897 QA/mininode: Send all headers upfront in send_blocks_and_test to avoid sending an unconnected one (luke-jr) +- #15696 test_runner: Move feature_pruning to base tests (MarcoFalke) +- #15869 Add settings merge test to prevent regresssions (ryanofsky) +- #15758 Add further tests to wallet_balance (MarcoFalke) +- #15841 combine_logs: append node stderr and stdout if it exists (MarcoFalke) +- #15949 test_runner: Move pruning back to extended (MarcoFalke) +- #15927 log thread names by default in functional tests (jnewbery) +- #15664 change default Python block serialization to witness (instagibbs) +- #15988 Add test for ArgsManager::GetChainName (ryanofsky) +- #15963 Make random seed logged and settable (jnewbery) +- #15943 Fail if RPC has been added without tests (MarcoFalke) +- #16036 travis: Run all lint scripts even if one fails (scravy) +- #13555 parameterize adjustment period in versionbits_computeblockversion (JBaczuk) +- #16079 wallet_balance.py: Prevent edge cases (stevenroose) +- #16078 replace tx hash with txid in rawtransaction test (LongShao007) +- #16042 Bump MAX_NODES to 12 (MarcoFalke) +- #16124 Limit Python linting to files in the repo (practicalswift) +- #16143 Mark unit test blockfilter_index_initial_sync as non-deterministic (practicalswift) +- #16214 travis: Fix caching issues (MarcoFalke) +- #15982 Make msg_block a witness block (MarcoFalke) +- #16225 Make coins_tests/updatecoins_simulation_test deterministic (practicalswift) +- #16236 fuzz: Log output even if fuzzer failed (MarcoFalke) +- #15520 cirrus: Run extended test feature_pruning (MarcoFalke) +- #16234 Add test for unknown args (MarcoFalke) +- #16207 stop generating lcov coverage when functional tests fail (asood123) +- #16252 Log to debug.log in all unit tests (MarcoFalke) +- #16289 Add missing ECC_Stop() in GUI rpcnestedtests.cpp (jonasschnelli) +- #16278 Remove unused includes (practicalswift) +- #16302 Add missing syncwithvalidationinterfacequeue to wallet_balance test (MarcoFalke) +- #15538 wallet_bumpfee.py: Make sure coin selection produces change (instagibbs) +- #16294 Create at most one testing setup (MarcoFalke) +- #16299 bench: Move generated data to a dedicated translation unit (promag) +- #16329 Add tests for getblockchaininfo.softforks (MarcoFalke) +- #15687 tool wallet test coverage for unexpected writes to wallet (jonatack) +- #16267 bench: Benchmark blocktojson (fanatid) +- #14505 Add linter to make sure single parameter constructors are marked explicit (practicalswift) +- #16338 Disable other targets when enable-fuzz is set (qmma70) +- #16334 rpc_users: Also test rpcauth.py with password (dongcarl) +- #15282 Replace hard-coded hex tx with class in test framework (stevenroose) +- #16390 Add --filter option to test_runner.py (promag) +- #15891 Require standard txs in regtest by default (MarcoFalke) +- #16374 Enable passing wildcard test names to test runner from root (jonatack) +- #16420 Fix race condition in wallet_encryption test (jonasschnelli) +- #16422 remove redundant setup in addrman_tests (zenosage) +- #16438 travis: Print memory and number of cpus (MarcoFalke) +- #16445 Skip flaky p2p_invalid_messages test on macOS (fjahr) +- #16459 Fix race condition in example_test.py (sdaftuar) +- #16464 Ensure we don't generate a too-big block in p2sh sigops test (sdaftuar) +- #16491 fix deprecated log.warn in feature_dbcrash test (jonatack) +- #15134 Switch one of the Travis jobs to an unsigned char environment (-funsigned-char) (practicalswift) +- #16505 Changes verbosity of msbuild from quiet to normal in the appveyor script (sipsorcery) +- #16293 Make test cases separate functions (MarcoFalke) +- #16470 Fail early on disconnect in mininode.wait_for_* (MarcoFalke) +- #16277 Suppress output in test_bitcoin for expected errors (gertjaap) +- #16493 Fix test failures (MarcoFalke) +- #16538 Add missing sync_blocks to feature_pruning (MarcoFalke) +- #16509 Adapt test framework for chains other than "regtest" (MarcoFalke) +- #16363 Add test for BIP30 duplicate tx (MarcoFalke) +- #16535 Explain why -whitelist is used in feature_fee_estimation (MarcoFalke) +- #16554 only include and use OpenSSL where it's actually needed (BIP70) (fanquake) +- #16598 Remove confusing hash256 function in util (elichai) +- #16595 travis: Use extended 90 minute timeout when available (MarcoFalke) +- #16563 Add unit test for AddTimeData (mzumsande) +- #16561 Use colors and dots in test_runner.py output only if standard output is a terminal (practicalswift) +- #16465 Test p2sh-witness and bech32 in wallet_import_rescan (MarcoFalke) +- #16582 Rework ci (Use travis only as fallback env) (MarcoFalke) +- #16633 travis: Fix test_runner.py timeouts (MarcoFalke) +- #16646 Run tests with UPnP disabled (fanquake) +- #16623 ci: Add environment files for all settings (MarcoFalke) +- #16656 fix rpc_setban.py race (jonasschnelli) +- #16570 Make descriptor tests deterministic (davereikher) +- #16404 Test ZMQ notification after chain reorg (promag) +- #16726 Avoid common Python default parameter gotcha when mutable dict/list:s are used as default parameter values (practicalswift) +- #16739 ci: Pass down $makejobs to test_runner.py, other improvements (MarcoFalke) +- #16767 Check for codespell in lint-spelling.sh (kristapsk) +- #16768 Make lint-includes.sh work from any directory (kristapsk) +- #15257 Scripts and tools: Bump flake8 to 3.7.8 (Empact) +- #16804 Remove unused try-block in assert_debug_log (MarcoFalke) +- #16850 `servicesnames` field in `getpeerinfo` and `getnetworkinfo` (darosior) +- #16551 Test that low difficulty chain fork is rejected (MarcoFalke) +- #16737 Establish only one connection between nodes in rpc_invalidateblock (MarcoFalke) +- #16845 Add notes on how to generate data/wallets/high_minversion (MarcoFalke) +- #16888 Bump timeouts in slow running tests (MarcoFalke) +- #16864 Add python bech32 impl round-trip test (instagibbs) +- #16865 add some unit tests for merkle.cpp (soroosh-sdi) +- #14696 Add explicit references to related CVE's in p2p_invalid_block test (lucash-dev) +- #16907 lint: Add DisabledOpcodeTemplates to whitelist (MarcoFalke) +- #16898 Remove connect_nodes_bi (MarcoFalke) +- #16917 Move common function assert_approx() into util.py (fridokus) +- #16921 Add information on how to add Vulture suppressions (practicalswift) +- #16920 Fix extra_args in wallet_import_rescan.py (MarcoFalke) +- #16918 Make PORT_MIN in test runner configurable (MarcoFalke) +- #16941 travis: Disable feature_block in tsan run due to oom (MarcoFalke) +- #16929 follow-up to rpc: default maxfeerate value as BTC/kB (jonatack) +- #16959 ci: Set $host before setting fallback values (MarcoFalke) +- #16961 Remove python dead code linter (laanwj) +- #16931 add unittests for CheckProofOfWork (soroosh-sdi) +- #16991 Fix service flag comparison check in rpc_net test (luke-jr) (laanwj) +- #16987 Correct docstring param name (jbampton) +- #17015 Explain QT_QPA_PLATFORM for gui tests (MarcoFalke) +- #17006 Enable UBSan for Travis fuzzing job (practicalswift) +- #17086 Fix fs_tests for unknown locales (carnhofdaki) +- #15903 appveyor: Write @PACKAGE_NAME@ to config (MarcoFalke) +- #16742 test: add executable flag for wallet_watchonly.py (theStack) +- #16740 qa: Relax so that the subscriber is ready before publishing zmq messages (#16740) + +### Miscellaneous +- #15335 Fix lack of warning of unrecognized section names (AkioNak) +- #15528 contrib: Bump gitian descriptors for 0.19 (MarcoFalke) +- #15609 scripts and tools: Set 'distro' explicitly (hebasto) +- #15519 Add Poly1305 implementation (jonasschnelli) +- #15643 contrib: Gh-merge: include acks in merge commit (MarcoFalke) +- #15838 scripts and tools: Fetch missing review comments in github-merge.py (nkostoulas) +- #15920 lint: Check that all wallet args are hidden (MarcoFalke) +- #15849 Thread names in logs and deadlock debug tools (jamesob) +- #15650 Handle the result of posix_fallocate system call (lucayepa) +- #15766 scripts and tools: Upgrade gitian image before signing (hebasto) +- #15512 Add ChaCha20 encryption option (XOR) (jonasschnelli) +- #15968 Fix portability issue with pthreads (grim-trigger) +- #15970 Utils and libraries: fix static_assert for macro HAVE_THREAD_LOCAL (orientye) +- #15863 scripts and tools: Ensure repos are up-to-date in gitian-build.py (hebasto) +- #15224 Add RNG strengthening (10ms once every minute) (sipa) +- #15840 Contrib scripts: Filter IPv6 by ASN (abitfan) +- #13998 Scripts and tools: gitian-build.py improvements and corrections (hebasto) +- #15236 scripts and tools: Make --setup command independent (hebasto) +- #16114 contrib: Add curl as a required program in gitian-build.py (fanquake) +- #16046 util: Add type safe gettime (MarcoFalke) +- #15703 Update secp256k1 subtree to latest upstream (sipa) +- #16086 contrib: Use newer config.guess & config.sub in install_db4.sh (fanquake) +- #16130 Don't GPG sign intermediate commits with github-merge tool (stevenroose) +- #16162 scripts: Add key for michael ford (fanquake) to trusted keys list (fanquake) +- #16201 devtools: Always use unabbreviated commit IDs in github-merge.py (laanwj) +- #16112 util: Log early messages (MarcoFalke) +- #16223 devtools: Fetch and display ACKs at sign-off time in github-merge (laanwj) +- #16300 util: Explain why the path is cached (MarcoFalke) +- #16314 scripts and tools: Update copyright_header.py script (hebasto) +- #16158 Fix logic of memory_cleanse() on MSVC and clean up docs (real-or-random) +- #14734 fix an undefined behavior in uint::SetHex (kazcw) +- #16327 scripts and tools: Update ShellCheck linter (hebasto) +- #15277 contrib: Enable building in guix containers (dongcarl) +- #16362 Add bilingual_str type (hebasto) +- #16481 logs: add missing space (harding) +- #16581 sipsorcery gitian key (sipsorcery) +- #16566 util: Refactor upper/lowercase functions (kallewoof) +- #16620 util: Move resolveerrmsg to util/error (MarcoFalke) +- #16625 scripts: Remove github-merge.py (fanquake) +- #15864 Fix datadir handling (hebasto) +- #16670 util: Add join helper to join a list of strings (MarcoFalke) +- #16665 scripts: Move update-translations.py to maintainer-tools repo (fanquake) +- #16730 Support serialization of `std::vector<bool>` (sipa) +- #16556 Fix systemd service file configuration directory setup (setpill) +- #15615 Add log output during initial header sync (jonasschnelli) +- #16774 Avoid unnecessary "Synchronizing blockheaders" log messages (jonasschnelli) +- #16489 log: harmonize bitcoind logging (jonatack) +- #16577 util: Cbufferedfile fixes and unit test (LarryRuane) +- #16984 util: Make thread names shorter (hebasto) +- #17038 Don't rename main thread at process level (laanwj) +- #17184 util: Filter out macos process serial number (hebasto) +- #17095 util: Filter control characters out of log messages (laanwj) +- #17085 init: Change fallback locale to C.UTF-8 (laanwj) +- #16957 9% less memory: make SaltedOutpointHasher noexcept (martinus) +- #17449 fix uninitialized variable nMinerConfirmationWindow (bitcoinVBR) + +### Documentation +- #15514 Update Transifex links (fanquake) +- #15513 add "sections" info to example bitcoin.conf (fanquake) +- #15530 Move wallet lock annotations to header (MarcoFalke) +- #15562 remove duplicate clone step in build-windows.md (fanquake) +- #15565 remove release note fragments (fanquake) +- #15444 Additional productivity tips (Sjors) +- #15577 Enable TLS in link to chris.beams.io (JeremyRand) +- #15604 release note for disabling reject messages by default (jnewbery) +- #15611 Add Gitian key for droark (droark) +- #15626 Update ACK description in CONTRIBUTING.md (jonatack) +- #15603 Add more tips to productivity.md (gwillen) +- #15683 Comment for seemingly duplicate LIBBITCOIN_SERVER (Bushstar) +- #15685 rpc-mining: Clarify error messages (MarcoFalke) +- #15760 Clarify sendrawtransaction::maxfeerate==0 help (MarcoFalke) +- #15659 fix findFork comment (r8921039) +- #15718 Improve netaddress comments (dongcarl) +- #15833 remove out-of-date comment on pay-to-witness support (r8921039) +- #15821 Remove upgrade note in release notes from EOL versions (MarcoFalke) +- #15267 explain AcceptToMemoryPoolWorker's coins_to_uncache (jamesob) +- #15887 Align code example style with clang-format (hebasto) +- #15877 Fix -dustrelayfee= argument docs grammar (keepkeyjon) +- #15908 Align MSVC build options with Linux build ones (hebasto) +- #15941 Add historical release notes for 0.18.0 (laanwj) +- #15794 Clarify PR guidelines w/re documentation (dongcarl) +- #15607 Release process updates (jonatack) +- #14364 Clarify -blocksdir usage (sangaman) +- #15777 Add doxygen comments for keypool classes (jnewbery) +- #15820 Add productivity notes for dummy rebases (dongcarl) +- #15922 Explain how to pass in non-fundamental types into functions (MarcoFalke) +- #16080 build/doc: update bitcoin_config.h packages, release process (jonatack) +- #16047 analyzepsbt description in doc/psbt.md (jonatack) +- #16039 add release note for 14954 (fanquake) +- #16139 Add riscv64 to outputs list in release-process.md (JeremyRand) +- #16140 create security policy (narula) +- #16164 update release process for SECURITY.md (jonatack) +- #16213 Remove explicit mention of versions from SECURITY.md (MarcoFalke) +- #16186 doc/lint: Fix spelling errors identified by codespell 1.15.0 (Empact) +- #16149 Rework section on ACK in CONTRIBUTING.md (MarcoFalke) +- #16196 Add release notes for 14897 & 15834 (MarcoFalke) +- #16241 add rapidcheck to vcpkg install list (fanquake) +- #16243 Remove travis badge from readme (MarcoFalke) +- #16256 remove orphaned header in developer notes (jonatack) +- #15964 Improve build-osx document formatting (giulio92) +- #16313 Fix broken link in doc/build-osx.md (jonatack) +- #16330 Use placeholder instead of key expiration date (hebasto) +- #16339 add reduce-memory.md (fanquake) +- #16347 Include static members in Doxygen (dongcarl) +- #15824 Improve netbase comments (dongcarl) +- #16430 Update bips 35, 37 and 111 status (MarcoFalke) +- #16455 Remove downgrading warning in release notes, per 0.18 branch (MarcoFalke) +- #16484 update labels in CONTRIBUTING.md (MarcoFalke) +- #16483 update Python command in msvc readme (sipsorcery) +- #16504 Add release note for the deprecated totalFee option of bumpfee (promag) +- #16448 add note on precedence of options in bitcoin.conf (fanquake) +- #16536 Update and extend benchmarking.md (ariard) +- #16530 Fix grammar and punctuation in developer notes (Tech1k) +- #16574 Add historical release notes for 0.18.1 (laanwj) +- #16585 Update Markdown syntax for bdb packages (emilengler) +- #16586 Mention other ways to conserve memory on compilation (MarcoFalke) +- #16605 Add missing contributor to 0.18.1 release notes (meshcollider) +- #16615 Fix typos in COPYRIGHT (gapeman) +- #16626 Fix spelling error chache -> cache (nilswloewen) +- #16587 Improve versionbits.h documentation (ariard) +- #16643 Add ZMQ dependencies to the Fedora build instructions (hebasto) +- #16634 Refer in rpcbind doc to the manpage (MarcoFalke) +- #16555 mention whitelist is inbound, and applies to blocksonly (Sjors) +- #16645 initial RapidCheck property-based testing documentation (jonatack) +- #16691 improve depends prefix documentation (fanquake) +- #16629 Add documentation for the new whitelist permissions (NicolasDorier) +- #16723 Update labels in CONTRIBUTING.md (hebasto) +- #16461 Tidy up shadowing section (promag) +- #16621 add default bitcoin.conf locations (GChuf) +- #16752 Delete stale URL in test README (michaelfolkson) +- #14862 Declare BLOCK_VALID_HEADER reserved (MarcoFalke) +- #16806 Add issue templates for bug and feature request (MarcoFalke) +- #16857 Elaborate need to re-login on Debian-based after usermod for Tor group (clashicly) +- #16863 Add a missing closing parenthesis in the bitcoin-wallet's help (darosior) +- #16757 CChainState return values (MarcoFalke) +- #16847 add comments clarifying how local services are advertised (jamesob) +- #16812 Fix whitespace errs in .md files, bitcoin.conf, and Info.plist.in (ch4ot1c) +- #16885 Update tx-size-small comment with relevant CVE disclosure (instagibbs) +- #16900 Fix doxygen comment for SignTransaction in rpc/rawtransaction_util (MarcoFalke) +- #16914 Update homebrew instruction for doxygen (Sjors) +- #16912 Remove Doxygen intro from src/bitcoind.cpp (ch4ot1c) +- #16960 replace outdated OpenSSL comment in test README (fanquake) +- #16968 Remove MSVC update step from translation process (laanwj) +- #16953 Improve test READMEs (fjahr) +- #16962 Put PR template in comments (laanwj) +- #16397 Clarify includeWatching for fundrawtransaction (stevenroose) +- #15459 add how to calculate blockchain and chainstate size variables to release process (marcoagner) +- #16997 Update bips.md for 0.19 (laanwj) +- #17001 Remove mention of renamed mapBlocksUnlinked (MarcoFalke) +- #17014 Consolidate release notes before 0.19.0 (move-only) (MarcoFalke) +- #17111 update bips.md with buried BIP9 deployments (MarcoFalke) + +Credits +======= + +Thanks to everyone who directly contributed to this release: + +- 251 +- Aaron Clauson +- Akio Nakamura +- Alistair Mann +- Amiti Uttarwar +- Andrew Chow +- andrewtoth +- Anthony Towns +- Antoine Riard +- Aseem Sood +- Ben Carman +- Ben Woosley +- bpay +- Carl Dong +- Carnhof Daki +- Chris Capobianco +- Chris Moore +- Chuf +- clashic +- clashicly +- Cory Fields +- Daki Carnhof +- Dan Gershony +- Daniel Edgecumbe +- Daniel Kraft +- Daniel McNally +- darosior +- David A. Harding +- David Reikher +- Douglas Roark +- Elichai Turkel +- Emil +- Emil Engler +- ezegom +- Fabian Jahr +- fanquake +- Felix Weis +- Ferdinando M. Ametrano +- fridokus +- gapeman +- GChuf +- Gert-Jaap Glasbergen +- Giulio Lombardo +- Glenn Willen +- Graham Krizek +- Gregory Sanders +- grim-trigger +- gwillen +- Hennadii Stepanov +- Jack Mallers +- James Hilliard +- James O'Beirne +- Jan Beich +- Jeremy Rubin +- JeremyRand +- Jim Posen +- John Bampton +- John Newbery +- Jon Atack +- Jon Layton +- Jonas Schnelli +- Jonathan "Duke" Leto +- João Barbosa +- Joonmo Yang +- Jordan Baczuk +- Jorge Timón +- Josu Goñi +- Julian Fleischer +- Karl-Johan Alm +- Kaz Wesley +- keepkeyjon +- Kirill Fomichev +- Kristaps Kaupe +- Kristian Kramer +- Larry Ruane +- Lenny Maiorani +- LongShao007 +- Luca Venturini +- lucash-dev +- Luke Dashjr +- marcoagner +- MarcoFalke +- marcuswin +- Martin Ankerl +- Martin Zumsande +- Matt Corallo +- MeshCollider +- Michael Folkson +- Miguel Herranz +- Nathan Marley +- Neha Narula +- nicolas.dorier +- Nils Loewen +- nkostoulas +- NullFunctor +- orient +- Patrick Strateman +- Peter Bushnell +- Peter Wagner +- Pieter Wuille +- practicalswift +- qmma +- r8921039 +- RJ Rybarczyk +- Russell Yanofsky +- Samuel Dobson +- Sebastian Falbesoner +- setpill +- shannon1916 +- Sjors Provoost +- soroosh-sdi +- Steven Roose +- Suhas Daftuar +- tecnovert +- THETCR +- Tim Ruffing +- Tobias Kaderle +- Torkel Rogstad +- Ulrich Kempken +- whythat +- William Casarin +- Wladimir J. van der Laan +- zenosage + +As well as everyone that helped translating on [Transifex](https://www.transifex.com/bitcoin/bitcoin/). diff --git a/doc/release-notes/release-notes-0.19.0.md b/doc/release-notes/release-notes-0.19.0.md index 153da68a6e..086491e92d 100644 --- a/doc/release-notes/release-notes-0.19.0.md +++ b/doc/release-notes/release-notes-0.19.0.md @@ -1,1086 +1,6 @@ -Bitcoin Core version 0.19.0 is now available from: - - <https://bitcoincore.org/bin/bitcoin-core-0.19.0/> - -This release includes new features, various bug fixes and performance -improvements, as well as updated translations. - -Please report bugs using the issue tracker at GitHub: - - <https://github.com/bitcoin/bitcoin/issues> - -To receive security and update notifications, please subscribe to: - - <https://bitcoincore.org/en/list/announcements/join/> - -How to Upgrade -============== - -If you are running an older version, shut it down. Wait until it has completely -shut down (which might take a few minutes for older versions), then run the -installer (on Windows) or just copy over `/Applications/Bitcoin-Qt` (on Mac) -or `bitcoind`/`bitcoin-qt` (on Linux). - -Upgrading directly from a version of Bitcoin Core that has reached its EOL is -possible, but might take some time if the datadir needs to be migrated. Old -wallet versions of Bitcoin Core are generally supported. - -Compatibility -============== - -Bitcoin Core is supported and extensively tested on operating systems using -the Linux kernel, macOS 10.10+, and Windows 7 and newer. It is not recommended -to use Bitcoin Core on unsupported systems. - -Bitcoin Core should also work on most other Unix-like systems but is not -as frequently tested on them. - -From 0.17.0 onwards, macOS <10.10 is no longer supported. 0.17.0 is -built using Qt 5.9.x, which doesn't support versions of macOS older than -10.10. Additionally, Bitcoin Core does not yet change appearance when -macOS "dark mode" is activated. - -Users running macOS Catalina may need to "right-click" and then choose "Open" -to open the Bitcoin Core .dmg. This is due to new signing requirements -imposed by Apple, which the Bitcoin Core project does not yet adhere too. - -Notable changes -=============== - -New user documentation ----------------------- - -- [Reduce memory](https://github.com/bitcoin/bitcoin/blob/master/doc/reduce-memory.md) - suggests configuration tweaks for running Bitcoin Core on systems with - limited memory. (#16339) - -New RPCs --------- - -- `getbalances` returns an object with all balances (`mine`, - `untrusted_pending` and `immature`). Please refer to the RPC help of - `getbalances` for details. The new RPC is intended to replace - `getbalance`, `getunconfirmedbalance`, and the balance fields in - `getwalletinfo`. These old calls and fields may be removed in a - future version. (#15930, #16239) - -- `setwalletflag` sets and unsets wallet flags that enable or disable - features specific to that existing wallet, such as the new - `avoid_reuse` feature documented elsewhere in these release notes. - (#13756) - -- `getblockfilter` gets the BIP158 filter for the specified block. This - RPC is only enabled if block filters have been created using the - `-blockfilterindex` configuration option. (#14121) - -New settings ------------- - -- `-blockfilterindex` enables the creation of BIP158 block filters for - the entire blockchain. Filters will be created in the background and - currently use about 4 GiB of space. Note: this version of Bitcoin - Core does not serve block filters over the P2P network, although the - local user may obtain block filters using the `getblockfilter` RPC. - (#14121) - -Updated settings ----------------- - -- `whitebind` and `whitelist` now accept a list of permissions to - provide peers connecting using the indicated interfaces or IP - addresses. If no permissions are specified with an address or CIDR - network, the implicit default permissions are the same as previous - releases. See the `bitcoind -help` output for these two options for - details about the available permissions. (#16248) - -- Users setting custom `dbcache` values can increase their setting slightly - without using any more real memory. Recent changes reduced the memory use - by about 9% and made chainstate accounting more accurate (it was underestimating - the use of memory before). For example, if you set a value of "450" before, you - may now set a value of "500" to use about the same real amount of memory. (#16957) - - -Updated RPCs ------------- - -Note: some low-level RPC changes mainly useful for testing are described in the -Low-level Changes section below. - -- `sendmany` no longer has a `minconf` argument. This argument was not - well-specified and would lead to RPC errors even when the wallet's - coin selection succeeded. Users who want to influence coin selection - can use the existing `-spendzeroconfchange`, `-limitancestorcount`, - `-limitdescendantcount` and `-walletrejectlongchains` configuration - arguments. (#15596) - -- `getbalance` and `sendtoaddress`, plus the new RPCs `getbalances` and - `createwallet`, now accept an "avoid_reuse" parameter that controls - whether already used addresses should be included in the operation. - Additionally, `sendtoaddress` will avoid partial spends when - `avoid_reuse` is enabled even if this feature is not already enabled - via the `-avoidpartialspends` command line flag because not doing so - would risk using up the "wrong" UTXO for an address reuse case. - (#13756) - -- RPCs which have an `include_watchonly` argument or `includeWatching` option now default to `true` for watch-only - wallets. Affected RPCs are: `getbalance`, `listreceivedbyaddress`, `listreceivedbylabel`, `listtransactions`, - `listsinceblock`, `gettransaction`, `walletcreatefundedpsbt`, and `fundrawtransaction`. (#16383) - -- `listunspent` now returns a "reused" bool for each output if the - wallet flag "avoid_reuse" is enabled. (#13756) - -- `getblockstats` now uses BlockUndo data instead of the transaction - index, making it much faster, no longer dependent on the `-txindex` - configuration option, and functional for all non-pruned blocks. - (#14802) - -- `utxoupdatepsbt` now accepts a `descriptors` parameter that will fill - out input and output scripts and keys when known. P2SH-witness inputs - will be filled in from the UTXO set when a descriptor is provided that - shows they're spending segwit outputs. See the RPC help text for full - details. (#15427) - -- `sendrawtransaction` and `testmempoolaccept` no longer accept a - `allowhighfees` parameter to fail mempool acceptance if the - transaction fee exceeds the value of the configuration option - `-maxtxfee`. Now there is a hardcoded default maximum feerate that - can be changed when calling either RPC using a `maxfeerate` parameter. - (#15620) - -- `getmempoolancestors`, `getmempooldescendants`, `getmempoolentry`, and - `getrawmempool` no longer return a `size` field unless the - configuration option `-deprecatedrpc=size` is used. Instead a new - `vsize` field is returned with the transaction's virtual size - (consistent with other RPCs such as `getrawtransaction`). (#15637) - -- `getwalletinfo` now includes a `scanning` field that is either `false` - (no scanning) or an object with information about the duration and - progress of the wallet's scanning historical blocks for transactions - affecting its balances. (#15730) - -- `gettransaction` now accepts a third (boolean) argument `verbose`. If - set to `true`, a new `decoded` field will be added to the response containing - the decoded transaction. This field is equivalent to RPC `decoderawtransaction`, - or RPC `getrawtransaction` when `verbose` is passed. (#16185, #16866, #16873) - -- `createwallet` accepts a new `passphrase` parameter. If set, this - will create the new wallet encrypted with the given passphrase. If - unset (the default) or set to an empty string, no encryption will be - used. (#16394) - -- `getchaintxstats` RPC now returns the additional key of - `window_final_block_height`. (#16695) - -- `getmempoolentry` now provides a `weight` field containing the - transaction weight as defined in BIP141. (#16647) - -- The `getnetworkinfo` and `getpeerinfo` commands now contain a new field with decoded network service flags. (#16786) - -- `getdescriptorinfo` now returns an additional `checksum` field - containing the checksum for the unmodified descriptor provided by the - user (that is, before the descriptor is normalized for the - `descriptor` field). (#15986) - -- `joinpsbts` now shuffles the order of the inputs and outputs of the resulting - joined PSBT. Previously, inputs and outputs were added in the order PSBTs were - provided. This made it easy to correlate inputs to outputs, representing a - privacy leak. (#16512) - -- `walletcreatefundedpsbt` now signals BIP125 Replace-by-Fee if the - `-walletrbf` configuration option is set to true. (#15911) - -GUI changes ------------ - -- The GUI wallet now provides bech32 addresses by default. The user may change the address type - during invoice generation using a GUI toggle, or the default address - type may be changed with the `-addresstype` configuration option. - (#15711, #16497) - -- In 0.18.0, a `./configure` flag was introduced to allow disabling BIP70 support in the GUI (support was enabled by default). In 0.19.0, this flag is now __disabled__ by default. If you want to compile Bitcoin Core with BIP70 support in the GUI, you can pass `--enable-bip70` to `./configure`. (#15584) - -Deprecated or removed configuration options -------------------------------------------- - -- `-mempoolreplacement` is removed, although default node behavior - remains the same. This option previously allowed the user to prevent - the node from accepting or relaying BIP125 transaction replacements. - This is different from the remaining configuration option - `-walletrbf`. (#16171) - -Deprecated or removed RPCs --------------------------- - -- `bumpfee` no longer accepts a `totalFee` option unless the - configuration parameter `deprecatedrpc=totalFee` is specified. This - parameter will be fully removed in a subsequent release. (#15996) - -- `bumpfee` has a new `fee_rate` option as a replacement for the deprecated `totalFee`. (#16727) - -- `generate` is now removed after being deprecated in Bitcoin Core 0.18. - Use the `generatetoaddress` RPC instead. (#15492) - -P2P changes +0.19.0 note ----------- -- BIP 61 reject messages were deprecated in v0.18. They are now disabled - by default, but can be enabled by setting the `-enablebip61` command - line option. BIP 61 reject messages will be removed entirely in a - future version of Bitcoin Core. (#14054) - -- To eliminate well-known denial-of-service vectors in Bitcoin Core, - especially for nodes with spinning disks, the default value for the - `-peerbloomfilters` configuration option has been changed to false. - This prevents Bitcoin Core from sending the BIP111 NODE_BLOOM service - flag, accepting BIP37 bloom filters, or serving merkle blocks or - transactions matching a bloom filter. Users who still want to provide - bloom filter support may either set the configuration option to true - to re-enable both BIP111 and BIP37 support or enable just BIP37 - support for specific peers using the updated `-whitelist` and - `-whitebind` configuration options described elsewhere in these - release notes. For the near future, lightweight clients using public - BIP111/BIP37 nodes should still be able to connect to older versions - of Bitcoin Core and nodes that have manually enabled BIP37 support, - but developers of such software should consider migrating to either - using specific BIP37 nodes or an alternative transaction filtering - system. (#16152) - -- By default, Bitcoin Core will now make two additional outbound connections that are exclusively used for block-relay. No transactions or addr messages will be processed on these connections. These connections are designed to add little additional memory or bandwidth resource requirements but should make some partitioning attacks more difficult to carry out. (#15759) - -Miscellaneous CLI Changes -------------------------- - -- The `testnet` field in `bitcoin-cli -getinfo` has been renamed to - `chain` and now returns the current network name as defined in BIP70 - (main, test, regtest). (#15566) - -Low-level changes -================= - -RPC ---- - -- `getblockchaininfo` no longer returns a `bip9_softforks` object. - Instead, information has been moved into the `softforks` object and - an additional `type` field describes how Bitcoin Core determines - whether that soft fork is active (e.g. BIP9 or BIP90). See the RPC - help for details. (#16060) - -- `getblocktemplate` no longer returns a `rules` array containing `CSV` - and `segwit` (the BIP9 deployments that are currently in active - state). (#16060) - -- `getrpcinfo` now returns a `logpath` field with the path to - `debug.log`. (#15483) - -Tests ------ - -- The regression test chain enabled by the `-regtest` command line flag - now requires transactions to not violate standard policy by default. - This is the same default used for mainnet and makes it easier to test - mainnet behavior on regtest. Note that the testnet still allows - non-standard txs by default and that the policy can be locally - adjusted with the `-acceptnonstdtxn` command line flag for both test - chains. (#15891) - -Configuration ------------- - -- A setting specified in the default section but not also specified in a - network-specific section (e.g. testnet) will now produce an error - preventing startup instead of just a warning unless the network is - mainnet. This prevents settings intended for mainnet from being - applied to testnet or regtest. (#15629) - -- On platforms supporting `thread_local`, log lines can be prefixed with - the name of the thread that caused the log. To enable this behavior, - use `-logthreadnames=1`. (#15849) - -Network -------- - -- When fetching a transaction announced by multiple peers, previous versions of - Bitcoin Core would sequentially attempt to download the transaction from each - announcing peer until the transaction is received, in the order that those - peers' announcements were received. In this release, the download logic has - changed to randomize the fetch order across peers and to prefer sending - download requests to outbound peers over inbound peers. This fixes an issue - where inbound peers could prevent a node from getting a transaction. - (#14897, #15834) - -- If a Tor hidden service is being used, Bitcoin Core will be bound to - the standard port 8333 even if a different port is configured for - clearnet connections. This prevents leaking node identity through use - of identical non-default port numbers. (#15651) - -Mempool and transaction relay ------------------------------ - -- Allows one extra single-ancestor transaction per package. Previously, - if a transaction in the mempool had 25 descendants, or it and all of - its descendants were over 101,000 vbytes, any newly-received - transaction that was also a descendant would be ignored. Now, one - extra descendant will be allowed provided it is an immediate - descendant (child) and the child's size is 10,000 vbytes or less. - This makes it possible for two-party contract protocols such as - Lightning Network to give each participant an output they can spend - immediately for Child-Pays-For-Parent (CPFP) fee bumping without - allowing one malicious participant to fill the entire package and thus - prevent the other participant from spending their output. (#15681) - -- Transactions with outputs paying v1 to v16 witness versions (future - segwit versions) are now accepted into the mempool, relayed, and - mined. Attempting to spend those outputs remains forbidden by policy - ("non-standard"). When this change has been widely deployed, wallets - and services can accept any valid bech32 Bitcoin address without - concern that transactions paying future segwit versions will become - stuck in an unconfirmed state. (#15846) - -- Legacy transactions (transactions with no segwit inputs) must now be - sent using the legacy encoding format, enforcing the rule specified in - BIP144. (#14039) - -Wallet ------- - -- When in pruned mode, a rescan that was triggered by an `importwallet`, - `importpubkey`, `importaddress`, or `importprivkey` RPC will only fail - when blocks have been pruned. Previously it would fail when `-prune` - has been set. This change allows setting `-prune` to a high value - (e.g. the disk size) without the calls to any of the import RPCs - failing until the first block is pruned. (#15870) - -- When creating a transaction with a fee above `-maxtxfee` (default 0.1 - BTC), the RPC commands `walletcreatefundedpsbt` and - `fundrawtransaction` will now fail instead of rounding down the fee. - Be aware that the `feeRate` argument is specified in BTC per 1,000 - vbytes, not satoshi per vbyte. (#16257) - -- A new wallet flag `avoid_reuse` has been added (default off). When - enabled, a wallet will distinguish between used and unused addresses, - and default to not use the former in coin selection. When setting - this flag on an existing wallet, rescanning the blockchain is required - to correctly mark previously used destinations. Together with "avoid - partial spends" (added in Bitcoin Core v0.17.0), this can eliminate a - serious privacy issue where a malicious user can track spends by - sending small payments to a previously-paid address that would then - be included with unrelated inputs in future payments. (#13756) - -Build system changes --------------------- - -- Python >=3.5 is now required by all aspects of the project. This - includes the build systems, test framework and linters. The previously - supported minimum (3.4), was EOL in March 2019. (#14954) - -- The minimum supported miniUPnPc API version is set to 10. This keeps - compatibility with Ubuntu 16.04 LTS and Debian 8 `libminiupnpc-dev` - packages. Please note, on Debian this package is still vulnerable to - [CVE-2017-8798](https://security-tracker.debian.org/tracker/CVE-2017-8798) - (in jessie only) and - [CVE-2017-1000494](https://security-tracker.debian.org/tracker/CVE-2017-1000494) - (both in jessie and in stretch). (#15993) - -0.19.0 change log -================= - -### Consensus -- #16128 Delete error-prone CScript constructor only used with FindAndDelete (instagibbs) -- #16060 Bury bip9 deployments (jnewbery) - -### Policy -- #15557 Enhance `bumpfee` to include inputs when targeting a feerate (instagibbs) -- #15846 Make sending to future native witness outputs standard (sipa) - -### Block and transaction handling -- #15632 Remove ResendWalletTransactions from the Validation Interface (jnewbery) -- #14121 Index for BIP 157 block filters (jimpo) -- #15141 Rewrite DoS interface between validation and net_processing (sdaftuar) -- #15880 utils and libraries: Replace deprecated Boost Filesystem functions (hebasto) -- #15971 validation: Add compile-time checking for negative locking requirement in LimitValidationInterfaceQueue (practicalswift) -- #15999 init: Remove dead code in LoadChainTip (MarcoFalke) -- #16015 validation: Hold cs_main when reading chainActive in RewindBlockIndex (practicalswift) -- #16056 remove unused magic number from consistency check (instagibbs) -- #16171 Remove -mempoolreplacement to prevent needless block prop slowness (TheBlueMatt) -- #15894 Remove duplicated "Error: " prefix in logs (hebasto) -- #14193 validation: Add missing mempool locks (MarcoFalke) -- #15681 Allow one extra single-ancestor transaction per package (TheBlueMatt) -- #15305 [validation] Crash if disconnecting a block fails (sdaftuar) -- #16471 log correct messages when CPFP fails (jnewbery) -- #16433 txmempool: Remove unused default value MemPoolRemovalReason::UNKNOWN (MarcoFalke) -- #13868 Remove unused fScriptChecks parameter from CheckInputs (Empact) -- #16421 Conservatively accept RBF bumps bumping one tx at the package limits (TheBlueMatt) -- #16854 Prevent UpdateTip log message from being broken up (stevenroose) -- #16956 validation: Make GetWitnessCommitmentIndex public (MarcoFalke) -- #16713 Ignore old versionbit activations to avoid 'unknown softforks' warning (jnewbery) -- #17002 chainparams: Bump assumed chain params (MarcoFalke) -- #16849 Fix block index inconsistency in InvalidateBlock() (sdaftuar) - -### P2P protocol and network code -- #15597 Generate log entry when blocks messages are received unexpectedly (pstratem) -- #15654 Remove unused unsanitized user agent string CNode::strSubVer (MarcoFalke) -- #15689 netaddress: Update CNetAddr for ORCHIDv2 (dongcarl) -- #15834 Fix transaction relay bugs introduced in #14897 and expire transactions from peer in-flight map (sdaftuar) -- #15651 torcontrol: Use the default/standard network port for Tor hidden services, even if the internal port is set differently (luke-jr) -- #16188 Document what happens to getdata of unknown type (MarcoFalke) -- #15649 Add ChaCha20Poly1305@Bitcoin AEAD (jonasschnelli) -- #16152 Disable bloom filtering by default (TheBlueMatt) -- #15993 Drop support of the insecure miniUPnPc versions (hebasto) -- #16197 Use mockable time for tx download (MarcoFalke) -- #16248 Make whitebind/whitelist permissions more flexible (NicolasDorier) -- #16618 [Fix] Allow connection of a noban banned peer (NicolasDorier) -- #16631 Restore default whitelistrelay to true (NicolasDorier) -- #15759 Add 2 outbound block-relay-only connections (sdaftuar) -- #15558 Don't query all DNS seeds at once (sipa) -- #16999 0.19 seeds update (laanwj) - -### Wallet -- #15288 Remove wallet -> node global function calls (ryanofsky) -- #15491 Improve log output for errors during load (gwillen) -- #13541 wallet/rpc: sendrawtransaction maxfeerate (kallewoof) -- #15680 Remove resendwallettransactions RPC method (jnewbery) -- #15508 Refactor analyzepsbt for use outside RPC code (gwillen) -- #15747 Remove plethora of Get*Balance (MarcoFalke) -- #15728 Refactor relay transactions (jnewbery) -- #15639 bitcoin-wallet tool: Drop libbitcoin_server.a dependency (ryanofsky) -- #15853 Remove unused import checkpoints.h (MarcoFalke) -- #15780 add cachable amounts for caching credit/debit values (kallewoof) -- #15778 Move maxtxfee from node to wallet (jnewbery) -- #15901 log on rescan completion (andrewtoth) -- #15917 Avoid logging no_such_file_or_directory error (promag) -- #15452 Replace CScriptID and CKeyID in CTxDestination with dedicated types (instagibbs) -- #15870 Only fail rescan when blocks have actually been pruned (MarcoFalke) -- #15006 Add option to create an encrypted wallet (achow101) -- #16001 Give WalletModel::UnlockContext move semantics (sipa) -- #15741 Batch write imported stuff in importmulti (achow101) -- #16144 do not encrypt wallets with disabled private keys (mrwhythat) -- #15024 Allow specific private keys to be derived from descriptor (meshcollider) -- #13756 "avoid_reuse" wallet flag for improved privacy (kallewoof) -- #16226 Move ismine to the wallet module (achow101) -- #16239 wallet/rpc: follow-up clean-up/fixes to avoid_reuse (kallewoof) -- #16286 refactoring: wallet: Fix GCC 7.4.0 warning (hebasto) -- #16257 abort when attempting to fund a transaction above -maxtxfee (Sjors) -- #16237 Have the wallet give out destinations instead of keys (achow101) -- #16322 Fix -maxtxfee check by moving it to CWallet::CreateTransaction (promag) -- #16361 Remove redundant pre-TopUpKeypool check (instagibbs) -- #16244 Move wallet creation out of the createwallet rpc into its own function (achow101) -- #16227 Refactor CWallet's inheritance chain (achow101) -- #16208 Consume ReserveDestination on successful CreateTransaction (instagibbs) -- #16301 Use CWallet::Import* functions in all import* RPCs (achow101) -- #16402 Remove wallet settings from chainparams (MarcoFalke) -- #16415 Get rid of PendingWalletTx class (ryanofsky) -- #15588 Log the actual wallet file version and no longer publicly expose the "version" record (achow101) -- #16399 Improve wallet creation (fjahr) -- #16475 Enumerate walletdb keys (MarcoFalke) -- #15709 Do not add "setting" key as unknown (Bushstar) -- #16451 Remove CMerkleTx (jnewbery) -- #15906 Move min_depth and max_depth to coin control (amitiuttarwar) -- #16502 Drop unused OldKey (promag) -- #16394 Allow createwallet to take empty passwords to make unencrypted wallets (achow101) -- #15911 Use wallet RBF default for walletcreatefundedpsbt (Sjors) -- #16503 Remove p2pEnabled from Chain interface (ariard) -- #16557 restore coinbase and confirmed/conflicted checks in SubmitMemoryPoolAndRelay() (jnewbery) -- #14934 Descriptor expansion cache clarifications (Sjors) -- #16383 rpcwallet: default include_watchonly to true for watchonly wallets (jb55) -- #16542 Return more specific errors about invalid descriptors (achow101) -- #16572 Fix Char as Bool in Wallet (JeremyRubin) -- #16753 extract PubKey from P2PK script with Solver (theStack) -- #16716 Use wallet name instead of pointer on unload/release (promag) -- #16185 gettransaction: add an argument to decode the transaction (darosior) -- #16745 Translate all initErrors in CreateWalletFromFile (MarcoFalke) -- #16792 Assert that the HRP is lowercase in Bech32::Encode (meshcollider) -- #16624 encapsulate transactions state (ariard) -- #16830 Cleanup walletinitinterface.h (hebasto) -- #16796 Fix segfault in CreateWalletFromFile (MarcoFalke) -- #16866 Rename 'decode' argument in gettransaction method to 'verbose' (jnewbery) -- #16727 Explicit feerate for bumpfee (instagibbs) -- #16609 descriptor: fix missed m_script_arg arg renaming in #14934 (fanquake) - -### RPC and other APIs -- #15492 remove deprecated generate method (Sjors) -- #15566 cli: Replace testnet with chain and return network name as per bip70 (fanquake) -- #15564 cli: Remove duplicate wallet fields from -getinfo (fanquake) -- #15642 Remove deprecated rpc warnings (jnewbery) -- #15637 Rename size to vsize in mempool related calls (fanquake) -- #15620 Uncouple non-wallet rpcs from maxTxFee global (MarcoFalke) -- #15616 Clarify decodescript RPCResult doc (MarcoFalke) -- #15669 Fix help text for signtransactionwithXXX (torkelrogstad) -- #15596 Ignore sendmany::minconf as dummy value (MarcoFalke) -- #15755 remove unused var in rawtransaction.cpp (Bushstar) -- #15746 RPCHelpMan: Always name dictionary keys (MarcoFalke) -- #15748 remove dead mining code (jnewbery) -- #15751 Speed up deriveaddresses for large ranges (sipa) -- #15770 Validate maxfeerate with AmountFromValue (promag) -- #15474 rest/rpc: Make mempoolinfo atomic (promag) -- #15463 Speedup getaddressesbylabel (promag) -- #15784 Remove dependency on interfaces::Chain in SignTransaction (ariard) -- #15323 Expose g_is_mempool_loaded via getmempoolinfo (Empact) -- #15932 Serialize in getblock without cs_main (MarcoFalke) -- #15930 Add balances RPC (MarcoFalke) -- #15730 Show scanning details in getwalletinfo (promag) -- #14802 faster getblockstats using BlockUndo data (FelixWeis) -- #14984 Speedup getrawmempool when verbose=true (promag) -- #16071 Hint for importmulti in help output of importpubkey and importaddress (kristapsk) -- #16063 Mention getwalletinfo where a rescan is triggered (promag) -- #16024 deriveaddresses: Correction of descriptor checksum in RPC example (ccapo) -- #16217 getrawtransaction: inform about blockhash argument when lookup fails (darosior) -- #15427 Add support for descriptors to utxoupdatepsbt (sipa) -- #16262 Allow shutdown while in generateblocks (pstratem) -- #15483 Adding a 'logpath' entry to getrpcinfo (darosior) -- #16325 Clarify that block count means height excl genesis (MarcoFalke) -- #16326 add new utxoupdatepsbt arguments to the CRPCCommand and CPRCCvertParam tables (jnewbery) -- #16332 Add logpath description for getrpcinfo (instagibbs) -- #16240 JSONRPCRequest-aware RPCHelpMan (kallewoof) -- #15996 Deprecate totalfee argument in `bumpfee` (instagibbs) -- #16467 sendrawtransaction help privacy note (jonatack) -- #16596 Fix getblocktemplate CLI example (emilengler) -- #15986 Add checksum to getdescriptorinfo (sipa) -- #16647 add weight to getmempoolentry output (fanquake) -- #16695 Add window final block height to getchaintxstats (leto) -- #16798 Refactor rawtransaction_util's SignTransaction to separate prevtx parsing (achow101) -- #16285 Improve scantxoutset response and help message (promag) -- #16725 Don't show addresses or P2PK in decoderawtransaction (NicolasDorier) -- #16787 Human readable network services (darosior) -- #16251 Improve signrawtransaction error reporting (ajtowns) -- #16873 fix regression in gettransaction (jonatack) -- #16512 Shuffle inputs and outputs after joining psbts (achow101) -- #16521 Use the default maxfeerate value as BTC/kB (Remagpie) -- #16817 Fix casing in getblockchaininfo to be inline with other fields (dangershony) -- #17131 fix -rpcclienttimeout 0 option (fjahr) -- #17249 Add missing deque include to fix build (jbeich) - -### GUI -- #15464 Drop unused return values in WalletFrame (promag) -- #15614 Defer removeAndDeleteWallet when no modal widget is active (promag) -- #15711 Generate bech32 addresses by default (MarcoFalke) -- #15829 update request payment button text and tab description (fanquake) -- #15874 Resolve the qt/guiutil <-> qt/optionsmodel CD (251Labs) -- #15371 Uppercase bech32 addresses in qr codes (benthecarman) -- #15928 Move QRImageWidget to its own file-pair (luke-jr) -- #16113 move coin control "OK" to the right hand side of the dialog (fanquake) -- #16090 Add vertical spacer to peer detail widget (JosuGZ) -- #15886 qt, wallet: Revamp SendConfirmationDialog (hebasto) -- #16263 Use qInfo() if no error occurs (hebasto) -- #16153 Add antialiasing to traffic graph widget (JosuGZ) -- #16350 Remove unused guard (hebasto) -- #16106 Sort wallets in open wallet menu (promag) -- #16291 Stop translating PACKAGE_NAME (MarcoFalke) -- #16380 Remove unused bits from the service flags enum (MarcoFalke) -- #16379 Fix autostart filenames on Linux for testnet/regtest (hebasto) -- #16366 init: Use InitError for all errors in bitcoind/qt (MarcoFalke) -- #16436 Do not create payment server if -disablewallet option provided (hebasto) -- #16514 Remove unused RPCConsole::tabFocus (promag) -- #16497 Generate bech32 addresses by default (take 2, fixup) (MarcoFalke) -- #16349 Remove redundant WalletController::addWallet slot (hebasto) -- #16578 Do not pass in command line arguments to QApplication (achow101) -- #16612 Remove menu icons (laanwj) -- #16677 remove unused PlatformStyle::TextColorIcon (fanquake) -- #16694 Ensure transaction send error is always visible (fanquake) -- #14879 Add warning messages to the debug window (hebasto) -- #16708 Replace obsolete functions of QSslSocket (hebasto) -- #16701 Replace functions deprecated in Qt 5.13 (hebasto) -- #16706 Replace deprecated QSignalMapper by lambda expressions (hebasto) -- #16707 Remove obsolete QModelIndex::child() (hebasto) -- #16758 Replace QFontMetrics::width() with TextWidth() (hebasto) -- #16760 Change uninstall icon on Windows (GChuf) -- #16720 Replace objc_msgSend() function calls with the native Objective-C syntax (hebasto) -- #16788 Update transifex slug for 0.19 (laanwj) -- #15450 Create wallet menu option (achow101) -- #16735 Remove unused menu items for Windows and Linux (GChuf) -- #16826 Do additional character escaping for wallet names and address labels (achow101) -- #15529 Add Qt programs to msvc build (updated, no code changes) (sipsorcery) -- #16714 add prune to intro screen with smart default (Sjors) -- #16858 advise users not to switch wallets when opening a BIP70 URI (jameshilliard) -- #16822 Create wallet menu option follow-ups (jonatack) -- #16882 Re-generate translations before 0.19.0 (MarcoFalke) -- #16928 Rename address checkbox back to bech32 (MarcoFalke) -- #16837 Fix {C{,XX},LD}FLAGS pickup (dongcarl) -- #16971 Change default size of intro frame (emilengler) -- #16988 Periodic translations update (laanwj) -- #16852 When BIP70 is disabled, get PaymentRequest merchant using string search (achow101) -- #16952 make sure to update the UI when deleting a transaction (jonasschnelli) -- #17031 Prevent processing duplicate payment requests (promag) -- #17135 Make polling in ClientModel asynchronous (promag) -- #17120 Fix start timer from non QThread (promag) -- #17257 disable font antialiasing for QR image address (fanquake) - -### Build system -- #14954 Require python 3.5 (MarcoFalke) -- #15580 native_protobuf: avoid system zlib (dongcarl) -- #15601 Switch to python3 (take 3) (MarcoFalke) -- #15581 Make less assumptions about build env (dongcarl) -- #14853 latest RapidCheck (fanquake) -- #15446 Improve depends debuggability (dongcarl) -- #13788 Fix --disable-asm for newer assembly checks/code (luke-jr) -- #12051 add missing debian contrib file to tarball (puchu) -- #15919 Remove unused OpenSSL includes to make it more clear where OpenSSL is used (practicalswift) -- #15978 .gitignore: Don't ignore depends patches (dongcarl) -- #15939 gitian: Remove windows 32 bit build (MarcoFalke) -- #15239 scripts and tools: Move non-linux build source tarballs to "bitcoin-binaries/version" directory (hebasto) -- #14047 Add HKDF_HMAC256_L32 and method to negate a private key (jonasschnelli) -- #16051 add patch to common dependencies (fanquake) -- #16049 switch to secure download of all dependencies (Kemu) -- #16059 configure: Fix thread_local detection (dongcarl) -- #16089 add ability to skip building zeromq (fanquake) -- #15844 Purge libtool archives (dongcarl) -- #15461 update to Boost 1.70 (Sjors) -- #16141 remove GZIP export from gitian descriptors (fanquake) -- #16235 Cleaned up and consolidated msbuild files (no code changes) (sipsorcery) -- #16246 MSVC: Fix error in debug mode (Fix #16245) (NicolasDorier) -- #16183 xtrans: Configure flags cleanup (dongcarl) -- #16258 [MSVC]: Create the config.ini as part of bitcoind build (NicolasDorier) -- #16271 remove -Wall from rapidcheck build flags (fanquake) -- #16309 [MSVC] allow user level project customization (NicolasDorier) -- #16308 [MSVC] Copy build output to src/ automatically after build (NicolasDorier) -- #15457 Check std::system for -[alert|block|wallet]notify (Sjors) -- #16344 use #if HAVE_SYSTEM instead of defined(HAVE_SYSTEM) (Sjors) -- #16352 prune dbus from depends (fanquake) -- #16270 expat 2.2.7 (fanquake) -- #16408 Prune X packages (dongcarl) -- #16386 disable unused Qt features (fanquake) -- #16424 Treat -Wswitch as error when --enable-werror (MarcoFalke) -- #16441 remove qt libjpeg check from bitcoin_qt.m4 (fanquake) -- #16434 Specify AM_CPPFLAGS for ZMQ (domob1812) -- #16534 add Qt Creator Makefile.am.user to .gitignore (Bushstar) -- #16573 disable building libsecp256k1 benchmarks (fanquake) -- #16533 disable libxcb extensions (fanquake) -- #16589 Remove unused src/obj-test folder (MarcoFalke) -- #16435 autoconf: Sane `--enable-debug` defaults (dongcarl) -- #16622 echo property tests status during build (jonatack) -- #16611 Remove src/obj directory from repository (laanwj) -- #16371 ignore macOS make deploy artefacts & add them to clean-local (fanquake) -- #16654 build: update RapidCheck Makefile (jonatack) -- #16370 cleanup package configure flags (fanquake) -- #16746 msbuild: Ignore linker warning (sipsorcery) -- #16750 msbuild: adds bench_bitcoin to auto generated project files (sipsorcery) -- #16810 guix: Remove ssp spec file hack (dongcarl) -- #16477 skip deploying plugins we dont use in macdeployqtplus (fanquake) -- #16413 Bump QT to LTS release 5.9.8 (THETCR) -- #15584 disable BIP70 support by default (fanquake) -- #16871 make building protobuf optional in depends (fanquake) -- #16879 remove redundant sed patching (fanquake) -- #16809 zlib: Move toolchain options to configure (dongcarl) -- #15146 Solve SmartOS FD_ZERO build issue (Empact) -- #16870 update boost macros to latest upstream for improved error reporting (fanquake) -- #16982 Factor out qt translations from build system (laanwj) -- #16926 Add OpenSSL termios fix for musl libc (nmarley) -- #16927 Refresh ZeroMQ 4.3.1 patch (nmarley) -- #17005 Qt version appears only if GUI is being built (ch4ot1c) -- #16468 Exclude depends/Makefile in .gitignore (promag) - -### Tests and QA -- #15296 Add script checking for deterministic line coverage in unit tests (practicalswift) -- #15338 ci: Build and run tests once on freebsd (MarcoFalke) -- #15479 Add .style.yapf (MarcoFalke) -- #15534 lint-format-strings: open files sequentially (fix for OS X) (gwillen) -- #15504 fuzz: Link BasicTestingSetup (shared with unit tests) (MarcoFalke) -- #15473 bench: Benchmark mempooltojson (MarcoFalke) -- #15466 Print remaining jobs in test_runner.py (stevenroose) -- #15631 mininode: Clearer error message on invalid magic bytes (MarcoFalke) -- #15255 Remove travis_wait from lint script (gkrizek) -- #15686 make pruning test faster (jnewbery) -- #15533 .style.yapf: Set column_limit=160 (MarcoFalke) -- #15660 Overhaul p2p_compactblocks.py (sdaftuar) -- #15495 Add regtests for HTTP status codes (domob1812) -- #15772 Properly log named args in authproxy (MarcoFalke) -- #15771 Prevent concurrency issues reading .cookie file (promag) -- #15693 travis: Switch to ubuntu keyserver to avoid timeouts (MarcoFalke) -- #15629 init: Throw error when network specific config is ignored (MarcoFalke) -- #15773 Add BitcoinTestFramework::sync_* methods (MarcoFalke) -- #15797 travis: Bump second timeout to 33 minutes, add rationale (MarcoFalke) -- #15788 Unify testing setups for fuzz, bench, and unit tests (MarcoFalke) -- #15352 Reduce noise level in test_bitcoin output (practicalswift) -- #15779 Add wallet_balance benchmark (MarcoFalke) -- #15843 fix outdated include in blockfilter_index_tests (jamesob) -- #15866 Add missing syncwithvalidationinterfacequeue to wallet_import_rescan (MarcoFalke) -- #15697 Make swap_magic_bytes in p2p_invalid_messages atomic (MarcoFalke) -- #15895 Avoid re-reading config.ini unnecessarily (luke-jr) -- #15896 feature_filelock, interface_bitcoin_cli: Use PACKAGE_NAME in messages rather than hardcoding Bitcoin Core (luke-jr) -- #15897 QA/mininode: Send all headers upfront in send_blocks_and_test to avoid sending an unconnected one (luke-jr) -- #15696 test_runner: Move feature_pruning to base tests (MarcoFalke) -- #15869 Add settings merge test to prevent regresssions (ryanofsky) -- #15758 Add further tests to wallet_balance (MarcoFalke) -- #15841 combine_logs: append node stderr and stdout if it exists (MarcoFalke) -- #15949 test_runner: Move pruning back to extended (MarcoFalke) -- #15927 log thread names by default in functional tests (jnewbery) -- #15664 change default Python block serialization to witness (instagibbs) -- #15988 Add test for ArgsManager::GetChainName (ryanofsky) -- #15963 Make random seed logged and settable (jnewbery) -- #15943 Fail if RPC has been added without tests (MarcoFalke) -- #16036 travis: Run all lint scripts even if one fails (scravy) -- #13555 parameterize adjustment period in versionbits_computeblockversion (JBaczuk) -- #16079 wallet_balance.py: Prevent edge cases (stevenroose) -- #16078 replace tx hash with txid in rawtransaction test (LongShao007) -- #16042 Bump MAX_NODES to 12 (MarcoFalke) -- #16124 Limit Python linting to files in the repo (practicalswift) -- #16143 Mark unit test blockfilter_index_initial_sync as non-deterministic (practicalswift) -- #16214 travis: Fix caching issues (MarcoFalke) -- #15982 Make msg_block a witness block (MarcoFalke) -- #16225 Make coins_tests/updatecoins_simulation_test deterministic (practicalswift) -- #16236 fuzz: Log output even if fuzzer failed (MarcoFalke) -- #15520 cirrus: Run extended test feature_pruning (MarcoFalke) -- #16234 Add test for unknown args (MarcoFalke) -- #16207 stop generating lcov coverage when functional tests fail (asood123) -- #16252 Log to debug.log in all unit tests (MarcoFalke) -- #16289 Add missing ECC_Stop() in GUI rpcnestedtests.cpp (jonasschnelli) -- #16278 Remove unused includes (practicalswift) -- #16302 Add missing syncwithvalidationinterfacequeue to wallet_balance test (MarcoFalke) -- #15538 wallet_bumpfee.py: Make sure coin selection produces change (instagibbs) -- #16294 Create at most one testing setup (MarcoFalke) -- #16299 bench: Move generated data to a dedicated translation unit (promag) -- #16329 Add tests for getblockchaininfo.softforks (MarcoFalke) -- #15687 tool wallet test coverage for unexpected writes to wallet (jonatack) -- #16267 bench: Benchmark blocktojson (fanatid) -- #14505 Add linter to make sure single parameter constructors are marked explicit (practicalswift) -- #16338 Disable other targets when enable-fuzz is set (qmma70) -- #16334 rpc_users: Also test rpcauth.py with password (dongcarl) -- #15282 Replace hard-coded hex tx with class in test framework (stevenroose) -- #16390 Add --filter option to test_runner.py (promag) -- #15891 Require standard txs in regtest by default (MarcoFalke) -- #16374 Enable passing wildcard test names to test runner from root (jonatack) -- #16420 Fix race condition in wallet_encryption test (jonasschnelli) -- #16422 remove redundant setup in addrman_tests (zenosage) -- #16438 travis: Print memory and number of cpus (MarcoFalke) -- #16445 Skip flaky p2p_invalid_messages test on macOS (fjahr) -- #16459 Fix race condition in example_test.py (sdaftuar) -- #16464 Ensure we don't generate a too-big block in p2sh sigops test (sdaftuar) -- #16491 fix deprecated log.warn in feature_dbcrash test (jonatack) -- #15134 Switch one of the Travis jobs to an unsigned char environment (-funsigned-char) (practicalswift) -- #16505 Changes verbosity of msbuild from quiet to normal in the appveyor script (sipsorcery) -- #16293 Make test cases separate functions (MarcoFalke) -- #16470 Fail early on disconnect in mininode.wait_for_* (MarcoFalke) -- #16277 Suppress output in test_bitcoin for expected errors (gertjaap) -- #16493 Fix test failures (MarcoFalke) -- #16538 Add missing sync_blocks to feature_pruning (MarcoFalke) -- #16509 Adapt test framework for chains other than "regtest" (MarcoFalke) -- #16363 Add test for BIP30 duplicate tx (MarcoFalke) -- #16535 Explain why -whitelist is used in feature_fee_estimation (MarcoFalke) -- #16554 only include and use OpenSSL where it's actually needed (BIP70) (fanquake) -- #16598 Remove confusing hash256 function in util (elichai) -- #16595 travis: Use extended 90 minute timeout when available (MarcoFalke) -- #16563 Add unit test for AddTimeData (mzumsande) -- #16561 Use colors and dots in test_runner.py output only if standard output is a terminal (practicalswift) -- #16465 Test p2sh-witness and bech32 in wallet_import_rescan (MarcoFalke) -- #16582 Rework ci (Use travis only as fallback env) (MarcoFalke) -- #16633 travis: Fix test_runner.py timeouts (MarcoFalke) -- #16646 Run tests with UPnP disabled (fanquake) -- #16623 ci: Add environment files for all settings (MarcoFalke) -- #16656 fix rpc_setban.py race (jonasschnelli) -- #16570 Make descriptor tests deterministic (davereikher) -- #16404 Test ZMQ notification after chain reorg (promag) -- #16726 Avoid common Python default parameter gotcha when mutable dict/list:s are used as default parameter values (practicalswift) -- #16739 ci: Pass down $makejobs to test_runner.py, other improvements (MarcoFalke) -- #16767 Check for codespell in lint-spelling.sh (kristapsk) -- #16768 Make lint-includes.sh work from any directory (kristapsk) -- #15257 Scripts and tools: Bump flake8 to 3.7.8 (Empact) -- #16804 Remove unused try-block in assert_debug_log (MarcoFalke) -- #16850 `servicesnames` field in `getpeerinfo` and `getnetworkinfo` (darosior) -- #16551 Test that low difficulty chain fork is rejected (MarcoFalke) -- #16737 Establish only one connection between nodes in rpc_invalidateblock (MarcoFalke) -- #16845 Add notes on how to generate data/wallets/high_minversion (MarcoFalke) -- #16888 Bump timeouts in slow running tests (MarcoFalke) -- #16864 Add python bech32 impl round-trip test (instagibbs) -- #16865 add some unit tests for merkle.cpp (soroosh-sdi) -- #14696 Add explicit references to related CVE's in p2p_invalid_block test (lucash-dev) -- #16907 lint: Add DisabledOpcodeTemplates to whitelist (MarcoFalke) -- #16898 Remove connect_nodes_bi (MarcoFalke) -- #16917 Move common function assert_approx() into util.py (fridokus) -- #16921 Add information on how to add Vulture suppressions (practicalswift) -- #16920 Fix extra_args in wallet_import_rescan.py (MarcoFalke) -- #16918 Make PORT_MIN in test runner configurable (MarcoFalke) -- #16941 travis: Disable feature_block in tsan run due to oom (MarcoFalke) -- #16929 follow-up to rpc: default maxfeerate value as BTC/kB (jonatack) -- #16959 ci: Set $host before setting fallback values (MarcoFalke) -- #16961 Remove python dead code linter (laanwj) -- #16931 add unittests for CheckProofOfWork (soroosh-sdi) -- #16991 Fix service flag comparison check in rpc_net test (luke-jr) (laanwj) -- #16987 Correct docstring param name (jbampton) -- #17015 Explain QT_QPA_PLATFORM for gui tests (MarcoFalke) -- #17006 Enable UBSan for Travis fuzzing job (practicalswift) -- #17086 Fix fs_tests for unknown locales (carnhofdaki) -- #15903 appveyor: Write @PACKAGE_NAME@ to config (MarcoFalke) -- #16742 test: add executable flag for wallet_watchonly.py (theStack) -- #16740 qa: Relax so that the subscriber is ready before publishing zmq messages (#16740) - -### Miscellaneous -- #15335 Fix lack of warning of unrecognized section names (AkioNak) -- #15528 contrib: Bump gitian descriptors for 0.19 (MarcoFalke) -- #15609 scripts and tools: Set 'distro' explicitly (hebasto) -- #15519 Add Poly1305 implementation (jonasschnelli) -- #15643 contrib: Gh-merge: include acks in merge commit (MarcoFalke) -- #15838 scripts and tools: Fetch missing review comments in github-merge.py (nkostoulas) -- #15920 lint: Check that all wallet args are hidden (MarcoFalke) -- #15849 Thread names in logs and deadlock debug tools (jamesob) -- #15650 Handle the result of posix_fallocate system call (lucayepa) -- #15766 scripts and tools: Upgrade gitian image before signing (hebasto) -- #15512 Add ChaCha20 encryption option (XOR) (jonasschnelli) -- #15968 Fix portability issue with pthreads (grim-trigger) -- #15970 Utils and libraries: fix static_assert for macro HAVE_THREAD_LOCAL (orientye) -- #15863 scripts and tools: Ensure repos are up-to-date in gitian-build.py (hebasto) -- #15224 Add RNG strengthening (10ms once every minute) (sipa) -- #15840 Contrib scripts: Filter IPv6 by ASN (abitfan) -- #13998 Scripts and tools: gitian-build.py improvements and corrections (hebasto) -- #15236 scripts and tools: Make --setup command independent (hebasto) -- #16114 contrib: Add curl as a required program in gitian-build.py (fanquake) -- #16046 util: Add type safe gettime (MarcoFalke) -- #15703 Update secp256k1 subtree to latest upstream (sipa) -- #16086 contrib: Use newer config.guess & config.sub in install_db4.sh (fanquake) -- #16130 Don't GPG sign intermediate commits with github-merge tool (stevenroose) -- #16162 scripts: Add key for michael ford (fanquake) to trusted keys list (fanquake) -- #16201 devtools: Always use unabbreviated commit IDs in github-merge.py (laanwj) -- #16112 util: Log early messages (MarcoFalke) -- #16223 devtools: Fetch and display ACKs at sign-off time in github-merge (laanwj) -- #16300 util: Explain why the path is cached (MarcoFalke) -- #16314 scripts and tools: Update copyright_header.py script (hebasto) -- #16158 Fix logic of memory_cleanse() on MSVC and clean up docs (real-or-random) -- #14734 fix an undefined behavior in uint::SetHex (kazcw) -- #16327 scripts and tools: Update ShellCheck linter (hebasto) -- #15277 contrib: Enable building in guix containers (dongcarl) -- #16362 Add bilingual_str type (hebasto) -- #16481 logs: add missing space (harding) -- #16581 sipsorcery gitian key (sipsorcery) -- #16566 util: Refactor upper/lowercase functions (kallewoof) -- #16620 util: Move resolveerrmsg to util/error (MarcoFalke) -- #16625 scripts: Remove github-merge.py (fanquake) -- #15864 Fix datadir handling (hebasto) -- #16670 util: Add join helper to join a list of strings (MarcoFalke) -- #16665 scripts: Move update-translations.py to maintainer-tools repo (fanquake) -- #16730 Support serialization of `std::vector<bool>` (sipa) -- #16556 Fix systemd service file configuration directory setup (setpill) -- #15615 Add log output during initial header sync (jonasschnelli) -- #16774 Avoid unnecessary "Synchronizing blockheaders" log messages (jonasschnelli) -- #16489 log: harmonize bitcoind logging (jonatack) -- #16577 util: Cbufferedfile fixes and unit test (LarryRuane) -- #16984 util: Make thread names shorter (hebasto) -- #17038 Don't rename main thread at process level (laanwj) -- #17184 util: Filter out macos process serial number (hebasto) -- #17095 util: Filter control characters out of log messages (laanwj) -- #17085 init: Change fallback locale to C.UTF-8 (laanwj) -- #16957 9% less memory: make SaltedOutpointHasher noexcept (martinus) - -### Documentation -- #15514 Update Transifex links (fanquake) -- #15513 add "sections" info to example bitcoin.conf (fanquake) -- #15530 Move wallet lock annotations to header (MarcoFalke) -- #15562 remove duplicate clone step in build-windows.md (fanquake) -- #15565 remove release note fragments (fanquake) -- #15444 Additional productivity tips (Sjors) -- #15577 Enable TLS in link to chris.beams.io (JeremyRand) -- #15604 release note for disabling reject messages by default (jnewbery) -- #15611 Add Gitian key for droark (droark) -- #15626 Update ACK description in CONTRIBUTING.md (jonatack) -- #15603 Add more tips to productivity.md (gwillen) -- #15683 Comment for seemingly duplicate LIBBITCOIN_SERVER (Bushstar) -- #15685 rpc-mining: Clarify error messages (MarcoFalke) -- #15760 Clarify sendrawtransaction::maxfeerate==0 help (MarcoFalke) -- #15659 fix findFork comment (r8921039) -- #15718 Improve netaddress comments (dongcarl) -- #15833 remove out-of-date comment on pay-to-witness support (r8921039) -- #15821 Remove upgrade note in release notes from EOL versions (MarcoFalke) -- #15267 explain AcceptToMemoryPoolWorker's coins_to_uncache (jamesob) -- #15887 Align code example style with clang-format (hebasto) -- #15877 Fix -dustrelayfee= argument docs grammar (keepkeyjon) -- #15908 Align MSVC build options with Linux build ones (hebasto) -- #15941 Add historical release notes for 0.18.0 (laanwj) -- #15794 Clarify PR guidelines w/re documentation (dongcarl) -- #15607 Release process updates (jonatack) -- #14364 Clarify -blocksdir usage (sangaman) -- #15777 Add doxygen comments for keypool classes (jnewbery) -- #15820 Add productivity notes for dummy rebases (dongcarl) -- #15922 Explain how to pass in non-fundamental types into functions (MarcoFalke) -- #16080 build/doc: update bitcoin_config.h packages, release process (jonatack) -- #16047 analyzepsbt description in doc/psbt.md (jonatack) -- #16039 add release note for 14954 (fanquake) -- #16139 Add riscv64 to outputs list in release-process.md (JeremyRand) -- #16140 create security policy (narula) -- #16164 update release process for SECURITY.md (jonatack) -- #16213 Remove explicit mention of versions from SECURITY.md (MarcoFalke) -- #16186 doc/lint: Fix spelling errors identified by codespell 1.15.0 (Empact) -- #16149 Rework section on ACK in CONTRIBUTING.md (MarcoFalke) -- #16196 Add release notes for 14897 & 15834 (MarcoFalke) -- #16241 add rapidcheck to vcpkg install list (fanquake) -- #16243 Remove travis badge from readme (MarcoFalke) -- #16256 remove orphaned header in developer notes (jonatack) -- #15964 Improve build-osx document formatting (giulio92) -- #16313 Fix broken link in doc/build-osx.md (jonatack) -- #16330 Use placeholder instead of key expiration date (hebasto) -- #16339 add reduce-memory.md (fanquake) -- #16347 Include static members in Doxygen (dongcarl) -- #15824 Improve netbase comments (dongcarl) -- #16430 Update bips 35, 37 and 111 status (MarcoFalke) -- #16455 Remove downgrading warning in release notes, per 0.18 branch (MarcoFalke) -- #16484 update labels in CONTRIBUTING.md (MarcoFalke) -- #16483 update Python command in msvc readme (sipsorcery) -- #16504 Add release note for the deprecated totalFee option of bumpfee (promag) -- #16448 add note on precedence of options in bitcoin.conf (fanquake) -- #16536 Update and extend benchmarking.md (ariard) -- #16530 Fix grammar and punctuation in developer notes (Tech1k) -- #16574 Add historical release notes for 0.18.1 (laanwj) -- #16585 Update Markdown syntax for bdb packages (emilengler) -- #16586 Mention other ways to conserve memory on compilation (MarcoFalke) -- #16605 Add missing contributor to 0.18.1 release notes (meshcollider) -- #16615 Fix typos in COPYRIGHT (gapeman) -- #16626 Fix spelling error chache -> cache (nilswloewen) -- #16587 Improve versionbits.h documentation (ariard) -- #16643 Add ZMQ dependencies to the Fedora build instructions (hebasto) -- #16634 Refer in rpcbind doc to the manpage (MarcoFalke) -- #16555 mention whitelist is inbound, and applies to blocksonly (Sjors) -- #16645 initial RapidCheck property-based testing documentation (jonatack) -- #16691 improve depends prefix documentation (fanquake) -- #16629 Add documentation for the new whitelist permissions (NicolasDorier) -- #16723 Update labels in CONTRIBUTING.md (hebasto) -- #16461 Tidy up shadowing section (promag) -- #16621 add default bitcoin.conf locations (GChuf) -- #16752 Delete stale URL in test README (michaelfolkson) -- #14862 Declare BLOCK_VALID_HEADER reserved (MarcoFalke) -- #16806 Add issue templates for bug and feature request (MarcoFalke) -- #16857 Elaborate need to re-login on Debian-based after usermod for Tor group (clashicly) -- #16863 Add a missing closing parenthesis in the bitcoin-wallet's help (darosior) -- #16757 CChainState return values (MarcoFalke) -- #16847 add comments clarifying how local services are advertised (jamesob) -- #16812 Fix whitespace errs in .md files, bitcoin.conf, and Info.plist.in (ch4ot1c) -- #16885 Update tx-size-small comment with relevant CVE disclosure (instagibbs) -- #16900 Fix doxygen comment for SignTransaction in rpc/rawtransaction_util (MarcoFalke) -- #16914 Update homebrew instruction for doxygen (Sjors) -- #16912 Remove Doxygen intro from src/bitcoind.cpp (ch4ot1c) -- #16960 replace outdated OpenSSL comment in test README (fanquake) -- #16968 Remove MSVC update step from translation process (laanwj) -- #16953 Improve test READMEs (fjahr) -- #16962 Put PR template in comments (laanwj) -- #16397 Clarify includeWatching for fundrawtransaction (stevenroose) -- #15459 add how to calculate blockchain and chainstate size variables to release process (marcoagner) -- #16997 Update bips.md for 0.19 (laanwj) -- #17001 Remove mention of renamed mapBlocksUnlinked (MarcoFalke) -- #17014 Consolidate release notes before 0.19.0 (move-only) (MarcoFalke) -- #17111 update bips.md with buried BIP9 deployments (MarcoFalke) - -Credits -======= - -Thanks to everyone who directly contributed to this release: - -- 251 -- Aaron Clauson -- Akio Nakamura -- Alistair Mann -- Amiti Uttarwar -- Andrew Chow -- andrewtoth -- Anthony Towns -- Antoine Riard -- Aseem Sood -- Ben Carman -- Ben Woosley -- bpay -- Carl Dong -- Carnhof Daki -- Chris Capobianco -- Chris Moore -- Chuf -- clashic -- clashicly -- Cory Fields -- Daki Carnhof -- Dan Gershony -- Daniel Edgecumbe -- Daniel Kraft -- Daniel McNally -- darosior -- David A. Harding -- David Reikher -- Douglas Roark -- Elichai Turkel -- Emil -- Emil Engler -- ezegom -- Fabian Jahr -- fanquake -- Felix Weis -- Ferdinando M. Ametrano -- fridokus -- gapeman -- GChuf -- Gert-Jaap Glasbergen -- Giulio Lombardo -- Glenn Willen -- Graham Krizek -- Gregory Sanders -- grim-trigger -- gwillen -- Hennadii Stepanov -- Jack Mallers -- James Hilliard -- James O'Beirne -- Jan Beich -- Jeremy Rubin -- JeremyRand -- Jim Posen -- John Bampton -- John Newbery -- Jon Atack -- Jon Layton -- Jonas Schnelli -- Jonathan "Duke" Leto -- João Barbosa -- Joonmo Yang -- Jordan Baczuk -- Jorge Timón -- Josu Goñi -- Julian Fleischer -- Karl-Johan Alm -- Kaz Wesley -- keepkeyjon -- Kirill Fomichev -- Kristaps Kaupe -- Kristian Kramer -- Larry Ruane -- Lenny Maiorani -- LongShao007 -- Luca Venturini -- lucash-dev -- Luke Dashjr -- marcoagner -- MarcoFalke -- marcuswin -- Martin Ankerl -- Martin Zumsande -- Matt Corallo -- MeshCollider -- Michael Folkson -- Miguel Herranz -- Nathan Marley -- Neha Narula -- nicolas.dorier -- Nils Loewen -- nkostoulas -- orient -- Patrick Strateman -- Peter Bushnell -- Peter Wagner -- Pieter Wuille -- practicalswift -- qmma -- r8921039 -- RJ Rybarczyk -- Russell Yanofsky -- Samuel Dobson -- Sebastian Falbesoner -- setpill -- shannon1916 -- Sjors Provoost -- soroosh-sdi -- Steven Roose -- Suhas Daftuar -- tecnovert -- THETCR -- Tim Ruffing -- Tobias Kaderle -- Torkel Rogstad -- Ulrich Kempken -- whythat -- William Casarin -- Wladimir J. van der Laan -- zenosage +Due to a last-minute issue (#17449), 0.19.0, although it was tagged, was never released. -As well as everyone that helped translating on [Transifex](https://www.transifex.com/bitcoin/bitcoin/). +See the release notes for 0.19.0.1 instead. diff --git a/doc/release-process.md b/doc/release-process.md index 2c3c4e3869..6d1e7c69e9 100644 --- a/doc/release-process.md +++ b/doc/release-process.md @@ -116,10 +116,8 @@ Ensure gitian-builder is up-to-date: pushd ./gitian-builder mkdir -p inputs - wget -P inputs https://bitcoincore.org/cfields/osslsigncode-Backports-to-1.7.1.patch - echo 'a8c4e9cafba922f89de0df1f2152e7be286aba73f78505169bc351a7938dd911 inputs/osslsigncode-Backports-to-1.7.1.patch' | sha256sum -c - wget -P inputs https://downloads.sourceforge.net/project/osslsigncode/osslsigncode/osslsigncode-1.7.1.tar.gz - echo 'f9a8cdb38b9c309326764ebc937cba1523a3a751a7ab05df3ecc99d18ae466c9 inputs/osslsigncode-1.7.1.tar.gz' | sha256sum -c + wget -O osslsigncode-2.0.tar.gz -P inputs https://github.com/mtrojnar/osslsigncode/archive/2.0.tar.gz + echo '5a60e0a4b3e0b4d655317b2f12a810211c50242138322b16e7e01c6fbb89d92f inputs/osslsigncode-2.0.tar.gz' | sha256sum -c popd Create the macOS SDK tarball, see the [macOS build instructions](build-osx.md#deterministic-macos-dmg-notes) for details, and copy it into the inputs directory. diff --git a/libbitcoinconsensus.pc.in b/libbitcoinconsensus.pc.in index eb920c47eb..1ceab280bb 100644 --- a/libbitcoinconsensus.pc.in +++ b/libbitcoinconsensus.pc.in @@ -8,4 +8,3 @@ Description: Library for the Bitcoin consensus protocol. Version: @PACKAGE_VERSION@ Libs: -L${libdir} -lbitcoinconsensus Cflags: -I${includedir} -Requires.private: libcrypto diff --git a/share/qt/Info.plist.in b/share/qt/Info.plist.in index ffa001bb7f..275078c88d 100644 --- a/share/qt/Info.plist.in +++ b/share/qt/Info.plist.in @@ -3,7 +3,7 @@ <plist version="0.9"> <dict> <key>LSMinimumSystemVersion</key> - <string>10.10.0</string> + <string>10.12.0</string> <key>LSArchitecturePriority</key> <array> diff --git a/src/Makefile.am b/src/Makefile.am index a14e44d2c0..27c87688b4 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) +BITCOIN_INCLUDES=-I$(builddir) $(BDB_CPPFLAGS) $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS) BITCOIN_INCLUDES += -I$(srcdir)/secp256k1/include BITCOIN_INCLUDES += $(UNIVALUE_CFLAGS) @@ -119,6 +119,7 @@ BITCOIN_CORE_H = \ compat.h \ compat/assumptions.h \ compat/byteswap.h \ + compat/cpuid.h \ compat/endian.h \ compat/sanity.h \ compressor.h \ @@ -175,6 +176,7 @@ BITCOIN_CORE_H = \ protocol.h \ psbt.h \ random.h \ + randomenv.h \ reverse_iterator.h \ reverselock.h \ rpc/blockchain.h \ @@ -503,6 +505,7 @@ libbitcoin_util_a_SOURCES = \ interfaces/handler.cpp \ logging.cpp \ random.cpp \ + randomenv.cpp \ rpc/request.cpp \ support/cleanse.cpp \ sync.cpp \ @@ -568,7 +571,7 @@ bitcoind_LDADD = \ $(LIBMEMENV) \ $(LIBSECP256K1) -bitcoind_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(ZMQ_LIBS) +bitcoind_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(MINIUPNPC_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(ZMQ_LIBS) # bitcoin-cli binary # bitcoin_cli_SOURCES = bitcoin-cli.cpp @@ -586,7 +589,7 @@ bitcoin_cli_LDADD = \ $(LIBBITCOIN_UTIL) \ $(LIBBITCOIN_CRYPTO) -bitcoin_cli_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS) $(EVENT_LIBS) +bitcoin_cli_LDADD += $(BOOST_LIBS) $(EVENT_LIBS) # # bitcoin-tx binary # @@ -607,7 +610,7 @@ bitcoin_tx_LDADD = \ $(LIBBITCOIN_CRYPTO) \ $(LIBSECP256K1) -bitcoin_tx_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS) +bitcoin_tx_LDADD += $(BOOST_LIBS) # # bitcoin-wallet binary # @@ -634,7 +637,7 @@ bitcoin_wallet_LDADD = \ $(LIBSECP256K1) \ $(LIBUNIVALUE) -bitcoin_wallet_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(CRYPTO_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(MINIUPNPC_LIBS) $(ZMQ_LIBS) +bitcoin_wallet_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(MINIUPNPC_LIBS) $(ZMQ_LIBS) # # bitcoinconsensus library # @@ -714,6 +717,8 @@ if EMBEDDED_LEVELDB include Makefile.leveldb.include endif +include Makefile.test_util.include + if ENABLE_TESTS include Makefile.test.include endif diff --git a/src/Makefile.bench.include b/src/Makefile.bench.include index c9e4fcc4bc..9e70db116b 100644 --- a/src/Makefile.bench.include +++ b/src/Makefile.bench.include @@ -40,10 +40,6 @@ bench_bench_bitcoin_SOURCES = \ bench/lockedpool.cpp \ bench/poly1305.cpp \ bench/prevector.cpp \ - test/util/transaction_utils.h \ - test/util/transaction_utils.cpp \ - test/util/setup_common.h \ - test/util/setup_common.cpp \ test/util.h \ test/util.cpp @@ -59,6 +55,7 @@ bench_bench_bitcoin_LDADD = \ $(LIBBITCOIN_UTIL) \ $(LIBBITCOIN_CONSENSUS) \ $(LIBBITCOIN_CRYPTO) \ + $(LIBTEST_UTIL) \ $(LIBLEVELDB) \ $(LIBLEVELDB_SSE42) \ $(LIBMEMENV) \ @@ -76,7 +73,7 @@ bench_bench_bitcoin_SOURCES += bench/coin_selection.cpp bench_bench_bitcoin_SOURCES += bench/wallet_balance.cpp endif -bench_bench_bitcoin_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(CRYPTO_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(MINIUPNPC_LIBS) +bench_bench_bitcoin_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(MINIUPNPC_LIBS) bench_bench_bitcoin_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) CLEAN_BITCOIN_BENCH = bench/*.gcda bench/*.gcno $(GENERATED_BENCH_FILES) diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index 13b1470b58..cf09eee2cb 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -136,6 +136,7 @@ BITCOIN_QT_H = \ qt/rpcconsole.h \ qt/sendcoinsdialog.h \ qt/sendcoinsentry.h \ + qt/sendcoinsrecipient.h \ qt/signverifymessagedialog.h \ qt/splashscreen.h \ qt/trafficgraphwidget.h \ @@ -314,7 +315,6 @@ 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) $(BDB_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1) \ $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) -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 diff --git a/src/Makefile.qttest.include b/src/Makefile.qttest.include index 562b393b22..8c47fabad9 100644 --- a/src/Makefile.qttest.include +++ b/src/Makefile.qttest.include @@ -26,12 +26,6 @@ TEST_QT_H = \ qt/test/util.h \ qt/test/wallettests.h -TEST_BITCOIN_CPP = \ - test/util/setup_common.cpp - -TEST_BITCOIN_H = \ - test/util/setup_common.h - qt_test_test_bitcoin_qt_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(BITCOIN_QT_INCLUDES) \ $(QT_INCLUDES) $(QT_TEST_INCLUDES) @@ -42,9 +36,7 @@ qt_test_test_bitcoin_qt_SOURCES = \ qt/test/test_main.cpp \ qt/test/uritests.cpp \ qt/test/util.cpp \ - $(TEST_QT_H) \ - $(TEST_BITCOIN_CPP) \ - $(TEST_BITCOIN_H) + $(TEST_QT_H) if ENABLE_WALLET qt_test_test_bitcoin_qt_SOURCES += \ qt/test/addressbooktests.cpp \ @@ -54,7 +46,7 @@ endif # ENABLE_WALLET nodist_qt_test_test_bitcoin_qt_SOURCES = $(TEST_QT_MOC_CPP) -qt_test_test_bitcoin_qt_LDADD = $(LIBBITCOINQT) $(LIBBITCOIN_SERVER) +qt_test_test_bitcoin_qt_LDADD = $(LIBBITCOINQT) $(LIBBITCOIN_SERVER) $(LIBTEST_UTIL) if ENABLE_WALLET qt_test_test_bitcoin_qt_LDADD += $(LIBBITCOIN_UTIL) $(LIBBITCOIN_WALLET) endif @@ -63,7 +55,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) $(BDB_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1) \ + $(QR_LIBS) $(BDB_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 dd1ade5496..b4ca01b1fe 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -24,6 +24,7 @@ FUZZ_TARGETS = \ test/fuzz/messageheader_deserialize \ test/fuzz/netaddr_deserialize \ test/fuzz/parse_iso8601 \ + test/fuzz/psbt \ test/fuzz/script \ test/fuzz/script_flags \ test/fuzz/service_deserialize \ @@ -57,31 +58,19 @@ RAW_TEST_FILES = GENERATED_TEST_FILES = $(JSON_TEST_FILES:.json=.json.h) $(RAW_TEST_FILES:.raw=.raw.h) BITCOIN_TEST_SUITE = \ - test/util/blockfilter.cpp \ - test/util/blockfilter.h \ - test/util/logging.cpp \ - test/util/logging.h \ - test/util/transaction_utils.cpp \ - test/util/transaction_utils.h \ test/main.cpp \ - test/util/setup_common.h \ - test/util/setup_common.cpp \ - test/util/str.h \ - test/util/str.cpp + $(TEST_UTIL_H) FUZZ_SUITE = \ test/fuzz/fuzz.cpp \ test/fuzz/fuzz.h \ - test/fuzz/FuzzedDataProvider.h \ - test/util/setup_common.cpp \ - test/util/setup_common.h \ - test/util/str.cpp \ - test/util/str.h + test/fuzz/FuzzedDataProvider.h FUZZ_SUITE_LD_COMMON = \ $(LIBBITCOIN_SERVER) \ $(LIBBITCOIN_COMMON) \ $(LIBBITCOIN_UTIL) \ + $(LIBTEST_UTIL) \ $(LIBBITCOIN_CONSENSUS) \ $(LIBBITCOIN_CRYPTO) \ $(LIBUNIVALUE) \ @@ -91,7 +80,6 @@ FUZZ_SUITE_LD_COMMON = \ $(LIBMEMENV) \ $(LIBSECP256K1) \ $(EVENT_LIBS) \ - $(CRYPTO_LIBS) \ $(EVENT_PTHREADS_LIBS) # test_bitcoin binary # @@ -198,7 +186,7 @@ endif test_test_bitcoin_SOURCES = $(BITCOIN_TEST_SUITE) $(BITCOIN_TESTS) $(JSON_TEST_FILES) $(RAW_TEST_FILES) test_test_bitcoin_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(TESTDEFS) $(EVENT_CFLAGS) -test_test_bitcoin_LDADD = +test_test_bitcoin_LDADD = $(LIBTEST_UTIL) if ENABLE_WALLET test_test_bitcoin_LDADD += $(LIBBITCOIN_WALLET) endif @@ -207,7 +195,7 @@ test_test_bitcoin_LDADD += $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_C $(LIBLEVELDB) $(LIBLEVELDB_SSE42) $(LIBMEMENV) $(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) $(LIBSECP256K1) $(EVENT_LIBS) $(EVENT_PTHREADS_LIBS) test_test_bitcoin_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) -test_test_bitcoin_LDADD += $(BDB_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(RAPIDCHECK_LIBS) +test_test_bitcoin_LDADD += $(BDB_LIBS) $(MINIUPNPC_LIBS) $(RAPIDCHECK_LIBS) test_test_bitcoin_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -static if ENABLE_ZMQ @@ -293,6 +281,12 @@ test_fuzz_parse_iso8601_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) test_fuzz_parse_iso8601_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) test_fuzz_parse_iso8601_LDADD = $(FUZZ_SUITE_LD_COMMON) +test_fuzz_psbt_SOURCES = $(FUZZ_SUITE) test/fuzz/psbt.cpp +test_fuzz_psbt_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) +test_fuzz_psbt_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) +test_fuzz_psbt_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) +test_fuzz_psbt_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) diff --git a/src/Makefile.test_util.include b/src/Makefile.test_util.include new file mode 100644 index 0000000000..cf55d141b0 --- /dev/null +++ b/src/Makefile.test_util.include @@ -0,0 +1,31 @@ +# Copyright (c) 2013-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. + +LIBTEST_UTIL=libtest_util.a + +EXTRA_LIBRARIES += \ + $(LIBTEST_UTIL) + +TEST_UTIL_H = \ + test/util/blockfilter.h \ + test/util/logging.h \ + test/util/setup_common.h \ + test/util/str.h \ + test/util/transaction_utils.h + +libtest_util_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(MINIUPNPC_CPPFLAGS) $(EVENT_CFLAGS) $(EVENT_PTHREADS_CFLAGS) +libtest_util_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) +libtest_util_a_SOURCES = \ + test/util/blockfilter.cpp \ + test/util/logging.cpp \ + test/util/setup_common.cpp \ + test/util/str.cpp \ + test/util/transaction_utils.cpp \ + $(TEST_UTIL_H) + +LIBTEST_UTIL += $(LIBBITCOIN_SERVER) +LIBTEST_UTIL += $(LIBBITCOIN_COMMON) +LIBTEST_UTIL += $(LIBBITCOIN_UTIL) +LIBTEST_UTIL += $(LIBBITCOIN_CRYPTO_BASE) + diff --git a/src/bitcoin-wallet.cpp b/src/bitcoin-wallet.cpp index 917ecd71c5..a2013edc05 100644 --- a/src/bitcoin-wallet.cpp +++ b/src/bitcoin-wallet.cpp @@ -41,8 +41,8 @@ static bool WalletAppInit(int argc, char* argv[]) } if (argc < 2 || HelpRequested(gArgs)) { std::string usage = strprintf("%s bitcoin-wallet version", PACKAGE_NAME) + " " + FormatFullVersion() + "\n\n" + - "wallet-tool is an offline tool for creating and interacting with Bitcoin Core wallet files.\n" + - "By default wallet-tool will act on wallets in the default mainnet wallet directory in the datadir.\n" + + "bitcoin-wallet is an offline tool for creating and interacting with Bitcoin Core wallet files.\n" + + "By default bitcoin-wallet will act on wallets in the default mainnet wallet directory in the datadir.\n" + "To change the target wallet, use the -datadir, -wallet and -testnet/-regtest arguments.\n\n" + "Usage:\n" + " bitcoin-wallet [options] <command>\n\n" + diff --git a/src/compat/cpuid.h b/src/compat/cpuid.h new file mode 100644 index 0000000000..0877ad47d3 --- /dev/null +++ b/src/compat/cpuid.h @@ -0,0 +1,24 @@ +// 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. + +#ifndef BITCOIN_COMPAT_CPUID_H +#define BITCOIN_COMPAT_CPUID_H + +#if defined(__x86_64__) || defined(__amd64__) || defined(__i386__) +#define HAVE_GETCPUID + +#include <cpuid.h> + +// We can't use cpuid.h's __get_cpuid as it does not support subleafs. +void static inline GetCPUID(uint32_t leaf, uint32_t subleaf, uint32_t& a, uint32_t& b, uint32_t& c, uint32_t& d) +{ +#ifdef __GNUC__ + __cpuid_count(leaf, subleaf, a, b, c, d); +#else + __asm__ ("cpuid" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(leaf), "2"(subleaf)); +#endif +} + +#endif // defined(__x86_64__) || defined(__amd64__) || defined(__i386__) +#endif // BITCOIN_COMPAT_CPUID_H diff --git a/src/consensus/validation.h b/src/consensus/validation.h index e602b9d5f3..3401eb64ca 100644 --- a/src/consensus/validation.h +++ b/src/consensus/validation.h @@ -114,7 +114,7 @@ inline ValidationState::~ValidationState() {}; class TxValidationState : public ValidationState { private: - TxValidationResult m_result; + TxValidationResult m_result = TxValidationResult::TX_RESULT_UNSET; public: bool Invalid(TxValidationResult result, const std::string &reject_reason="", @@ -129,7 +129,7 @@ public: class BlockValidationState : public ValidationState { private: - BlockValidationResult m_result; + BlockValidationResult m_result = BlockValidationResult::BLOCK_RESULT_UNSET; public: bool Invalid(BlockValidationResult result, const std::string &reject_reason="", diff --git a/src/crypto/sha256.cpp b/src/crypto/sha256.cpp index 3257ee7f97..dda7e5230f 100644 --- a/src/crypto/sha256.cpp +++ b/src/crypto/sha256.cpp @@ -8,9 +8,10 @@ #include <assert.h> #include <string.h> +#include <compat/cpuid.h> + #if defined(__x86_64__) || defined(__amd64__) || defined(__i386__) #if defined(USE_ASM) -#include <cpuid.h> namespace sha256_sse4 { void Transform(uint32_t* s, const unsigned char* chunk, size_t blocks); @@ -546,18 +547,7 @@ bool SelfTest() { return true; } - #if defined(USE_ASM) && (defined(__x86_64__) || defined(__amd64__) || defined(__i386__)) -// We can't use cpuid.h's __get_cpuid as it does not support subleafs. -void inline cpuid(uint32_t leaf, uint32_t subleaf, uint32_t& a, uint32_t& b, uint32_t& c, uint32_t& d) -{ -#ifdef __GNUC__ - __cpuid_count(leaf, subleaf, a, b, c, d); -#else - __asm__ ("cpuid" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(leaf), "2"(subleaf)); -#endif -} - /** Check whether the OS has enabled AVX registers. */ bool AVXEnabled() { @@ -572,7 +562,7 @@ bool AVXEnabled() std::string SHA256AutoDetect() { std::string ret = "standard"; -#if defined(USE_ASM) && (defined(__x86_64__) || defined(__amd64__) || defined(__i386__)) +#if defined(USE_ASM) && defined(HAVE_GETCPUID) bool have_sse4 = false; bool have_xsave = false; bool have_avx = false; @@ -589,7 +579,7 @@ std::string SHA256AutoDetect() (void)enabled_avx; uint32_t eax, ebx, ecx, edx; - cpuid(1, 0, eax, ebx, ecx, edx); + GetCPUID(1, 0, eax, ebx, ecx, edx); have_sse4 = (ecx >> 19) & 1; have_xsave = (ecx >> 27) & 1; have_avx = (ecx >> 28) & 1; @@ -597,7 +587,7 @@ std::string SHA256AutoDetect() enabled_avx = AVXEnabled(); } if (have_sse4) { - cpuid(7, 0, eax, ebx, ecx, edx); + GetCPUID(7, 0, eax, ebx, ecx, edx); have_avx2 = (ebx >> 5) & 1; have_shani = (ebx >> 29) & 1; } diff --git a/src/crypto/sha512.h b/src/crypto/sha512.h index 4118ac1b18..fc7dd1b87e 100644 --- a/src/crypto/sha512.h +++ b/src/crypto/sha512.h @@ -23,6 +23,7 @@ public: CSHA512& Write(const unsigned char* data, size_t len); void Finalize(unsigned char hash[OUTPUT_SIZE]); CSHA512& Reset(); + uint64_t Size() const { return bytes; } }; #endif // BITCOIN_CRYPTO_SHA512_H diff --git a/src/cuckoocache.h b/src/cuckoocache.h index 674f47b956..4ad5818cdc 100644 --- a/src/cuckoocache.h +++ b/src/cuckoocache.h @@ -6,11 +6,11 @@ #define BITCOIN_CUCKOOCACHE_H #include <array> -#include <algorithm> #include <atomic> -#include <cstring> #include <cmath> +#include <cstring> #include <memory> +#include <utility> #include <vector> diff --git a/src/init.cpp b/src/init.cpp index f02740786d..e7dda59590 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -281,9 +281,9 @@ void Shutdown(NodeContext& node) node.chain_clients.clear(); UnregisterAllValidationInterfaces(); GetMainSignals().UnregisterBackgroundSignalScheduler(); - GetMainSignals().UnregisterWithMempoolSignals(mempool); globalVerifyHandle.reset(); ECC_Stop(); + if (node.mempool) node.mempool = nullptr; LogPrintf("%s: done\n", __func__); } @@ -563,9 +563,7 @@ std::string LicenseInfo() "\n" + "\n" + _("This is experimental software.").translated + "\n" + - strprintf(_("Distributed under the MIT software license, see the accompanying file %s or %s").translated, "COPYING", "<https://opensource.org/licenses/MIT>") + "\n" + - "\n" + - strprintf(_("This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit %s and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.").translated, "<https://www.openssl.org>") + + strprintf(_("Distributed under the MIT software license, see the accompanying file %s or %s").translated, "COPYING", "<https://opensource.org/licenses/MIT>") + "\n"; } @@ -1258,8 +1256,12 @@ bool AppInitMain(NodeContext& node) CScheduler::Function serviceLoop = std::bind(&CScheduler::serviceQueue, &scheduler); threadGroup.create_thread(std::bind(&TraceThread<CScheduler::Function>, "scheduler", serviceLoop)); + // Gather some entropy once per minute. + scheduler.scheduleEvery([]{ + RandAddPeriodic(); + }, 60000); + GetMainSignals().RegisterBackgroundSignalScheduler(scheduler); - GetMainSignals().RegisterWithMempoolSignals(mempool); // Create client interfaces for wallets that are supposed to be loaded // according to -wallet and -disablewallet options. This only constructs @@ -1632,6 +1634,11 @@ bool AppInitMain(NodeContext& node) return false; } + // Now that the chain state is loaded, make mempool generally available in the node context. For example the + // connection manager, wallet, or RPC threads, which are all started after this, may use it from the node context. + assert(!node.mempool); + node.mempool = &::mempool; + fs::path est_path = GetDataDir() / FEE_ESTIMATES_FILENAME; CAutoFile est_filein(fsbridge::fopen(est_path, "rb"), SER_DISK, CLIENT_VERSION); // Allowed to fail as this file IS missing on first startup. diff --git a/src/interfaces/wallet.cpp b/src/interfaces/wallet.cpp index 701a748e55..94c6e8c7b7 100644 --- a/src/interfaces/wallet.cpp +++ b/src/interfaces/wallet.cpp @@ -18,8 +18,9 @@ #include <wallet/feebumper.h> #include <wallet/fees.h> #include <wallet/ismine.h> -#include <wallet/rpcwallet.h> #include <wallet/load.h> +#include <wallet/psbtwallet.h> +#include <wallet/rpcwallet.h> #include <wallet/wallet.h> #include <memory> @@ -116,8 +117,22 @@ public: std::string error; return m_wallet->GetNewDestination(type, label, dest, error); } - bool getPubKey(const CKeyID& address, CPubKey& pub_key) override { return m_wallet->GetLegacyScriptPubKeyMan()->GetPubKey(address, pub_key); } - bool getPrivKey(const CKeyID& address, CKey& key) override { return m_wallet->GetLegacyScriptPubKeyMan()->GetKey(address, key); } + bool getPubKey(const CScript& script, const CKeyID& address, CPubKey& pub_key) override + { + const SigningProvider* provider = m_wallet->GetSigningProvider(script); + if (provider) { + return provider->GetPubKey(address, pub_key); + } + return false; + } + bool getPrivKey(const CScript& script, const CKeyID& address, CKey& key) override + { + const SigningProvider* provider = m_wallet->GetSigningProvider(script); + if (provider) { + return provider->GetKey(address, key); + } + return false; + } bool isSpendable(const CTxDestination& dest) override { return m_wallet->IsMine(dest) & ISMINE_SPENDABLE; } bool haveWatchOnly() override { @@ -343,6 +358,14 @@ public: } return {}; } + TransactionError fillPSBT(PartiallySignedTransaction& psbtx, + bool& complete, + int sighash_type = 1 /* SIGHASH_ALL */, + bool sign = true, + bool bip32derivs = false) override + { + return FillPSBT(m_wallet.get(), psbtx, complete, sighash_type, sign, bip32derivs); + } WalletBalances getBalances() override { const auto bal = m_wallet->GetBalance(); diff --git a/src/interfaces/wallet.h b/src/interfaces/wallet.h index a96b93b4c3..8d2b8a2eca 100644 --- a/src/interfaces/wallet.h +++ b/src/interfaces/wallet.h @@ -14,6 +14,7 @@ #include <functional> #include <map> #include <memory> +#include <psbt.h> #include <stdint.h> #include <string> #include <tuple> @@ -81,10 +82,10 @@ public: virtual bool getNewDestination(const OutputType type, const std::string label, CTxDestination& dest) = 0; //! Get public key. - virtual bool getPubKey(const CKeyID& address, CPubKey& pub_key) = 0; + virtual bool getPubKey(const CScript& script, const CKeyID& address, CPubKey& pub_key) = 0; //! Get private key. - virtual bool getPrivKey(const CKeyID& address, CKey& key) = 0; + virtual bool getPrivKey(const CScript& script, const CKeyID& address, CKey& key) = 0; //! Return whether wallet has private key. virtual bool isSpendable(const CTxDestination& dest) = 0; @@ -194,6 +195,13 @@ public: bool& in_mempool, int& num_blocks) = 0; + //! Fill PSBT. + virtual TransactionError fillPSBT(PartiallySignedTransaction& psbtx, + bool& complete, + int sighash_type = 1 /* SIGHASH_ALL */, + bool sign = true, + bool bip32derivs = false) = 0; + //! Get balances. virtual WalletBalances getBalances() = 0; diff --git a/src/key.cpp b/src/key.cpp index 3ba21753a2..10b6668aae 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -83,13 +83,13 @@ static int ec_privkey_import_der(const secp256k1_context* ctx, unsigned char *ou * <http://www.secg.org/sec1-v2.pdf>. The optional parameters and publicKey fields are * included. * - * privkey must point to an output buffer of length at least CKey::PRIVATE_KEY_SIZE bytes. + * privkey must point to an output buffer of length at least CKey::SIZE bytes. * privkeylen must initially be set to the size of the privkey buffer. Upon return it * will be set to the number of bytes used in the buffer. * key32 must point to a 32-byte raw private key. */ static int ec_privkey_export_der(const secp256k1_context *ctx, unsigned char *privkey, size_t *privkeylen, const unsigned char *key32, bool compressed) { - assert(*privkeylen >= CKey::PRIVATE_KEY_SIZE); + assert(*privkeylen >= CKey::SIZE); secp256k1_pubkey pubkey; size_t pubkeylen = 0; if (!secp256k1_ec_pubkey_create(ctx, &pubkey, key32)) { @@ -115,11 +115,11 @@ static int ec_privkey_export_der(const secp256k1_context *ctx, unsigned char *pr memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin); memcpy(ptr, key32, 32); ptr += 32; memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle); - pubkeylen = CPubKey::COMPRESSED_PUBLIC_KEY_SIZE; + pubkeylen = CPubKey::COMPRESSED_SIZE; secp256k1_ec_pubkey_serialize(ctx, ptr, &pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED); ptr += pubkeylen; *privkeylen = ptr - privkey; - assert(*privkeylen == CKey::COMPRESSED_PRIVATE_KEY_SIZE); + assert(*privkeylen == CKey::COMPRESSED_SIZE); } else { static const unsigned char begin[] = { 0x30,0x82,0x01,0x13,0x02,0x01,0x01,0x04,0x20 @@ -141,11 +141,11 @@ static int ec_privkey_export_der(const secp256k1_context *ctx, unsigned char *pr memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin); memcpy(ptr, key32, 32); ptr += 32; memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle); - pubkeylen = CPubKey::PUBLIC_KEY_SIZE; + pubkeylen = CPubKey::SIZE; secp256k1_ec_pubkey_serialize(ctx, ptr, &pubkeylen, &pubkey, SECP256K1_EC_UNCOMPRESSED); ptr += pubkeylen; *privkeylen = ptr - privkey; - assert(*privkeylen == CKey::PRIVATE_KEY_SIZE); + assert(*privkeylen == CKey::SIZE); } return 1; } @@ -173,8 +173,8 @@ CPrivKey CKey::GetPrivKey() const { CPrivKey privkey; int ret; size_t privkeylen; - privkey.resize(PRIVATE_KEY_SIZE); - privkeylen = PRIVATE_KEY_SIZE; + privkey.resize(SIZE); + privkeylen = SIZE; ret = ec_privkey_export_der(secp256k1_context_sign, privkey.data(), &privkeylen, begin(), fCompressed); assert(ret); privkey.resize(privkeylen); @@ -184,7 +184,7 @@ CPrivKey CKey::GetPrivKey() const { CPubKey CKey::GetPubKey() const { assert(fValid); secp256k1_pubkey pubkey; - size_t clen = CPubKey::PUBLIC_KEY_SIZE; + size_t clen = CPubKey::SIZE; CPubKey result; int ret = secp256k1_ec_pubkey_create(secp256k1_context_sign, &pubkey, begin()); assert(ret); @@ -276,7 +276,7 @@ bool CKey::Derive(CKey& keyChild, ChainCode &ccChild, unsigned int nChild, const std::vector<unsigned char, secure_allocator<unsigned char>> vout(64); if ((nChild >> 31) == 0) { CPubKey pubkey = GetPubKey(); - assert(pubkey.size() == CPubKey::COMPRESSED_PUBLIC_KEY_SIZE); + assert(pubkey.size() == CPubKey::COMPRESSED_SIZE); BIP32Hash(cc, nChild, *pubkey.begin(), pubkey.begin()+1, vout.data()); } else { assert(size() == 32); @@ -19,7 +19,7 @@ /** * secure_allocator is defined in allocators.h * CPrivKey is a serialized private key, with all parameters included - * (PRIVATE_KEY_SIZE bytes) + * (SIZE bytes) */ typedef std::vector<unsigned char, secure_allocator<unsigned char> > CPrivKey; @@ -30,15 +30,15 @@ public: /** * secp256k1: */ - static const unsigned int PRIVATE_KEY_SIZE = 279; - static const unsigned int COMPRESSED_PRIVATE_KEY_SIZE = 214; + static const unsigned int SIZE = 279; + static const unsigned int COMPRESSED_SIZE = 214; /** * see www.keylength.com * script supports up to 75 for single byte push */ static_assert( - PRIVATE_KEY_SIZE >= COMPRESSED_PRIVATE_KEY_SIZE, - "COMPRESSED_PRIVATE_KEY_SIZE is larger than PRIVATE_KEY_SIZE"); + SIZE >= COMPRESSED_SIZE, + "COMPRESSED_SIZE is larger than SIZE"); private: //! Whether this private key is valid. We check for correctness when modifying the key diff --git a/src/miner.cpp b/src/miner.cpp index 1c9174ee07..2f6feb9e02 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -435,7 +435,7 @@ void IncrementExtraNonce(CBlock* pblock, const CBlockIndex* pindexPrev, unsigned ++nExtraNonce; unsigned int nHeight = pindexPrev->nHeight+1; // Height first in coinbase required for block.version=2 CMutableTransaction txCoinbase(*pblock->vtx[0]); - txCoinbase.vin[0].scriptSig = (CScript() << nHeight << CScriptNum(nExtraNonce)) + COINBASE_FLAGS; + txCoinbase.vin[0].scriptSig = (CScript() << nHeight << CScriptNum(nExtraNonce)); assert(txCoinbase.vin[0].scriptSig.size() <= 100); pblock->vtx[0] = MakeTransactionRef(std::move(txCoinbase)); diff --git a/src/net.cpp b/src/net.cpp index 84692d2a79..99dae88bab 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -16,6 +16,7 @@ #include <crypto/sha256.h> #include <netbase.h> #include <net_permissions.h> +#include <random.h> #include <scheduler.h> #include <ui_interface.h> #include <util/strencodings.h> @@ -445,6 +446,9 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo CNode* pnode = new CNode(id, nLocalServices, GetBestHeight(), hSocket, addrConnect, CalculateKeyedNetGroup(addrConnect), nonce, addr_bind, pszDest ? pszDest : "", false, block_relay_only); pnode->AddRef(); + // We're making a new connection, harvest entropy from the time (and our peer count) + RandAddEvent((uint32_t)id); + return pnode; } @@ -693,6 +697,9 @@ CNetMessage V1TransportDeserializer::GetMessage(const CMessageHeader::MessageSta msg.m_message_size = hdr.nMessageSize; msg.m_raw_message_size = hdr.nMessageSize + CMessageHeader::HEADER_SIZE; + // We just received a message off the wire, harvest entropy from the time (and the message checksum) + RandAddEvent(ReadLE32(hash.begin())); + 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", @@ -1017,6 +1024,9 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) { LOCK(cs_vNodes); vNodes.push_back(pnode); } + + // We received a new connection, harvest entropy from the time (and our peer count) + RandAddEvent((uint32_t)id); } void CConnman::DisconnectNodes() diff --git a/src/node/context.h b/src/node/context.h index 2b124af4db..dab5b5d048 100644 --- a/src/node/context.h +++ b/src/node/context.h @@ -10,6 +10,7 @@ class BanMan; class CConnman; +class CTxMemPool; class PeerLogicValidation; namespace interfaces { class Chain; @@ -22,13 +23,13 @@ class ChainClient; //! This is used by init, rpc, and test code to pass object references around //! without needing to declare the same variables and parameters repeatedly, or //! to use globals. More variables could be added to this struct (particularly -//! references to validation and mempool objects) to eliminate use of globals +//! references to validation objects) to eliminate use of globals //! and make code more modular and testable. The struct isn't intended to have //! any member functions. It should just be a collection of references that can //! be used without pulling in unwanted dependencies or functionality. -struct NodeContext -{ +struct NodeContext { std::unique_ptr<CConnman> connman; + CTxMemPool* mempool{nullptr}; // Currently a raw pointer because the memory is not managed by this struct std::unique_ptr<PeerLogicValidation> peer_logic; std::unique_ptr<BanMan> banman; std::unique_ptr<interfaces::Chain> chain; diff --git a/src/prevector.h b/src/prevector.h index d307495fbe..4fb07688ff 100644 --- a/src/prevector.h +++ b/src/prevector.h @@ -13,6 +13,7 @@ #include <algorithm> #include <cstddef> #include <type_traits> +#include <utility> #pragma pack(push, 1) /** Implements a drop-in replacement for std::vector<T> which stores up to N diff --git a/src/psbt.h b/src/psbt.h index 6a5c468058..bcff66f7a1 100644 --- a/src/psbt.h +++ b/src/psbt.h @@ -171,7 +171,7 @@ struct PSBTInput case PSBT_IN_PARTIAL_SIG: { // Make sure that the key is the size of pubkey + 1 - if (key.size() != CPubKey::PUBLIC_KEY_SIZE + 1 && key.size() != CPubKey::COMPRESSED_PUBLIC_KEY_SIZE + 1) { + if (key.size() != CPubKey::SIZE + 1 && key.size() != CPubKey::COMPRESSED_SIZE + 1) { throw std::ios_base::failure("Size of key was not the expected size for the type partial signature pubkey"); } // Read in the pubkey from key diff --git a/src/pubkey.cpp b/src/pubkey.cpp index d38df716bd..10953adc35 100644 --- a/src/pubkey.cpp +++ b/src/pubkey.cpp @@ -196,8 +196,8 @@ bool CPubKey::RecoverCompact(const uint256 &hash, const std::vector<unsigned cha if (!secp256k1_ecdsa_recover(secp256k1_context_verify, &pubkey, &sig, hash.begin())) { return false; } - unsigned char pub[PUBLIC_KEY_SIZE]; - size_t publen = PUBLIC_KEY_SIZE; + unsigned char pub[SIZE]; + size_t publen = SIZE; secp256k1_ec_pubkey_serialize(secp256k1_context_verify, pub, &publen, &pubkey, fComp ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED); Set(pub, pub + publen); return true; @@ -217,8 +217,8 @@ bool CPubKey::Decompress() { if (!secp256k1_ec_pubkey_parse(secp256k1_context_verify, &pubkey, vch, size())) { return false; } - unsigned char pub[PUBLIC_KEY_SIZE]; - size_t publen = PUBLIC_KEY_SIZE; + unsigned char pub[SIZE]; + size_t publen = SIZE; secp256k1_ec_pubkey_serialize(secp256k1_context_verify, pub, &publen, &pubkey, SECP256K1_EC_UNCOMPRESSED); Set(pub, pub + publen); return true; @@ -227,7 +227,7 @@ bool CPubKey::Decompress() { bool CPubKey::Derive(CPubKey& pubkeyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc) const { assert(IsValid()); assert((nChild >> 31) == 0); - assert(size() == COMPRESSED_PUBLIC_KEY_SIZE); + assert(size() == COMPRESSED_SIZE); unsigned char out[64]; BIP32Hash(cc, nChild, *begin(), begin()+1, out); memcpy(ccChild.begin(), out+32, 32); @@ -238,8 +238,8 @@ bool CPubKey::Derive(CPubKey& pubkeyChild, ChainCode &ccChild, unsigned int nChi if (!secp256k1_ec_pubkey_tweak_add(secp256k1_context_verify, &pubkey, out)) { return false; } - unsigned char pub[COMPRESSED_PUBLIC_KEY_SIZE]; - size_t publen = COMPRESSED_PUBLIC_KEY_SIZE; + unsigned char pub[COMPRESSED_SIZE]; + size_t publen = COMPRESSED_SIZE; secp256k1_ec_pubkey_serialize(secp256k1_context_verify, pub, &publen, &pubkey, SECP256K1_EC_COMPRESSED); pubkeyChild.Set(pub, pub + publen); return true; @@ -251,8 +251,8 @@ void CExtPubKey::Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const { code[5] = (nChild >> 24) & 0xFF; code[6] = (nChild >> 16) & 0xFF; code[7] = (nChild >> 8) & 0xFF; code[8] = (nChild >> 0) & 0xFF; memcpy(code+9, chaincode.begin(), 32); - assert(pubkey.size() == CPubKey::COMPRESSED_PUBLIC_KEY_SIZE); - memcpy(code+41, pubkey.begin(), CPubKey::COMPRESSED_PUBLIC_KEY_SIZE); + assert(pubkey.size() == CPubKey::COMPRESSED_SIZE); + memcpy(code+41, pubkey.begin(), CPubKey::COMPRESSED_SIZE); } void CExtPubKey::Decode(const unsigned char code[BIP32_EXTKEY_SIZE]) { diff --git a/src/pubkey.h b/src/pubkey.h index fd815a871b..76f743da66 100644 --- a/src/pubkey.h +++ b/src/pubkey.h @@ -33,17 +33,17 @@ public: /** * secp256k1: */ - static constexpr unsigned int PUBLIC_KEY_SIZE = 65; - static constexpr unsigned int COMPRESSED_PUBLIC_KEY_SIZE = 33; - static constexpr unsigned int SIGNATURE_SIZE = 72; - static constexpr unsigned int COMPACT_SIGNATURE_SIZE = 65; + static constexpr unsigned int SIZE = 65; + static constexpr unsigned int COMPRESSED_SIZE = 33; + static constexpr unsigned int SIGNATURE_SIZE = 72; + static constexpr unsigned int COMPACT_SIGNATURE_SIZE = 65; /** * see www.keylength.com * script supports up to 75 for single byte push */ static_assert( - PUBLIC_KEY_SIZE >= COMPRESSED_PUBLIC_KEY_SIZE, - "COMPRESSED_PUBLIC_KEY_SIZE is larger than PUBLIC_KEY_SIZE"); + SIZE >= COMPRESSED_SIZE, + "COMPRESSED_SIZE is larger than SIZE"); private: @@ -51,15 +51,15 @@ private: * Just store the serialized data. * Its length can very cheaply be computed from the first byte. */ - unsigned char vch[PUBLIC_KEY_SIZE]; + unsigned char vch[SIZE]; //! Compute the length of a pubkey with a given first byte. unsigned int static GetLen(unsigned char chHeader) { if (chHeader == 2 || chHeader == 3) - return COMPRESSED_PUBLIC_KEY_SIZE; + return COMPRESSED_SIZE; if (chHeader == 4 || chHeader == 6 || chHeader == 7) - return PUBLIC_KEY_SIZE; + return SIZE; return 0; } @@ -140,7 +140,7 @@ public: void Unserialize(Stream& s) { unsigned int len = ::ReadCompactSize(s); - if (len <= PUBLIC_KEY_SIZE) { + if (len <= SIZE) { s.read((char*)vch, len); } else { // invalid pubkey, skip available data @@ -179,7 +179,7 @@ public: //! Check whether this is a compressed public key. bool IsCompressed() const { - return size() == COMPRESSED_PUBLIC_KEY_SIZE; + return size() == COMPRESSED_SIZE; } /** diff --git a/src/qt/bantablemodel.cpp b/src/qt/bantablemodel.cpp index 48201b420e..b6c6984b10 100644 --- a/src/qt/bantablemodel.cpp +++ b/src/qt/bantablemodel.cpp @@ -8,7 +8,7 @@ #include <net_types.h> // For banmap_t #include <qt/clientmodel.h> -#include <algorithm> +#include <utility> #include <QDebug> #include <QList> diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp index f928f1ca2a..3302dde4ed 100644 --- a/src/qt/coincontroldialog.cpp +++ b/src/qt/coincontroldialog.cpp @@ -468,7 +468,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) { CPubKey pubkey; PKHash *pkhash = boost::get<PKHash>(&address); - if (pkhash && model->wallet().getPubKey(CKeyID(*pkhash), pubkey)) + if (pkhash && model->wallet().getPubKey(out.txout.scriptPubKey, CKeyID(*pkhash), pubkey)) { nBytesInputs += (pubkey.IsCompressed() ? 148 : 180); } diff --git a/src/qt/forms/modaloverlay.ui b/src/qt/forms/modaloverlay.ui index b5a69c578d..da19a6fa2e 100644 --- a/src/qt/forms/modaloverlay.ui +++ b/src/qt/forms/modaloverlay.ui @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> <class>ModalOverlay</class> - <widget class="ModalOverlay" name="ModalOverlay"> + <widget class="QWidget" name="ModalOverlay"> <property name="geometry"> <rect> <x>0</x> @@ -369,14 +369,6 @@ QLabel { color: rgb(40,40,40); }</string> </item> </layout> </widget> - <customwidgets> - <customwidget> - <class>ModalOverlay</class> - <extends>QWidget</extends> - <header>qt/modaloverlay.h</header> - <container>1</container> - </customwidget> - </customwidgets> <resources/> <connections/> </ui> diff --git a/src/qt/forms/receivecoinsdialog.ui b/src/qt/forms/receivecoinsdialog.ui index 0214356eaa..7dbee6d689 100644 --- a/src/qt/forms/receivecoinsdialog.ui +++ b/src/qt/forms/receivecoinsdialog.ui @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> <class>ReceiveCoinsDialog</class> - <widget class="QWidget" name="ReceiveCoinsDialog"> + <widget class="QDialog" name="ReceiveCoinsDialog"> <property name="geometry"> <rect> <x>0</x> @@ -63,7 +63,7 @@ <item row="4" column="2"> <widget class="QLineEdit" name="reqLabel"> <property name="toolTip"> - <string>An optional label to associate with the new receiving address.</string> + <string>An optional label to associate with the new receiving address (used by you to identify an invoice). It is also attached to the payment request.</string> </property> </widget> </item> @@ -93,7 +93,7 @@ <item row="6" column="2"> <widget class="QLineEdit" name="reqMessage"> <property name="toolTip"> - <string>An optional message to attach to the payment request, which will be displayed when the request is opened. Note: The message will not be sent with the payment over the Bitcoin network.</string> + <string>An optional message that is attached to the payment request and may be displayed to the sender.</string> </property> </widget> </item> diff --git a/src/qt/forms/sendcoinsdialog.ui b/src/qt/forms/sendcoinsdialog.ui index 7190d59240..cfd4bf33d4 100644 --- a/src/qt/forms/sendcoinsdialog.ui +++ b/src/qt/forms/sendcoinsdialog.ui @@ -1190,7 +1190,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p <number>3</number> </property> <item> - <widget class="QLabel" name="label"> + <widget class="QLabel" name="labelBalanceName"> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> <horstretch>0</horstretch> diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index c4e0321f28..2bb9535441 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -7,7 +7,7 @@ #include <qt/bitcoinaddressvalidator.h> #include <qt/bitcoinunits.h> #include <qt/qvalidatedlineedit.h> -#include <qt/walletmodel.h> +#include <qt/sendcoinsrecipient.h> #include <base58.h> #include <chainparams.h> @@ -54,10 +54,7 @@ #include <QUrlQuery> #if defined(Q_OS_MAC) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#include <CoreServices/CoreServices.h> #include <QProcess> void ForceActivation(); @@ -691,87 +688,6 @@ bool SetStartOnSystemStartup(bool fAutoStart) return true; } - -#elif defined(Q_OS_MAC) && defined(MAC_OS_X_VERSION_MIN_REQUIRED) && MAC_OS_X_VERSION_MIN_REQUIRED <= 101100 -// based on: https://github.com/Mozketo/LaunchAtLoginController/blob/master/LaunchAtLoginController.m - -LSSharedFileListItemRef findStartupItemInList(CFArrayRef listSnapshot, LSSharedFileListRef list, CFURLRef findUrl) -{ - if (listSnapshot == nullptr) { - return nullptr; - } - - // loop through the list of startup items and try to find the bitcoin app - for(int i = 0; i < CFArrayGetCount(listSnapshot); i++) { - LSSharedFileListItemRef item = (LSSharedFileListItemRef)CFArrayGetValueAtIndex(listSnapshot, i); - UInt32 resolutionFlags = kLSSharedFileListNoUserInteraction | kLSSharedFileListDoNotMountVolumes; - CFURLRef currentItemURL = nullptr; - -#if defined(MAC_OS_X_VERSION_MAX_ALLOWED) && MAC_OS_X_VERSION_MAX_ALLOWED >= 10100 - if(&LSSharedFileListItemCopyResolvedURL) - currentItemURL = LSSharedFileListItemCopyResolvedURL(item, resolutionFlags, nullptr); -#if defined(MAC_OS_X_VERSION_MIN_REQUIRED) && MAC_OS_X_VERSION_MIN_REQUIRED < 10100 - else - LSSharedFileListItemResolve(item, resolutionFlags, ¤tItemURL, nullptr); -#endif -#else - LSSharedFileListItemResolve(item, resolutionFlags, ¤tItemURL, nullptr); -#endif - - if(currentItemURL) { - if (CFEqual(currentItemURL, findUrl)) { - // found - CFRelease(currentItemURL); - return item; - } - CFRelease(currentItemURL); - } - } - return nullptr; -} - -bool GetStartOnSystemStartup() -{ - CFURLRef bitcoinAppUrl = CFBundleCopyBundleURL(CFBundleGetMainBundle()); - if (bitcoinAppUrl == nullptr) { - return false; - } - - LSSharedFileListRef loginItems = LSSharedFileListCreate(nullptr, kLSSharedFileListSessionLoginItems, nullptr); - CFArrayRef listSnapshot = LSSharedFileListCopySnapshot(loginItems, nullptr); - bool res = (findStartupItemInList(listSnapshot, loginItems, bitcoinAppUrl) != nullptr); - CFRelease(bitcoinAppUrl); - CFRelease(loginItems); - CFRelease(listSnapshot); - return res; -} - -bool SetStartOnSystemStartup(bool fAutoStart) -{ - CFURLRef bitcoinAppUrl = CFBundleCopyBundleURL(CFBundleGetMainBundle()); - if (bitcoinAppUrl == nullptr) { - return false; - } - - LSSharedFileListRef loginItems = LSSharedFileListCreate(nullptr, kLSSharedFileListSessionLoginItems, nullptr); - CFArrayRef listSnapshot = LSSharedFileListCopySnapshot(loginItems, nullptr); - LSSharedFileListItemRef foundItem = findStartupItemInList(listSnapshot, loginItems, bitcoinAppUrl); - - if(fAutoStart && !foundItem) { - // add bitcoin app to startup item list - LSSharedFileListInsertItemURL(loginItems, kLSSharedFileListItemBeforeFirst, nullptr, nullptr, bitcoinAppUrl, nullptr, nullptr); - } - else if(!fAutoStart && foundItem) { - // remove item - LSSharedFileListItemRemove(loginItems, foundItem); - } - - CFRelease(bitcoinAppUrl); - CFRelease(loginItems); - CFRelease(listSnapshot); - return true; -} -#pragma GCC diagnostic pop #else bool GetStartOnSystemStartup() { return false; } diff --git a/src/qt/openuridialog.cpp b/src/qt/openuridialog.cpp index 199804f84d..6a0143ac7e 100644 --- a/src/qt/openuridialog.cpp +++ b/src/qt/openuridialog.cpp @@ -6,7 +6,7 @@ #include <qt/forms/ui_openuridialog.h> #include <qt/guiutil.h> -#include <qt/walletmodel.h> +#include <qt/sendcoinsrecipient.h> #include <QUrl> diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp index 57cafaaac0..d48c537c75 100644 --- a/src/qt/optionsdialog.cpp +++ b/src/qt/optionsdialog.cpp @@ -71,13 +71,11 @@ OptionsDialog::OptionsDialog(QWidget *parent, bool enableWallet) : #ifdef Q_OS_MAC /* remove Window tab on Mac */ ui->tabWidget->removeTab(ui->tabWidget->indexOf(ui->tabWindow)); -#if defined(MAC_OS_X_VERSION_MIN_REQUIRED) && MAC_OS_X_VERSION_MIN_REQUIRED > 101100 - /* hide launch at startup option if compiled against macOS > 10.11 (removed API) */ + /* hide launch at startup option on macOS */ ui->bitcoinAtStartup->setVisible(false); ui->verticalLayout_Main->removeWidget(ui->bitcoinAtStartup); ui->verticalLayout_Main->removeItem(ui->horizontalSpacer_0_Main); #endif -#endif /* remove Wallet tab in case of -disablewallet */ if (!enableWallet) { diff --git a/src/qt/paymentserver.h b/src/qt/paymentserver.h index 8b2533508d..6d4ce4a7e4 100644 --- a/src/qt/paymentserver.h +++ b/src/qt/paymentserver.h @@ -36,13 +36,17 @@ #include <config/bitcoin-config.h> #endif -#include <qt/walletmodel.h> +#include <qt/sendcoinsrecipient.h> #include <QObject> #include <QString> class OptionsModel; +namespace interfaces { +class Node; +} // namespace interfaces + QT_BEGIN_NAMESPACE class QApplication; class QByteArray; diff --git a/src/qt/peertablemodel.cpp b/src/qt/peertablemodel.cpp index af2a1bb0e5..514ff35bcd 100644 --- a/src/qt/peertablemodel.cpp +++ b/src/qt/peertablemodel.cpp @@ -10,7 +10,7 @@ #include <interfaces/node.h> -#include <algorithm> +#include <utility> #include <QDebug> #include <QList> diff --git a/src/qt/receiverequestdialog.cpp b/src/qt/receiverequestdialog.cpp index e492502002..2674c9b953 100644 --- a/src/qt/receiverequestdialog.cpp +++ b/src/qt/receiverequestdialog.cpp @@ -8,6 +8,7 @@ #include <qt/bitcoinunits.h> #include <qt/guiutil.h> #include <qt/optionsmodel.h> +#include <qt/walletmodel.h> #include <QClipboard> #include <QPixmap> diff --git a/src/qt/receiverequestdialog.h b/src/qt/receiverequestdialog.h index a6e1a2af16..1bb43ce6d1 100644 --- a/src/qt/receiverequestdialog.h +++ b/src/qt/receiverequestdialog.h @@ -5,10 +5,12 @@ #ifndef BITCOIN_QT_RECEIVEREQUESTDIALOG_H #define BITCOIN_QT_RECEIVEREQUESTDIALOG_H -#include <qt/walletmodel.h> +#include <qt/sendcoinsrecipient.h> #include <QDialog> +class WalletModel; + namespace Ui { class ReceiveRequestDialog; } diff --git a/src/qt/recentrequeststablemodel.cpp b/src/qt/recentrequeststablemodel.cpp index 1611ec823c..18fa5f417f 100644 --- a/src/qt/recentrequeststablemodel.cpp +++ b/src/qt/recentrequeststablemodel.cpp @@ -7,12 +7,12 @@ #include <qt/bitcoinunits.h> #include <qt/guiutil.h> #include <qt/optionsmodel.h> +#include <qt/walletmodel.h> #include <clientversion.h> #include <streams.h> -#include <algorithm> - +#include <utility> RecentRequestsTableModel::RecentRequestsTableModel(WalletModel *parent) : QAbstractTableModel(parent), walletModel(parent) @@ -213,10 +213,10 @@ void RecentRequestsTableModel::updateDisplayUnit() updateAmountColumnTitle(); } -bool RecentRequestEntryLessThan::operator()(RecentRequestEntry &left, RecentRequestEntry &right) const +bool RecentRequestEntryLessThan::operator()(const RecentRequestEntry& left, const RecentRequestEntry& right) const { - RecentRequestEntry *pLeft = &left; - RecentRequestEntry *pRight = &right; + const RecentRequestEntry* pLeft = &left; + const RecentRequestEntry* pRight = &right; if (order == Qt::DescendingOrder) std::swap(pLeft, pRight); diff --git a/src/qt/recentrequeststablemodel.h b/src/qt/recentrequeststablemodel.h index 130b709d46..f5085f7268 100644 --- a/src/qt/recentrequeststablemodel.h +++ b/src/qt/recentrequeststablemodel.h @@ -5,12 +5,14 @@ #ifndef BITCOIN_QT_RECENTREQUESTSTABLEMODEL_H #define BITCOIN_QT_RECENTREQUESTSTABLEMODEL_H -#include <qt/walletmodel.h> +#include <qt/sendcoinsrecipient.h> #include <QAbstractTableModel> #include <QStringList> #include <QDateTime> +class WalletModel; + class RecentRequestEntry { public: @@ -43,7 +45,7 @@ class RecentRequestEntryLessThan public: RecentRequestEntryLessThan(int nColumn, Qt::SortOrder fOrder): column(nColumn), order(fOrder) {} - bool operator()(RecentRequestEntry &left, RecentRequestEntry &right) const; + bool operator()(const RecentRequestEntry& left, const RecentRequestEntry& right) const; private: int column; diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index 8edcca684d..f1ea3e23e5 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -21,11 +21,13 @@ #include <chainparams.h> #include <interfaces/node.h> #include <key_io.h> -#include <wallet/coincontrol.h> -#include <ui_interface.h> -#include <txmempool.h> #include <policy/fees.h> +#include <txmempool.h> +#include <ui_interface.h> +#include <wallet/coincontrol.h> #include <wallet/fees.h> +#include <wallet/psbtwallet.h> +#include <wallet/wallet.h> #include <QFontMetrics> #include <QScrollBar> @@ -186,6 +188,11 @@ void SendCoinsDialog::setModel(WalletModel *_model) // set default rbf checkbox state ui->optInRBF->setCheckState(Qt::Checked); + if (model->privateKeysDisabled()) { + ui->sendButton->setText(tr("Cr&eate Unsigned")); + ui->sendButton->setToolTip(tr("Creates a Partially Signed Bitcoin Transaction (PSBT) for use with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.").arg(PACKAGE_NAME)); + } + // set the smartfee-sliders default value (wallets default conf.target or last stored value) QSettings settings; if (settings.value("nSmartFeeSliderPosition").toInt() != 0) { @@ -305,9 +312,19 @@ void SendCoinsDialog::on_sendButton_clicked() formatted.append(recipientElement); } - QString questionString = tr("Are you sure you want to send?"); + QString questionString; + if (model->privateKeysDisabled()) { + questionString.append(tr("Do you want to draft this transaction?")); + } else { + questionString.append(tr("Are you sure you want to send?")); + } + questionString.append("<br /><span style='font-size:10pt;'>"); - questionString.append(tr("Please, review your transaction.")); + if (model->privateKeysDisabled()) { + questionString.append(tr("Please, review your transaction proposal. This will produce a Partially Signed Bitcoin Transaction (PSBT) which you can copy and then sign with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.").arg(PACKAGE_NAME)); + } else { + questionString.append(tr("Please, review your transaction.")); + } questionString.append("</span>%1"); if(txFee > 0) @@ -358,8 +375,9 @@ void SendCoinsDialog::on_sendButton_clicked() } else { questionString = questionString.arg("<br /><br />" + formatted.at(0)); } - - SendConfirmationDialog confirmationDialog(tr("Confirm send coins"), questionString, informative_text, detailed_text, SEND_CONFIRM_DELAY, this); + const QString confirmation = model->privateKeysDisabled() ? tr("Confirm transaction proposal") : tr("Confirm send coins"); + const QString confirmButtonText = model->privateKeysDisabled() ? tr("Copy PSBT to clipboard") : tr("Send"); + SendConfirmationDialog confirmationDialog(confirmation, questionString, informative_text, detailed_text, SEND_CONFIRM_DELAY, confirmButtonText, this); confirmationDialog.exec(); QMessageBox::StandardButton retval = static_cast<QMessageBox::StandardButton>(confirmationDialog.result()); @@ -369,17 +387,35 @@ void SendCoinsDialog::on_sendButton_clicked() return; } - // now send the prepared transaction - WalletModel::SendCoinsReturn sendStatus = model->sendCoins(currentTransaction); - // process sendStatus and on error generate message shown to user - processSendCoinsReturn(sendStatus); + bool send_failure = false; + if (model->privateKeysDisabled()) { + CMutableTransaction mtx = CMutableTransaction{*(currentTransaction.getWtx())}; + PartiallySignedTransaction psbtx(mtx); + bool complete = false; + const TransactionError err = model->wallet().fillPSBT(psbtx, complete, SIGHASH_ALL, false /* sign */, true /* bip32derivs */); + assert(!complete); + assert(err == TransactionError::OK); + // Serialize the PSBT + CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION); + ssTx << psbtx; + GUIUtil::setClipboard(EncodeBase64(ssTx.str()).c_str()); + Q_EMIT message(tr("PSBT copied"), "Copied to clipboard", CClientUIInterface::MSG_INFORMATION); + } else { + // now send the prepared transaction + WalletModel::SendCoinsReturn sendStatus = model->sendCoins(currentTransaction); + // process sendStatus and on error generate message shown to user + processSendCoinsReturn(sendStatus); - if (sendStatus.status == WalletModel::OK) - { + if (sendStatus.status == WalletModel::OK) { + Q_EMIT coinsSent(currentTransaction.getWtx()->GetHash()); + } else { + send_failure = true; + } + } + if (!send_failure) { accept(); CoinControlDialog::coinControl()->UnSelectAll(); coinControlUpdateLabels(); - Q_EMIT coinsSent(currentTransaction.getWtx()->GetHash()); } fNewRecipientAllowed = true; } @@ -526,7 +562,12 @@ void SendCoinsDialog::setBalance(const interfaces::WalletBalances& balances) { if(model && model->getOptionsModel()) { - ui->labelBalance->setText(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), balances.balance)); + CAmount balance = balances.balance; + if (model->privateKeysDisabled()) { + balance = balances.watch_only_balance; + ui->labelBalanceName->setText(tr("Watch-only balance:")); + } + ui->labelBalance->setText(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), balance)); } } @@ -611,6 +652,9 @@ void SendCoinsDialog::useAvailableBalance(SendCoinsEntry* entry) coin_control = *CoinControlDialog::coinControl(); } + // Include watch-only for wallets without private key + coin_control.fAllowWatchOnly = model->privateKeysDisabled(); + // Calculate available amount to send. CAmount amount = model->wallet().getAvailableBalance(coin_control); for (int i = 0; i < ui->entries->count(); ++i) { @@ -663,6 +707,8 @@ void SendCoinsDialog::updateCoinControlState(CCoinControl& ctrl) // Either custom fee will be used or if not selected, the confirmation target from dropdown box ctrl.m_confirm_target = getConfTargetForIndex(ui->confTargetSelector->currentIndex()); ctrl.m_signal_bip125_rbf = ui->optInRBF->isChecked(); + // Include watch-only for wallets without private key + ctrl.fAllowWatchOnly = model->privateKeysDisabled(); } void SendCoinsDialog::updateSmartFeeLabel() @@ -870,8 +916,8 @@ void SendCoinsDialog::coinControlUpdateLabels() } } -SendConfirmationDialog::SendConfirmationDialog(const QString& title, const QString& text, const QString& informative_text, const QString& detailed_text, int _secDelay, QWidget* parent) - : QMessageBox(parent), secDelay(_secDelay) +SendConfirmationDialog::SendConfirmationDialog(const QString& title, const QString& text, const QString& informative_text, const QString& detailed_text, int _secDelay, const QString& _confirmButtonText, QWidget* parent) + : QMessageBox(parent), secDelay(_secDelay), confirmButtonText(_confirmButtonText) { setIcon(QMessageBox::Question); setWindowTitle(title); // On macOS, the window title is ignored (as required by the macOS Guidelines). @@ -908,11 +954,11 @@ void SendConfirmationDialog::updateYesButton() if(secDelay > 0) { yesButton->setEnabled(false); - yesButton->setText(tr("Send") + " (" + QString::number(secDelay) + ")"); + yesButton->setText(confirmButtonText + " (" + QString::number(secDelay) + ")"); } else { yesButton->setEnabled(true); - yesButton->setText(tr("Send")); + yesButton->setText(confirmButtonText); } } diff --git a/src/qt/sendcoinsdialog.h b/src/qt/sendcoinsdialog.h index c6c1816877..ccd8494613 100644 --- a/src/qt/sendcoinsdialog.h +++ b/src/qt/sendcoinsdialog.h @@ -108,7 +108,7 @@ class SendConfirmationDialog : public QMessageBox Q_OBJECT public: - SendConfirmationDialog(const QString& title, const QString& text, const QString& informative_text = "", const QString& detailed_text = "", int secDelay = SEND_CONFIRM_DELAY, QWidget* parent = nullptr); + SendConfirmationDialog(const QString& title, const QString& text, const QString& informative_text = "", const QString& detailed_text = "", int secDelay = SEND_CONFIRM_DELAY, const QString& confirmText = "Send", QWidget* parent = nullptr); int exec(); private Q_SLOTS: @@ -119,6 +119,7 @@ private: QAbstractButton *yesButton; QTimer countDownTimer; int secDelay; + QString confirmButtonText; }; #endif // BITCOIN_QT_SENDCOINSDIALOG_H diff --git a/src/qt/sendcoinsentry.cpp b/src/qt/sendcoinsentry.cpp index be417655b4..ad37e09114 100644 --- a/src/qt/sendcoinsentry.cpp +++ b/src/qt/sendcoinsentry.cpp @@ -14,6 +14,7 @@ #include <qt/guiutil.h> #include <qt/optionsmodel.h> #include <qt/platformstyle.h> +#include <qt/walletmodel.h> #include <QApplication> #include <QClipboard> diff --git a/src/qt/sendcoinsentry.h b/src/qt/sendcoinsentry.h index 42e2217130..aa69d30f99 100644 --- a/src/qt/sendcoinsentry.h +++ b/src/qt/sendcoinsentry.h @@ -5,13 +5,17 @@ #ifndef BITCOIN_QT_SENDCOINSENTRY_H #define BITCOIN_QT_SENDCOINSENTRY_H -#include <qt/walletmodel.h> +#include <qt/sendcoinsrecipient.h> #include <QStackedWidget> class WalletModel; class PlatformStyle; +namespace interfaces { +class Node; +} // namespace interfaces + namespace Ui { class SendCoinsEntry; } diff --git a/src/qt/sendcoinsrecipient.h b/src/qt/sendcoinsrecipient.h new file mode 100644 index 0000000000..12279fab64 --- /dev/null +++ b/src/qt/sendcoinsrecipient.h @@ -0,0 +1,74 @@ +// Copyright (c) 2011-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_QT_SENDCOINSRECIPIENT_H +#define BITCOIN_QT_SENDCOINSRECIPIENT_H + +#if defined(HAVE_CONFIG_H) +#include <config/bitcoin-config.h> +#endif + +#include <amount.h> +#include <serialize.h> + +#include <string> + +#include <QString> + +class SendCoinsRecipient +{ +public: + explicit SendCoinsRecipient() : amount(0), fSubtractFeeFromAmount(false), nVersion(SendCoinsRecipient::CURRENT_VERSION) { } + explicit SendCoinsRecipient(const QString &addr, const QString &_label, const CAmount& _amount, const QString &_message): + address(addr), label(_label), amount(_amount), message(_message), fSubtractFeeFromAmount(false), nVersion(SendCoinsRecipient::CURRENT_VERSION) {} + + // If from an unauthenticated payment request, this is used for storing + // the addresses, e.g. address-A<br />address-B<br />address-C. + // Info: As we don't need to process addresses in here when using + // payment requests, we can abuse it for displaying an address list. + // Todo: This is a hack, should be replaced with a cleaner solution! + QString address; + QString label; + CAmount amount; + // If from a payment request, this is used for storing the memo + QString message; + // Keep the payment request around as a serialized string to ensure + // load/store is lossless. + std::string sPaymentRequest; + // Empty if no authentication or invalid signature/cert/etc. + QString authenticatedMerchant; + + bool fSubtractFeeFromAmount; // memory only + + static const int CURRENT_VERSION = 1; + int nVersion; + + ADD_SERIALIZE_METHODS; + + template <typename Stream, typename Operation> + inline void SerializationOp(Stream& s, Operation ser_action) { + std::string sAddress = address.toStdString(); + std::string sLabel = label.toStdString(); + std::string sMessage = message.toStdString(); + std::string sAuthenticatedMerchant = authenticatedMerchant.toStdString(); + + READWRITE(this->nVersion); + READWRITE(sAddress); + READWRITE(sLabel); + READWRITE(amount); + READWRITE(sMessage); + READWRITE(sPaymentRequest); + READWRITE(sAuthenticatedMerchant); + + if (ser_action.ForRead()) + { + address = QString::fromStdString(sAddress); + label = QString::fromStdString(sLabel); + message = QString::fromStdString(sMessage); + authenticatedMerchant = QString::fromStdString(sAuthenticatedMerchant); + } + } +}; + +#endif // BITCOIN_QT_SENDCOINSRECIPIENT_H diff --git a/src/qt/signverifymessagedialog.cpp b/src/qt/signverifymessagedialog.cpp index 1d0e1323bc..9d250bcb83 100644 --- a/src/qt/signverifymessagedialog.cpp +++ b/src/qt/signverifymessagedialog.cpp @@ -136,7 +136,7 @@ void SignVerifyMessageDialog::on_signMessageButton_SM_clicked() } CKey key; - if (!model->wallet().getPrivKey(CKeyID(*pkhash), key)) + if (!model->wallet().getPrivKey(GetScriptForDestination(destination), CKeyID(*pkhash), key)) { ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }"); ui->statusLabel_SM->setText(tr("Private key for the entered address is not available.")); diff --git a/src/qt/test/rpcnestedtests.cpp b/src/qt/test/rpcnestedtests.cpp index 971d9f4a7c..374fc9b59b 100644 --- a/src/qt/test/rpcnestedtests.cpp +++ b/src/qt/test/rpcnestedtests.cpp @@ -32,7 +32,6 @@ void RPCNestedTests::rpcNestedTests() // do some test setup // could be moved to a more generic place when we add more tests on QT level tableRPC.appendCommand("rpcNestedTest", &vRPCCommands[0]); - //mempool.setSanityCheck(1.0); TestingSetup test; diff --git a/src/qt/test/wallettests.cpp b/src/qt/test/wallettests.cpp index 980de711db..dfd56511ea 100644 --- a/src/qt/test/wallettests.cpp +++ b/src/qt/test/wallettests.cpp @@ -170,6 +170,16 @@ void TestGUI(interfaces::Node& node) sendCoinsDialog.setModel(&walletModel); transactionView.setModel(&walletModel); + { + // Check balance in send dialog + QLabel* balanceLabel = sendCoinsDialog.findChild<QLabel*>("labelBalance"); + QString balanceText = balanceLabel->text(); + int unit = walletModel.getOptionsModel()->getDisplayUnit(); + CAmount balance = walletModel.wallet().getBalance(); + QString balanceComparison = BitcoinUnits::formatWithUnit(unit, balance, false, BitcoinUnits::separatorAlways); + QCOMPARE(balanceText, balanceComparison); + } + // Send two transactions, and verify they are added to transaction list. TransactionTableModel* transactionTableModel = walletModel.getTransactionTableModel(); QCOMPARE(transactionTableModel->rowCount({}), 105); diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index 318b0756c7..9a93798aef 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -15,11 +15,12 @@ #include <consensus/consensus.h> #include <interfaces/node.h> +#include <interfaces/wallet.h> #include <key_io.h> -#include <validation.h> +#include <policy/policy.h> #include <script/script.h> #include <util/system.h> -#include <policy/policy.h> +#include <validation.h> #include <wallet/ismine.h> #include <stdint.h> diff --git a/src/qt/utilitydialog.cpp b/src/qt/utilitydialog.cpp index 095c98d26f..220e41b383 100644 --- a/src/qt/utilitydialog.cpp +++ b/src/qt/utilitydialog.cpp @@ -34,14 +34,6 @@ HelpMessageDialog::HelpMessageDialog(interfaces::Node& node, QWidget *parent, bo ui->setupUi(this); QString version = QString{PACKAGE_NAME} + " " + tr("version") + " " + QString::fromStdString(FormatFullVersion()); - /* On x86 add a bit specifier to the version so that users can distinguish between - * 32 and 64 bit builds. On other architectures, 32/64 bit may be more ambiguous. - */ -#if defined(__x86_64__) - version += " " + tr("(%1-bit)").arg(64); -#elif defined(__i386__ ) - version += " " + tr("(%1-bit)").arg(32); -#endif if (about) { diff --git a/src/qt/walletcontroller.cpp b/src/qt/walletcontroller.cpp index 4c253f8ddd..7413a1f09e 100644 --- a/src/qt/walletcontroller.cpp +++ b/src/qt/walletcontroller.cpp @@ -2,17 +2,18 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include <qt/walletcontroller.h> + #include <qt/askpassphrasedialog.h> #include <qt/createwalletdialog.h> #include <qt/guiconstants.h> #include <qt/guiutil.h> -#include <qt/walletcontroller.h> - -#include <wallet/wallet.h> +#include <qt/walletmodel.h> #include <interfaces/handler.h> #include <interfaces/node.h> #include <util/string.h> +#include <wallet/wallet.h> #include <algorithm> diff --git a/src/qt/walletcontroller.h b/src/qt/walletcontroller.h index e50dd5c7eb..956245775e 100644 --- a/src/qt/walletcontroller.h +++ b/src/qt/walletcontroller.h @@ -5,7 +5,7 @@ #ifndef BITCOIN_QT_WALLETCONTROLLER_H #define BITCOIN_QT_WALLETCONTROLLER_H -#include <qt/walletmodel.h> +#include <qt/sendcoinsrecipient.h> #include <support/allocators/secure.h> #include <sync.h> @@ -23,10 +23,12 @@ class OptionsModel; class PlatformStyle; +class WalletModel; namespace interfaces { class Handler; class Node; +class Wallet; } // namespace interfaces class AskPassphraseDialog; diff --git a/src/qt/walletframe.cpp b/src/qt/walletframe.cpp index d7f0617315..4b2b475883 100644 --- a/src/qt/walletframe.cpp +++ b/src/qt/walletframe.cpp @@ -61,11 +61,6 @@ void WalletFrame::addWallet(WalletModel *walletModel) walletStack->addWidget(walletView); mapWalletViews[walletModel] = walletView; - // Ensure a walletView is able to show the main window - connect(walletView, &WalletView::showNormalIfMinimized, [this]{ - gui->showNormalIfMinimized(); - }); - connect(walletView, &WalletView::outOfSyncWarningClicked, this, &WalletFrame::outOfSyncWarningClicked); } diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index 33801d3907..fb92e29f21 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -183,7 +183,7 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact std::string strFailReason; auto& newTx = transaction.getWtx(); - newTx = m_wallet->createTransaction(vecSend, coinControl, true /* sign */, nChangePosRet, nFeeRequired, strFailReason); + newTx = m_wallet->createTransaction(vecSend, coinControl, !privateKeysDisabled() /* sign */, nChangePosRet, nFeeRequired, strFailReason); transaction.setTransactionFee(nFeeRequired); if (fSubtractFeeFromAmount && newTx) transaction.reassignAmounts(nChangePosRet); diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h index a873519a34..8087356f5e 100644 --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -9,9 +9,7 @@ #include <config/bitcoin-config.h> #endif -#include <amount.h> #include <key.h> -#include <serialize.h> #include <script/standard.h> #include <qt/walletmodeltransaction.h> @@ -29,6 +27,7 @@ class AddressTableModel; class OptionsModel; class PlatformStyle; class RecentRequestsTableModel; +class SendCoinsRecipient; class TransactionTableModel; class WalletModelTransaction; @@ -47,61 +46,6 @@ QT_BEGIN_NAMESPACE class QTimer; QT_END_NAMESPACE -class SendCoinsRecipient -{ -public: - explicit SendCoinsRecipient() : amount(0), fSubtractFeeFromAmount(false), nVersion(SendCoinsRecipient::CURRENT_VERSION) { } - explicit SendCoinsRecipient(const QString &addr, const QString &_label, const CAmount& _amount, const QString &_message): - address(addr), label(_label), amount(_amount), message(_message), fSubtractFeeFromAmount(false), nVersion(SendCoinsRecipient::CURRENT_VERSION) {} - - // If from an unauthenticated payment request, this is used for storing - // the addresses, e.g. address-A<br />address-B<br />address-C. - // Info: As we don't need to process addresses in here when using - // payment requests, we can abuse it for displaying an address list. - // Todo: This is a hack, should be replaced with a cleaner solution! - QString address; - QString label; - CAmount amount; - // If from a payment request, this is used for storing the memo - QString message; - // Keep the payment request around as a serialized string to ensure - // load/store is lossless. - std::string sPaymentRequest; - // Empty if no authentication or invalid signature/cert/etc. - QString authenticatedMerchant; - - bool fSubtractFeeFromAmount; // memory only - - static const int CURRENT_VERSION = 1; - int nVersion; - - ADD_SERIALIZE_METHODS; - - template <typename Stream, typename Operation> - inline void SerializationOp(Stream& s, Operation ser_action) { - std::string sAddress = address.toStdString(); - std::string sLabel = label.toStdString(); - std::string sMessage = message.toStdString(); - std::string sAuthenticatedMerchant = authenticatedMerchant.toStdString(); - - READWRITE(this->nVersion); - READWRITE(sAddress); - READWRITE(sLabel); - READWRITE(amount); - READWRITE(sMessage); - READWRITE(sPaymentRequest); - READWRITE(sAuthenticatedMerchant); - - if (ser_action.ForRead()) - { - address = QString::fromStdString(sAddress); - label = QString::fromStdString(sLabel); - message = QString::fromStdString(sMessage); - authenticatedMerchant = QString::fromStdString(sAuthenticatedMerchant); - } - } -}; - /** Interface to Bitcoin wallet from Qt view code. */ class WalletModel : public QObject { diff --git a/src/qt/walletmodeltransaction.h b/src/qt/walletmodeltransaction.h index 242ba13897..9e5d285e8c 100644 --- a/src/qt/walletmodeltransaction.h +++ b/src/qt/walletmodeltransaction.h @@ -5,7 +5,8 @@ #ifndef BITCOIN_QT_WALLETMODELTRANSACTION_H #define BITCOIN_QT_WALLETMODELTRANSACTION_H -#include <qt/walletmodel.h> +#include <primitives/transaction.h> +#include <qt/sendcoinsrecipient.h> #include <amount.h> diff --git a/src/qt/walletview.h b/src/qt/walletview.h index e29c4c52f5..8d5a301cdb 100644 --- a/src/qt/walletview.h +++ b/src/qt/walletview.h @@ -115,8 +115,6 @@ public Q_SLOTS: void requestedSyncWarningInfo(); Q_SIGNALS: - /** Signal that we want to show the main window */ - void showNormalIfMinimized(); /** Fired when a message should be reported to the user */ void message(const QString &title, const QString &message, unsigned int style); /** Encryption status of wallet changed */ diff --git a/src/random.cpp b/src/random.cpp index 48d20d7d72..09777237c2 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -5,19 +5,23 @@ #include <random.h> +#include <compat/cpuid.h> +#include <crypto/sha256.h> #include <crypto/sha512.h> #include <support/cleanse.h> #ifdef WIN32 #include <compat.h> // for Windows API #include <wincrypt.h> #endif -#include <logging.h> // for LogPrint() -#include <sync.h> // for WAIT_LOCK +#include <logging.h> // for LogPrintf() +#include <sync.h> // for Mutex #include <util/time.h> // for GetTime() #include <stdlib.h> #include <thread> +#include <randomenv.h> + #include <support/allocators/secure.h> #ifndef WIN32 @@ -40,15 +44,6 @@ #include <sys/sysctl.h> #endif - -#if defined(__x86_64__) || defined(__amd64__) || defined(__i386__) -#include <cpuid.h> -#endif - -#include <openssl/err.h> -#include <openssl/rand.h> -#include <openssl/conf.h> - [[noreturn]] static void RandFailure() { LogPrintf("Failed to read randomness, aborting\n"); @@ -75,7 +70,7 @@ static inline int64_t GetPerformanceCounter() noexcept #endif } -#if defined(__x86_64__) || defined(__amd64__) || defined(__i386__) +#ifdef HAVE_GETCPUID static bool g_rdrand_supported = false; static bool g_rdseed_supported = false; static constexpr uint32_t CPUID_F1_ECX_RDRAND = 0x40000000; @@ -86,15 +81,6 @@ static_assert(CPUID_F1_ECX_RDRAND == bit_RDRND, "Unexpected value for bit_RDRND" #ifdef bit_RDSEED static_assert(CPUID_F7_EBX_RDSEED == bit_RDSEED, "Unexpected value for bit_RDSEED"); #endif -static void inline GetCPUID(uint32_t leaf, uint32_t subleaf, uint32_t& a, uint32_t& b, uint32_t& c, uint32_t& d) -{ - // We can't use __get_cpuid as it doesn't support subleafs. -#ifdef __GNUC__ - __cpuid_count(leaf, subleaf, a, b, c, d); -#else - __asm__ ("cpuid" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(leaf), "2"(subleaf)); -#endif -} static void InitHardwareRand() { @@ -263,44 +249,6 @@ static void Strengthen(const unsigned char (&seed)[32], int microseconds, CSHA51 memory_cleanse(buffer, sizeof(buffer)); } -static void RandAddSeedPerfmon(CSHA512& hasher) -{ -#ifdef WIN32 - // Don't need this on Linux, OpenSSL automatically uses /dev/urandom - // Seed with the entire set of perfmon data - - // This can take up to 2 seconds, so only do it every 10 minutes - static int64_t nLastPerfmon; - if (GetTime() < nLastPerfmon + 10 * 60) - return; - nLastPerfmon = GetTime(); - - std::vector<unsigned char> vData(250000, 0); - long ret = 0; - unsigned long nSize = 0; - const size_t nMaxSize = 10000000; // Bail out at more than 10MB of performance data - while (true) { - nSize = vData.size(); - ret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "Global", nullptr, nullptr, vData.data(), &nSize); - if (ret != ERROR_MORE_DATA || vData.size() >= nMaxSize) - break; - vData.resize(std::max((vData.size() * 3) / 2, nMaxSize)); // Grow size of buffer exponentially - } - RegCloseKey(HKEY_PERFORMANCE_DATA); - if (ret == ERROR_SUCCESS) { - hasher.Write(vData.data(), nSize); - memory_cleanse(vData.data(), nSize); - } else { - // Performance data is only a best-effort attempt at improving the - // situation when the OS randomness (and other sources) aren't - // adequate. As a result, failure to read it is isn't considered critical, - // so we don't call RandFailure(). - // TODO: Add logging when the logger is made functional before global - // constructors have been invoked. - } -#endif -} - #ifndef WIN32 /** Fallback: get 32 bytes of system entropy from /dev/urandom. The most * compatible way to get cryptographic randomness on UNIX-ish platforms. @@ -396,8 +344,6 @@ void GetOSRand(unsigned char *ent32) #endif } -void LockingCallbackOpenSSL(int mode, int i, const char* file, int line); - namespace { class RNGState { @@ -413,31 +359,15 @@ class RNGState { unsigned char m_state[32] GUARDED_BY(m_mutex) = {0}; uint64_t m_counter GUARDED_BY(m_mutex) = 0; bool m_strongly_seeded GUARDED_BY(m_mutex) = false; - std::unique_ptr<Mutex[]> m_mutex_openssl; public: RNGState() noexcept { InitHardwareRand(); - - // Init OpenSSL library multithreading support - m_mutex_openssl.reset(new Mutex[CRYPTO_num_locks()]); - CRYPTO_set_locking_callback(LockingCallbackOpenSSL); - - // OpenSSL can optionally load a config file which lists optional loadable modules and engines. - // We don't use them so we don't require the config. However some of our libs may call functions - // which attempt to load the config file, possibly resulting in an exit() or crash if it is missing - // or corrupt. Explicitly tell OpenSSL not to try to load the file. The result for our libs will be - // that the config appears to have been loaded and there are no modules/engines available. - OPENSSL_no_config(); } ~RNGState() { - // Securely erase the memory used by the OpenSSL PRNG - RAND_cleanup(); - // Shutdown OpenSSL library multithreading support - CRYPTO_set_locking_callback(nullptr); } /** Extract up to 32 bytes of entropy from the RNG state, mixing in new entropy from hasher. @@ -473,8 +403,6 @@ public: memory_cleanse(buf, 64); return ret; } - - Mutex& GetOpenSSLMutex(int i) { return m_mutex_openssl[i]; } }; RNGState& GetRNGState() noexcept @@ -486,17 +414,6 @@ RNGState& GetRNGState() noexcept } } -void LockingCallbackOpenSSL(int mode, int i, const char* file, int line) NO_THREAD_SAFETY_ANALYSIS -{ - RNGState& rng = GetRNGState(); - - if (mode & CRYPTO_LOCK) { - rng.GetOpenSSLMutex(i).lock(); - } else { - rng.GetOpenSSLMutex(i).unlock(); - } -} - /* A note on the use of noexcept in the seeding functions below: * * None of the RNG code should ever throw any exception, with the sole exception @@ -533,6 +450,23 @@ static void SeedFast(CSHA512& hasher) noexcept SeedTimestamp(hasher); } +// We use only SHA256 for the events hashing to get the ASM speedups we have for SHA256, +// since we want it to be fast as network peers may be able to trigger it repeatedly. +static Mutex events_mutex; +static CSHA256 events_hasher; +static void SeedEvents(CSHA512& hasher) +{ + LOCK(events_mutex); + + unsigned char events_hash[32]; + events_hasher.Finalize(events_hash); + hasher.Write(events_hash, 32); + + // Re-initialize the hasher with the finalized state to use later. + events_hasher.Reset(); + events_hasher.Write(events_hash, 32); +} + static void SeedSlow(CSHA512& hasher) noexcept { unsigned char buffer[32]; @@ -544,9 +478,8 @@ static void SeedSlow(CSHA512& hasher) noexcept GetOSRand(buffer); hasher.Write(buffer, sizeof(buffer)); - // OpenSSL RNG (for now) - RAND_bytes(buffer, sizeof(buffer)); - hasher.Write(buffer, sizeof(buffer)); + // Add the events hasher into the mix + SeedEvents(hasher); // High-precision timestamp. // @@ -556,22 +489,16 @@ static void SeedSlow(CSHA512& hasher) noexcept } /** Extract entropy from rng, strengthen it, and feed it into hasher. */ -static void SeedStrengthen(CSHA512& hasher, RNGState& rng) noexcept +static void SeedStrengthen(CSHA512& hasher, RNGState& rng, int microseconds) noexcept { - static std::atomic<int64_t> last_strengthen{0}; - int64_t last_time = last_strengthen.load(); - int64_t current_time = GetTimeMicros(); - if (current_time > last_time + 60000000) { // Only run once a minute - // Generate 32 bytes of entropy from the RNG, and a copy of the entropy already in hasher. - unsigned char strengthen_seed[32]; - rng.MixExtract(strengthen_seed, sizeof(strengthen_seed), CSHA512(hasher), false); - // Strengthen it for 10ms (100ms on first run), and feed it into hasher. - Strengthen(strengthen_seed, last_time == 0 ? 100000 : 10000, hasher); - last_strengthen = current_time; - } + // Generate 32 bytes of entropy from the RNG, and a copy of the entropy already in hasher. + unsigned char strengthen_seed[32]; + rng.MixExtract(strengthen_seed, sizeof(strengthen_seed), CSHA512(hasher), false); + // Strengthen the seed, and feed it into hasher. + Strengthen(strengthen_seed, microseconds, hasher); } -static void SeedSleep(CSHA512& hasher, RNGState& rng) +static void SeedPeriodic(CSHA512& hasher, RNGState& rng) { // Everything that the 'fast' seeder includes SeedFast(hasher); @@ -579,17 +506,16 @@ static void SeedSleep(CSHA512& hasher, RNGState& rng) // High-precision timestamp SeedTimestamp(hasher); - // Sleep for 1ms - MilliSleep(1); + // Add the events hasher into the mix + SeedEvents(hasher); - // High-precision timestamp after sleeping (as we commit to both the time before and after, this measures the delay) - SeedTimestamp(hasher); - - // Windows performance monitor data (once every 10 minutes) - RandAddSeedPerfmon(hasher); + // Dynamic environment data (performance monitoring, ...) + auto old_size = hasher.Size(); + RandAddDynamicEnv(hasher); + LogPrintf("Feeding %i bytes of dynamic environment data into RNG\n", hasher.Size() - old_size); - // Strengthen every minute - SeedStrengthen(hasher, rng); + // Strengthen for 10 ms + SeedStrengthen(hasher, rng, 10000); } static void SeedStartup(CSHA512& hasher, RNGState& rng) noexcept @@ -600,17 +526,22 @@ static void SeedStartup(CSHA512& hasher, RNGState& rng) noexcept // Everything that the 'slow' seeder includes. SeedSlow(hasher); - // Windows performance monitor data. - RandAddSeedPerfmon(hasher); + // Dynamic environment data (performance monitoring, ...) + auto old_size = hasher.Size(); + RandAddDynamicEnv(hasher); + + // Static environment data + RandAddStaticEnv(hasher); + LogPrintf("Feeding %i bytes of environment data into RNG\n", hasher.Size() - old_size); - // Strengthen - SeedStrengthen(hasher, rng); + // Strengthen for 100 ms + SeedStrengthen(hasher, rng, 100000); } enum class RNGLevel { FAST, //!< Automatically called by GetRandBytes SLOW, //!< Automatically called by GetStrongRandBytes - SLEEP, //!< Called by RandAddSeedSleep() + PERIODIC, //!< Called by RandAddPeriodic() }; static void ProcRand(unsigned char* out, int num, RNGLevel level) @@ -628,8 +559,8 @@ static void ProcRand(unsigned char* out, int num, RNGLevel level) case RNGLevel::SLOW: SeedSlow(hasher); break; - case RNGLevel::SLEEP: - SeedSleep(hasher, rng); + case RNGLevel::PERIODIC: + SeedPeriodic(hasher, rng); break; } @@ -640,19 +571,20 @@ static void ProcRand(unsigned char* out, int num, RNGLevel level) SeedStartup(startup_hasher, rng); rng.MixExtract(out, num, std::move(startup_hasher), true); } - - // For anything but the 'fast' level, feed the resulting RNG output (after an additional hashing step) back into OpenSSL. - if (level != RNGLevel::FAST) { - unsigned char buf[64]; - CSHA512().Write(out, num).Finalize(buf); - RAND_add(buf, sizeof(buf), num); - memory_cleanse(buf, 64); - } } void GetRandBytes(unsigned char* buf, int num) noexcept { ProcRand(buf, num, RNGLevel::FAST); } void GetStrongRandBytes(unsigned char* buf, int num) noexcept { ProcRand(buf, num, RNGLevel::SLOW); } -void RandAddSeedSleep() { ProcRand(nullptr, 0, RNGLevel::SLEEP); } +void RandAddPeriodic() { ProcRand(nullptr, 0, RNGLevel::PERIODIC); } + +void RandAddEvent(const uint32_t event_info) { + LOCK(events_mutex); + events_hasher.Write((const unsigned char *)&event_info, sizeof(event_info)); + // Get the low four bytes of the performance counter. This translates to roughly the + // subsecond part. + uint32_t perfcounter = (GetPerformanceCounter() & 0xffffffff); + events_hasher.Write((const unsigned char*)&perfcounter, sizeof(perfcounter)); +} bool g_mock_deterministic_tests{false}; @@ -716,7 +648,7 @@ bool Random_SanityCheck() uint64_t start = GetPerformanceCounter(); /* This does not measure the quality of randomness, but it does test that - * OSRandom() overwrites all 32 bytes of the output given a maximum + * GetOSRand() overwrites all 32 bytes of the output given a maximum * number of tries. */ static const ssize_t MAX_TRIES = 1024; diff --git a/src/random.h b/src/random.h index 9d1f751773..b6e70fcb1f 100644 --- a/src/random.h +++ b/src/random.h @@ -35,7 +35,6 @@ * that fast seeding includes, but additionally: * - OS entropy (/dev/urandom, getrandom(), ...). The application will terminate if * this entropy source fails. - * - Bytes from OpenSSL's RNG (which itself may be seeded from various sources) * - Another high-precision timestamp (indirectly committing to a benchmark of all the * previous sources). * These entropy sources are slower, but designed to make sure the RNG state contains @@ -52,7 +51,6 @@ * sources used in the 'slow' seeder are included, but also: * - 256 bits from the hardware RNG (rdseed or rdrand) when available. * - (On Windows) Performance monitoring data from the OS. - * - (On Windows) Through OpenSSL, the screen contents. * - Strengthen the entropy for 100 ms using repeated SHA512. * * When mixing in new entropy, H = SHA512(entropy || old_rng_state) is computed, and @@ -85,11 +83,19 @@ uint256 GetRandHash() noexcept; void GetStrongRandBytes(unsigned char* buf, int num) noexcept; /** - * Sleep for 1ms, gather entropy from various sources, and feed them to the PRNG state. + * Gather entropy from various expensive sources, and feed them to the PRNG state. * * Thread-safe. */ -void RandAddSeedSleep(); +void RandAddPeriodic(); + +/** + * Gathers entropy from the low bits of the time at which events occur. Should + * be called with a uint32_t describing the event at the time an event occurs. + * + * Thread-safe. + */ +void RandAddEvent(const uint32_t event_info); /** * Fast randomness source. This is seeded once with secure random data, but diff --git a/src/randomenv.cpp b/src/randomenv.cpp new file mode 100644 index 0000000000..6992c720ff --- /dev/null +++ b/src/randomenv.cpp @@ -0,0 +1,518 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// 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. + +#if defined(HAVE_CONFIG_H) +#include <config/bitcoin-config.h> +#endif + +#include <randomenv.h> + +#include <clientversion.h> +#include <compat/cpuid.h> +#include <crypto/sha512.h> +#include <support/cleanse.h> +#include <util/time.h> // for GetTime() +#ifdef WIN32 +#include <compat.h> // for Windows API +#endif + +#include <algorithm> +#include <atomic> +#include <chrono> +#include <climits> +#include <thread> +#include <vector> + +#include <stdint.h> +#include <string.h> +#ifndef WIN32 +#include <sys/types.h> // must go before a number of other headers +#include <fcntl.h> +#include <netinet/in.h> +#include <sys/resource.h> +#include <sys/socket.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <sys/utsname.h> +#include <unistd.h> +#endif +#ifdef __MACH__ +#include <mach/clock.h> +#include <mach/mach.h> +#include <mach/mach_time.h> +#endif +#if HAVE_DECL_GETIFADDRS +#include <ifaddrs.h> +#endif +#if HAVE_SYSCTL +#include <sys/sysctl.h> +#if HAVE_VM_VM_PARAM_H +#include <vm/vm_param.h> +#endif +#if HAVE_SYS_RESOURCES_H +#include <sys/resources.h> +#endif +#if HAVE_SYS_VMMETER_H +#include <sys/vmmeter.h> +#endif +#endif +#ifdef __linux__ +#include <sys/auxv.h> +#endif + +//! Necessary on some platforms +extern char** environ; + +namespace { + +void RandAddSeedPerfmon(CSHA512& hasher) +{ +#ifdef WIN32 + // Seed with the entire set of perfmon data + + // This can take up to 2 seconds, so only do it every 10 minutes + static std::atomic<std::chrono::seconds> last_perfmon{std::chrono::seconds{0}}; + auto last_time = last_perfmon.load(); + auto current_time = GetTime<std::chrono::seconds>(); + if (current_time < last_time + std::chrono::minutes{10}) return; + last_perfmon = current_time; + + std::vector<unsigned char> vData(250000, 0); + long ret = 0; + unsigned long nSize = 0; + const size_t nMaxSize = 10000000; // Bail out at more than 10MB of performance data + while (true) { + nSize = vData.size(); + ret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "Global", nullptr, nullptr, vData.data(), &nSize); + if (ret != ERROR_MORE_DATA || vData.size() >= nMaxSize) + break; + vData.resize(std::max((vData.size() * 3) / 2, nMaxSize)); // Grow size of buffer exponentially + } + RegCloseKey(HKEY_PERFORMANCE_DATA); + if (ret == ERROR_SUCCESS) { + hasher.Write(vData.data(), nSize); + memory_cleanse(vData.data(), nSize); + } else { + // Performance data is only a best-effort attempt at improving the + // situation when the OS randomness (and other sources) aren't + // adequate. As a result, failure to read it is isn't considered critical, + // so we don't call RandFailure(). + // TODO: Add logging when the logger is made functional before global + // constructors have been invoked. + } +#endif +} + +/** Helper to easily feed data into a CSHA512. + * + * Note that this does not serialize the passed object (like stream.h's << operators do). + * Its raw memory representation is used directly. + */ +template<typename T> +CSHA512& operator<<(CSHA512& hasher, const T& data) { + static_assert(!std::is_same<typename std::decay<T>::type, char*>::value, "Calling operator<<(CSHA512, char*) is probably not what you want"); + static_assert(!std::is_same<typename std::decay<T>::type, unsigned char*>::value, "Calling operator<<(CSHA512, unsigned char*) is probably not what you want"); + static_assert(!std::is_same<typename std::decay<T>::type, const char*>::value, "Calling operator<<(CSHA512, const char*) is probably not what you want"); + static_assert(!std::is_same<typename std::decay<T>::type, const unsigned char*>::value, "Calling operator<<(CSHA512, const unsigned char*) is probably not what you want"); + hasher.Write((const unsigned char*)&data, sizeof(data)); + return hasher; +} + +#ifndef WIN32 +void AddSockaddr(CSHA512& hasher, const struct sockaddr *addr) +{ + if (addr == nullptr) return; + switch (addr->sa_family) { + case AF_INET: + hasher.Write((const unsigned char*)addr, sizeof(sockaddr_in)); + break; + case AF_INET6: + hasher.Write((const unsigned char*)addr, sizeof(sockaddr_in6)); + break; + default: + hasher.Write((const unsigned char*)&addr->sa_family, sizeof(addr->sa_family)); + } +} + +void AddFile(CSHA512& hasher, const char *path) +{ + struct stat sb = {}; + int f = open(path, O_RDONLY); + size_t total = 0; + if (f != -1) { + unsigned char fbuf[4096]; + int n; + hasher.Write((const unsigned char*)&f, sizeof(f)); + if (fstat(f, &sb) == 0) hasher << sb; + do { + n = read(f, fbuf, sizeof(fbuf)); + if (n > 0) hasher.Write(fbuf, n); + total += n; + /* not bothering with EINTR handling. */ + } while (n == sizeof(fbuf) && total < 1048576); // Read only the first 1 Mbyte + close(f); + } +} + +void AddPath(CSHA512& hasher, const char *path) +{ + struct stat sb = {}; + if (stat(path, &sb) == 0) { + hasher.Write((const unsigned char*)path, strlen(path) + 1); + hasher << sb; + } +} +#endif + +#if HAVE_SYSCTL +template<int... S> +void AddSysctl(CSHA512& hasher) +{ + int CTL[sizeof...(S)] = {S...}; + unsigned char buffer[65536]; + size_t siz = 65536; + int ret = sysctl(CTL, sizeof...(S), buffer, &siz, nullptr, 0); + if (ret == 0 || (ret == -1 && errno == ENOMEM)) { + hasher << sizeof(CTL); + hasher.Write((const unsigned char*)CTL, sizeof(CTL)); + if (siz > sizeof(buffer)) siz = sizeof(buffer); + hasher << siz; + hasher.Write(buffer, siz); + } +} +#endif + +#ifdef HAVE_GETCPUID +void inline AddCPUID(CSHA512& hasher, uint32_t leaf, uint32_t subleaf, uint32_t& ax, uint32_t& bx, uint32_t& cx, uint32_t& dx) +{ + GetCPUID(leaf, subleaf, ax, bx, cx, dx); + hasher << leaf << subleaf << ax << bx << cx << dx; +} + +void AddAllCPUID(CSHA512& hasher) +{ + uint32_t ax, bx, cx, dx; + // Iterate over all standard leaves + AddCPUID(hasher, 0, 0, ax, bx, cx, dx); // Returns max leaf in ax + uint32_t max = ax; + for (uint32_t leaf = 1; leaf <= max && leaf <= 0xFF; ++leaf) { + uint32_t maxsub = 0; + for (uint32_t subleaf = 0; subleaf <= 0xFF; ++subleaf) { + AddCPUID(hasher, leaf, subleaf, ax, bx, cx, dx); + // Iterate subleafs for leaf values 4, 7, 11, 13 + if (leaf == 4) { + if ((ax & 0x1f) == 0) break; + } else if (leaf == 7) { + if (subleaf == 0) maxsub = ax; + if (subleaf == maxsub) break; + } else if (leaf == 11) { + if ((cx & 0xff00) == 0) break; + } else if (leaf == 13) { + if (ax == 0 && bx == 0 && cx == 0 && dx == 0) break; + } else { + // For any other leaf, stop after subleaf 0. + break; + } + } + } + // Iterate over all extended leaves + AddCPUID(hasher, 0x80000000, 0, ax, bx, cx, dx); // Returns max extended leaf in ax + uint32_t ext_max = ax; + for (uint32_t leaf = 0x80000001; leaf <= ext_max && leaf <= 0x800000FF; ++leaf) { + AddCPUID(hasher, leaf, 0, ax, bx, cx, dx); + } +} +#endif +} // namespace + +void RandAddDynamicEnv(CSHA512& hasher) +{ + RandAddSeedPerfmon(hasher); + + // Various clocks +#ifdef WIN32 + FILETIME ftime; + GetSystemTimeAsFileTime(&ftime); + hasher << ftime; +#else +# ifndef __MACH__ + // On non-MacOS systems, use various clock_gettime() calls. + struct timespec ts = {}; +# ifdef CLOCK_MONOTONIC + clock_gettime(CLOCK_MONOTONIC, &ts); + hasher << ts; +# endif +# ifdef CLOCK_REALTIME + clock_gettime(CLOCK_REALTIME, &ts); + hasher << ts; +# endif +# ifdef CLOCK_BOOTTIME + clock_gettime(CLOCK_BOOTTIME, &ts); + hasher << ts; +# endif +# else + // On MacOS use mach_absolute_time (number of CPU ticks since boot) as a replacement for CLOCK_MONOTONIC, + // and clock_get_time for CALENDAR_CLOCK as a replacement for CLOCK_REALTIME. + hasher << mach_absolute_time(); + // From https://gist.github.com/jbenet/1087739 + clock_serv_t cclock; + mach_timespec_t mts = {}; + if (host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock) == KERN_SUCCESS && clock_get_time(cclock, &mts) == KERN_SUCCESS) { + hasher << mts; + mach_port_deallocate(mach_task_self(), cclock); + } +# endif + // gettimeofday is available on all UNIX systems, but only has microsecond precision. + struct timeval tv = {}; + gettimeofday(&tv, nullptr); + hasher << tv; +#endif + // Probably redundant, but also use all the clocks C++11 provides: + hasher << std::chrono::system_clock::now().time_since_epoch().count(); + hasher << std::chrono::steady_clock::now().time_since_epoch().count(); + hasher << std::chrono::high_resolution_clock::now().time_since_epoch().count(); + +#ifndef WIN32 + // Current resource usage. + struct rusage usage = {}; + if (getrusage(RUSAGE_SELF, &usage) == 0) hasher << usage; +#endif + +#ifdef __linux__ + AddFile(hasher, "/proc/diskstats"); + AddFile(hasher, "/proc/vmstat"); + AddFile(hasher, "/proc/schedstat"); + AddFile(hasher, "/proc/zoneinfo"); + AddFile(hasher, "/proc/meminfo"); + AddFile(hasher, "/proc/softirqs"); + AddFile(hasher, "/proc/stat"); + AddFile(hasher, "/proc/self/schedstat"); + AddFile(hasher, "/proc/self/status"); +#endif + +#if HAVE_SYSCTL +# ifdef CTL_KERN +# if defined(KERN_PROC) && defined(KERN_PROC_ALL) + AddSysctl<CTL_KERN, KERN_PROC, KERN_PROC_ALL>(hasher); +# endif +# endif +# ifdef CTL_HW +# ifdef HW_DISKSTATS + AddSysctl<CTL_HW, HW_DISKSTATS>(hasher); +# endif +# endif +# ifdef CTL_VM +# ifdef VM_LOADAVG + AddSysctl<CTL_VM, VM_LOADAVG>(hasher); +# endif +# ifdef VM_TOTAL + AddSysctl<CTL_VM, VM_TOTAL>(hasher); +# endif +# ifdef VM_METER + AddSysctl<CTL_VM, VM_METER>(hasher); +# endif +# endif +#endif + + // Stack and heap location + void* addr = malloc(4097); + hasher << &addr << addr; + free(addr); +} + +void RandAddStaticEnv(CSHA512& hasher) +{ + // Some compile-time static properties + hasher << (CHAR_MIN < 0) << sizeof(void*) << sizeof(long) << sizeof(int); +#if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) + hasher << __GNUC__ << __GNUC_MINOR__ << __GNUC_PATCHLEVEL__; +#endif +#ifdef _MSC_VER + hasher << _MSC_VER; +#endif + hasher << __cplusplus; +#ifdef _XOPEN_VERSION + hasher << _XOPEN_VERSION; +#endif +#ifdef __VERSION__ + const char* COMPILER_VERSION = __VERSION__; + hasher.Write((const unsigned char*)COMPILER_VERSION, strlen(COMPILER_VERSION) + 1); +#endif + + // Bitcoin client version + hasher << CLIENT_VERSION; + +#ifdef __linux__ + // Information available through getauxval() +# ifdef AT_HWCAP + hasher << getauxval(AT_HWCAP); +# endif +# ifdef AT_HWCAP2 + hasher << getauxval(AT_HWCAP2); +# endif +# ifdef AT_RANDOM + const unsigned char* random_aux = (const unsigned char*)getauxval(AT_RANDOM); + if (random_aux) hasher.Write(random_aux, 16); +# endif +# ifdef AT_PLATFORM + const char* platform_str = (const char*)getauxval(AT_PLATFORM); + if (platform_str) hasher.Write((const unsigned char*)platform_str, strlen(platform_str) + 1); +# endif +# ifdef AT_EXECFN + const char* exec_str = (const char*)getauxval(AT_EXECFN); + if (exec_str) hasher.Write((const unsigned char*)exec_str, strlen(exec_str) + 1); +# endif +#endif // __linux__ + +#ifdef HAVE_GETCPUID + AddAllCPUID(hasher); +#endif + + // Memory locations + hasher << &hasher << &RandAddStaticEnv << &malloc << &errno << &environ; + + // Hostname + char hname[256]; + if (gethostname(hname, 256) == 0) { + hasher.Write((const unsigned char*)hname, strnlen(hname, 256)); + } + +#if HAVE_DECL_GETIFADDRS + // Network interfaces + struct ifaddrs *ifad = NULL; + getifaddrs(&ifad); + struct ifaddrs *ifit = ifad; + while (ifit != NULL) { + hasher.Write((const unsigned char*)&ifit, sizeof(ifit)); + hasher.Write((const unsigned char*)ifit->ifa_name, strlen(ifit->ifa_name) + 1); + hasher.Write((const unsigned char*)&ifit->ifa_flags, sizeof(ifit->ifa_flags)); + AddSockaddr(hasher, ifit->ifa_addr); + AddSockaddr(hasher, ifit->ifa_netmask); + AddSockaddr(hasher, ifit->ifa_dstaddr); + ifit = ifit->ifa_next; + } + freeifaddrs(ifad); +#endif + +#ifndef WIN32 + // UNIX kernel information + struct utsname name; + if (uname(&name) != -1) { + hasher.Write((const unsigned char*)&name.sysname, strlen(name.sysname) + 1); + hasher.Write((const unsigned char*)&name.nodename, strlen(name.nodename) + 1); + hasher.Write((const unsigned char*)&name.release, strlen(name.release) + 1); + hasher.Write((const unsigned char*)&name.version, strlen(name.version) + 1); + hasher.Write((const unsigned char*)&name.machine, strlen(name.machine) + 1); + } + + /* Path and filesystem provided data */ + AddPath(hasher, "/"); + AddPath(hasher, "."); + AddPath(hasher, "/tmp"); + AddPath(hasher, "/home"); + AddPath(hasher, "/proc"); +#ifdef __linux__ + AddFile(hasher, "/proc/cmdline"); + AddFile(hasher, "/proc/cpuinfo"); + AddFile(hasher, "/proc/version"); +#endif + AddFile(hasher, "/etc/passwd"); + AddFile(hasher, "/etc/group"); + AddFile(hasher, "/etc/hosts"); + AddFile(hasher, "/etc/resolv.conf"); + AddFile(hasher, "/etc/timezone"); + AddFile(hasher, "/etc/localtime"); +#endif + + // For MacOS/BSDs, gather data through sysctl instead of /proc. Not all of these + // will exist on every system. +#if HAVE_SYSCTL +# ifdef CTL_HW +# ifdef HW_MACHINE + AddSysctl<CTL_HW, HW_MACHINE>(hasher); +# endif +# ifdef HW_MODEL + AddSysctl<CTL_HW, HW_MODEL>(hasher); +# endif +# ifdef HW_NCPU + AddSysctl<CTL_HW, HW_NCPU>(hasher); +# endif +# ifdef HW_PHYSMEM + AddSysctl<CTL_HW, HW_PHYSMEM>(hasher); +# endif +# ifdef HW_USERMEM + AddSysctl<CTL_HW, HW_USERMEM>(hasher); +# endif +# ifdef HW_MACHINE_ARCH + AddSysctl<CTL_HW, HW_MACHINE_ARCH>(hasher); +# endif +# ifdef HW_REALMEM + AddSysctl<CTL_HW, HW_REALMEM>(hasher); +# endif +# ifdef HW_CPU_FREQ + AddSysctl<CTL_HW, HW_CPU_FREQ>(hasher); +# endif +# ifdef HW_BUS_FREQ + AddSysctl<CTL_HW, HW_BUS_FREQ>(hasher); +# endif +# ifdef HW_CACHELINE + AddSysctl<CTL_HW, HW_CACHELINE>(hasher); +# endif +# endif +# ifdef CTL_KERN +# ifdef KERN_BOOTFILE + AddSysctl<CTL_KERN, KERN_BOOTFILE>(hasher); +# endif +# ifdef KERN_BOOTTIME + AddSysctl<CTL_KERN, KERN_BOOTTIME>(hasher); +# endif +# ifdef KERN_CLOCKRATE + AddSysctl<CTL_KERN, KERN_CLOCKRATE>(hasher); +# endif +# ifdef KERN_HOSTID + AddSysctl<CTL_KERN, KERN_HOSTID>(hasher); +# endif +# ifdef KERN_HOSTUUID + AddSysctl<CTL_KERN, KERN_HOSTUUID>(hasher); +# endif +# ifdef KERN_HOSTNAME + AddSysctl<CTL_KERN, KERN_HOSTNAME>(hasher); +# endif +# ifdef KERN_OSRELDATE + AddSysctl<CTL_KERN, KERN_OSRELDATE>(hasher); +# endif +# ifdef KERN_OSRELEASE + AddSysctl<CTL_KERN, KERN_OSRELEASE>(hasher); +# endif +# ifdef KERN_OSREV + AddSysctl<CTL_KERN, KERN_OSREV>(hasher); +# endif +# ifdef KERN_OSTYPE + AddSysctl<CTL_KERN, KERN_OSTYPE>(hasher); +# endif +# ifdef KERN_POSIX1 + AddSysctl<CTL_KERN, KERN_OSREV>(hasher); +# endif +# ifdef KERN_VERSION + AddSysctl<CTL_KERN, KERN_VERSION>(hasher); +# endif +# endif +#endif + + // Env variables + if (environ) { + for (size_t i = 0; environ[i]; ++i) { + hasher.Write((const unsigned char*)environ[i], strlen(environ[i])); + } + } + + // Process, thread, user, session, group, ... ids. +#ifdef WIN32 + hasher << GetCurrentProcessId() << GetCurrentThreadId(); +#else + hasher << getpid() << getppid() << getsid(0) << getpgid(0) << getuid() << geteuid() << getgid() << getegid(); +#endif + hasher << std::this_thread::get_id(); +} diff --git a/src/randomenv.h b/src/randomenv.h new file mode 100644 index 0000000000..46cea6f6f2 --- /dev/null +++ b/src/randomenv.h @@ -0,0 +1,17 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// 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. + +#ifndef BITCOIN_RANDOMENV_H +#define BITCOIN_RANDOMENV_H + +#include <crypto/sha512.h> + +/** Gather non-cryptographic environment data that changes over time. */ +void RandAddDynamicEnv(CSHA512& hasher); + +/** Gather non-cryptographic environment data that does not change over time. */ +void RandAddStaticEnv(CSHA512& hasher); + +#endif diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 2f4b4412f5..946152d9aa 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -15,6 +15,7 @@ #include <hash.h> #include <index/blockfilterindex.h> #include <node/coinstats.h> +#include <node/context.h> #include <node/utxo_snapshot.h> #include <policy/feerate.h> #include <policy/policy.h> @@ -53,6 +54,15 @@ static Mutex cs_blockchange; static std::condition_variable cond_blockchange; static CUpdatedBlock latestblock; +CTxMemPool& EnsureMemPool() +{ + CHECK_NONFATAL(g_rpc_node); + if (!g_rpc_node->mempool) { + throw JSONRPCError(RPC_CLIENT_MEMPOOL_DISABLED, "Mempool disabled or instance not found"); + } + return *g_rpc_node->mempool; +} + /* Calculate the difficulty for a given block index. */ double GetDifficulty(const CBlockIndex* blockindex) diff --git a/src/rpc/blockchain.h b/src/rpc/blockchain.h index 8a1264f824..ccb3e39722 100644 --- a/src/rpc/blockchain.h +++ b/src/rpc/blockchain.h @@ -52,4 +52,6 @@ void CalculatePercentilesByWeight(CAmount result[NUM_GETBLOCKSTATS_PERCENTILES], //! direct way to pass in state to RPC methods without globals. extern NodeContext* g_rpc_node; +CTxMemPool& EnsureMemPool(); + #endif diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index ab22155651..85f9f1e8b7 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -375,9 +375,7 @@ static UniValue getblocktemplate(const JSONRPCRequest& request) " }\n" " ,...\n" " ],\n" - " \"coinbaseaux\" : { (json object) data that should be included in the coinbase's scriptSig content\n" - " \"flags\" : \"xx\" (string) key name is to be ignored, and value included in scriptSig\n" - " },\n" + " \"coinbaseaux\" : { ... }, (json object) data that should be included in the coinbase's scriptSig content\n" " \"coinbasevalue\" : n, (numeric) maximum allowable input to coinbase transaction, including the generation award and transaction fees (in satoshis)\n" " \"coinbasetxn\" : { ... }, (json object) information for coinbase transaction\n" " \"target\" : \"xxxx\", (string) The hash target\n" @@ -607,7 +605,6 @@ static UniValue getblocktemplate(const JSONRPCRequest& request) } UniValue aux(UniValue::VOBJ); - aux.pushKV("flags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end())); arith_uint256 hashTarget = arith_uint256().SetCompact(pblock->nBits); diff --git a/src/rpc/protocol.h b/src/rpc/protocol.h index ef6537e4ec..ca779497b9 100644 --- a/src/rpc/protocol.h +++ b/src/rpc/protocol.h @@ -63,6 +63,9 @@ enum RPCErrorCode RPC_CLIENT_INVALID_IP_OR_SUBNET = -30, //!< Invalid IP/Subnet RPC_CLIENT_P2P_DISABLED = -31, //!< No valid connection manager instance found + //! Chain errors + RPC_CLIENT_MEMPOOL_DISABLED = -33, //!< No mempool instance found + //! Wallet errors RPC_WALLET_ERROR = -4, //!< Unspecified problem with wallet (key not found etc.) RPC_WALLET_INSUFFICIENT_FUNDS = -6, //!< Not enough funds in wallet or account diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 983f251d6b..6f24caee21 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -763,7 +763,9 @@ static UniValue signrawtransactionwithkey(const JSONRPCRequest& request) // Parse the prevtxs array ParsePrevouts(request.params[2], &keystore, coins); - return SignTransaction(mtx, &keystore, coins, request.params[3]); + UniValue result(UniValue::VOBJ); + SignTransaction(mtx, &keystore, coins, request.params[3], result); + return result; } static UniValue sendrawtransaction(const JSONRPCRequest& request) diff --git a/src/rpc/rawtransaction_util.cpp b/src/rpc/rawtransaction_util.cpp index fe98fff4bb..40334883c5 100644 --- a/src/rpc/rawtransaction_util.cpp +++ b/src/rpc/rawtransaction_util.cpp @@ -268,7 +268,7 @@ void ParsePrevouts(const UniValue& prevTxsUnival, FillableSigningProvider* keyst } } -UniValue SignTransaction(CMutableTransaction& mtx, const SigningProvider* keystore, const std::map<COutPoint, Coin>& coins, const UniValue& hashType) +void SignTransaction(CMutableTransaction& mtx, const SigningProvider* keystore, const std::map<COutPoint, Coin>& coins, const UniValue& hashType, UniValue& result) { int nHashType = ParseSighashString(hashType); @@ -319,12 +319,12 @@ UniValue SignTransaction(CMutableTransaction& mtx, const SigningProvider* keysto } bool fComplete = vErrors.empty(); - UniValue result(UniValue::VOBJ); result.pushKV("hex", EncodeHexTx(CTransaction(mtx))); result.pushKV("complete", fComplete); if (!vErrors.empty()) { + if (result.exists("errors")) { + vErrors.push_backV(result["errors"].getValues()); + } result.pushKV("errors", vErrors); } - - return result; } diff --git a/src/rpc/rawtransaction_util.h b/src/rpc/rawtransaction_util.h index 1936998ff3..0b7712b83c 100644 --- a/src/rpc/rawtransaction_util.h +++ b/src/rpc/rawtransaction_util.h @@ -21,9 +21,9 @@ class SigningProvider; * @param keystore Temporary keystore containing signing keys * @param coins Map of unspent outputs * @param hashType The signature hash type - * @returns JSON object with details of signed transaction + * @param result JSON object where signed transaction results accumulate */ -UniValue SignTransaction(CMutableTransaction& mtx, const SigningProvider* keystore, const std::map<COutPoint, Coin>& coins, const UniValue& hashType); +void SignTransaction(CMutableTransaction& mtx, const SigningProvider* keystore, const std::map<COutPoint, Coin>& coins, const UniValue& hashType, UniValue& result); /** * Parse a prevtxs UniValue array and get the map of coins from it diff --git a/src/rpc/util.cpp b/src/rpc/util.cpp index cfa3509c65..0791a365fe 100644 --- a/src/rpc/util.cpp +++ b/src/rpc/util.cpp @@ -131,18 +131,18 @@ CPubKey HexToPubKey(const std::string& hex_in) } // Retrieves a public key for an address from the given FillableSigningProvider -CPubKey AddrToPubKey(FillableSigningProvider* const keystore, const std::string& addr_in) +CPubKey AddrToPubKey(const FillableSigningProvider& keystore, const std::string& addr_in) { CTxDestination dest = DecodeDestination(addr_in); if (!IsValidDestination(dest)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address: " + addr_in); } - CKeyID key = GetKeyForDestination(*keystore, dest); + CKeyID key = GetKeyForDestination(keystore, dest); if (key.IsNull()) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("%s does not refer to a key", addr_in)); } CPubKey vchPubKey; - if (!keystore->GetPubKey(key, vchPubKey)) { + if (!keystore.GetPubKey(key, vchPubKey)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("no full public key for address %s", addr_in)); } if (!vchPubKey.IsFullyValid()) { diff --git a/src/rpc/util.h b/src/rpc/util.h index 221638aa9e..9304e1fefb 100644 --- a/src/rpc/util.h +++ b/src/rpc/util.h @@ -69,7 +69,7 @@ extern std::string HelpExampleCli(const std::string& methodname, const std::stri extern std::string HelpExampleRpc(const std::string& methodname, const std::string& args); CPubKey HexToPubKey(const std::string& hex_in); -CPubKey AddrToPubKey(FillableSigningProvider* const keystore, const std::string& addr_in); +CPubKey AddrToPubKey(const FillableSigningProvider& keystore, const std::string& addr_in); CTxDestination AddAndGetMultisigDestination(const int required, const std::vector<CPubKey>& pubkeys, OutputType type, FillableSigningProvider& keystore, CScript& script_out); UniValue DescribeAddress(const CTxDestination& dest); diff --git a/src/scheduler.cpp b/src/scheduler.cpp index fdc859b3a0..07a54335ac 100644 --- a/src/scheduler.cpp +++ b/src/scheduler.cpp @@ -41,8 +41,6 @@ void CScheduler::serviceQueue() try { if (!shouldStop() && taskQueue.empty()) { reverse_lock<boost::unique_lock<boost::mutex> > rlock(lock); - // Use this chance to get more entropy - RandAddSeedSleep(); } while (!shouldStop() && taskQueue.empty()) { // Wait until there is something to do. diff --git a/src/script/descriptor.cpp b/src/script/descriptor.cpp index 13cdd6c61a..32b388b7fa 100644 --- a/src/script/descriptor.cpp +++ b/src/script/descriptor.cpp @@ -815,8 +815,8 @@ std::unique_ptr<DescriptorImpl> ParseScript(Span<const char>& sp, ParseScriptCon } } if (ctx == ParseScriptContext::P2SH) { - if (script_size + 3 > 520) { - error = strprintf("P2SH script is too large, %d bytes is larger than 520 bytes", script_size + 3); + if (script_size + 3 > MAX_SCRIPT_ELEMENT_SIZE) { + error = strprintf("P2SH script is too large, %d bytes is larger than %d bytes", script_size + 3, MAX_SCRIPT_ELEMENT_SIZE); return nullptr; } } diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index 20fae2eebf..ad833bc025 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -61,17 +61,17 @@ static inline void popstack(std::vector<valtype>& stack) } bool static IsCompressedOrUncompressedPubKey(const valtype &vchPubKey) { - if (vchPubKey.size() < CPubKey::COMPRESSED_PUBLIC_KEY_SIZE) { + if (vchPubKey.size() < CPubKey::COMPRESSED_SIZE) { // Non-canonical public key: too short return false; } if (vchPubKey[0] == 0x04) { - if (vchPubKey.size() != CPubKey::PUBLIC_KEY_SIZE) { + if (vchPubKey.size() != CPubKey::SIZE) { // Non-canonical public key: invalid length for uncompressed key return false; } } else if (vchPubKey[0] == 0x02 || vchPubKey[0] == 0x03) { - if (vchPubKey.size() != CPubKey::COMPRESSED_PUBLIC_KEY_SIZE) { + if (vchPubKey.size() != CPubKey::COMPRESSED_SIZE) { // Non-canonical public key: invalid length for compressed key return false; } @@ -83,7 +83,7 @@ bool static IsCompressedOrUncompressedPubKey(const valtype &vchPubKey) { } bool static IsCompressedPubKey(const valtype &vchPubKey) { - if (vchPubKey.size() != CPubKey::COMPRESSED_PUBLIC_KEY_SIZE) { + if (vchPubKey.size() != CPubKey::COMPRESSED_SIZE) { // Non-canonical public key: invalid length for compressed key return false; } diff --git a/src/script/sign.h b/src/script/sign.h index 9d0a5b4d70..4c2403f83f 100644 --- a/src/script/sign.h +++ b/src/script/sign.h @@ -101,7 +101,7 @@ template<typename Stream> void DeserializeHDKeypaths(Stream& s, const std::vector<unsigned char>& key, std::map<CPubKey, KeyOriginInfo>& hd_keypaths) { // Make sure that the key is the size of pubkey + 1 - if (key.size() != CPubKey::PUBLIC_KEY_SIZE + 1 && key.size() != CPubKey::COMPRESSED_PUBLIC_KEY_SIZE + 1) { + if (key.size() != CPubKey::SIZE + 1 && key.size() != CPubKey::COMPRESSED_SIZE + 1) { throw std::ios_base::failure("Size of key was not the expected size for the type BIP32 keypath"); } // Read in the pubkey from key diff --git a/src/script/standard.cpp b/src/script/standard.cpp index fc6898f444..144bdcff98 100644 --- a/src/script/standard.cpp +++ b/src/script/standard.cpp @@ -44,12 +44,12 @@ const char* GetTxnOutputType(txnouttype t) static bool MatchPayToPubkey(const CScript& script, valtype& pubkey) { - if (script.size() == CPubKey::PUBLIC_KEY_SIZE + 2 && script[0] == CPubKey::PUBLIC_KEY_SIZE && script.back() == OP_CHECKSIG) { - pubkey = valtype(script.begin() + 1, script.begin() + CPubKey::PUBLIC_KEY_SIZE + 1); + if (script.size() == CPubKey::SIZE + 2 && script[0] == CPubKey::SIZE && script.back() == OP_CHECKSIG) { + pubkey = valtype(script.begin() + 1, script.begin() + CPubKey::SIZE + 1); return CPubKey::ValidSize(pubkey); } - if (script.size() == CPubKey::COMPRESSED_PUBLIC_KEY_SIZE + 2 && script[0] == CPubKey::COMPRESSED_PUBLIC_KEY_SIZE && script.back() == OP_CHECKSIG) { - pubkey = valtype(script.begin() + 1, script.begin() + CPubKey::COMPRESSED_PUBLIC_KEY_SIZE + 1); + if (script.size() == CPubKey::COMPRESSED_SIZE + 2 && script[0] == CPubKey::COMPRESSED_SIZE && script.back() == OP_CHECKSIG) { + pubkey = valtype(script.begin() + 1, script.begin() + CPubKey::COMPRESSED_SIZE + 1); return CPubKey::ValidSize(pubkey); } return false; diff --git a/src/support/lockedpool.cpp b/src/support/lockedpool.cpp index 5c2050e4a2..85e3351e72 100644 --- a/src/support/lockedpool.cpp +++ b/src/support/lockedpool.cpp @@ -23,6 +23,10 @@ #endif #include <algorithm> +#ifdef ARENA_DEBUG +#include <iomanip> +#include <iostream> +#endif LockedPoolManager* LockedPoolManager::_instance = nullptr; std::once_flag LockedPoolManager::init_flag; @@ -137,7 +141,7 @@ Arena::Stats Arena::stats() const } #ifdef ARENA_DEBUG -static void printchunk(char* base, size_t sz, bool used) { +static void printchunk(void* base, size_t sz, bool used) { std::cout << "0x" << std::hex << std::setw(16) << std::setfill('0') << base << " 0x" << std::hex << std::setw(16) << std::setfill('0') << sz << @@ -149,7 +153,7 @@ void Arena::walk() const printchunk(chunk.first, chunk.second, true); std::cout << std::endl; for (const auto& chunk: chunks_free) - printchunk(chunk.first, chunk.second, false); + printchunk(chunk.first, chunk.second->first, false); std::cout << std::endl; } #endif diff --git a/src/test/checkqueue_tests.cpp b/src/test/checkqueue_tests.cpp index 6745bb9015..482fe3772c 100644 --- a/src/test/checkqueue_tests.cpp +++ b/src/test/checkqueue_tests.cpp @@ -17,6 +17,7 @@ #include <condition_variable> #include <unordered_set> +#include <utility> BOOST_FIXTURE_TEST_SUITE(checkqueue_tests, TestingSetup) diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp index 591a317d17..2deb0c5bfc 100644 --- a/src/test/crypto_tests.cpp +++ b/src/test/crypto_tests.cpp @@ -186,14 +186,15 @@ static void TestHKDF_SHA256_32(const std::string &ikm_hex, const std::string &sa BOOST_CHECK(HexStr(out, out + 32) == okm_check_hex); } -static std::string LongTestString() { +static std::string LongTestString() +{ std::string ret; - for (int i=0; i<200000; i++) { - ret += (unsigned char)(i); - ret += (unsigned char)(i >> 4); - ret += (unsigned char)(i >> 8); - ret += (unsigned char)(i >> 12); - ret += (unsigned char)(i >> 16); + for (int i = 0; i < 200000; i++) { + ret += (char)(i); + ret += (char)(i >> 4); + ret += (char)(i >> 8); + ret += (char)(i >> 12); + ret += (char)(i >> 16); } return ret; } diff --git a/src/test/dbwrapper_tests.cpp b/src/test/dbwrapper_tests.cpp index 57d5b2bb5c..b647c0f70b 100644 --- a/src/test/dbwrapper_tests.cpp +++ b/src/test/dbwrapper_tests.cpp @@ -397,6 +397,18 @@ BOOST_AUTO_TEST_CASE(iterator_string_ordering) } } +BOOST_AUTO_TEST_CASE(unicodepath) +{ + // Attempt to create a database with a utf8 character in the path. + // On Windows this test will fail if the directory is created using + // the ANSI CreateDirectoryA call and the code page isn't UTF8. + // It will succeed if the created with CreateDirectoryW. + fs::path ph = GetDataDir() / "test_runner_₿_🏃_20191128_104644"; + CDBWrapper dbw(ph, (1 << 20)); + + fs::path lockPath = ph / "LOCK"; + BOOST_CHECK(boost::filesystem::exists(lockPath)); +} BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/fuzz/psbt.cpp b/src/test/fuzz/psbt.cpp new file mode 100644 index 0000000000..1ce28f9a6d --- /dev/null +++ b/src/test/fuzz/psbt.cpp @@ -0,0 +1,79 @@ +// 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/fuzz.h> + +#include <node/psbt.h> +#include <optional.h> +#include <psbt.h> +#include <pubkey.h> +#include <script/script.h> +#include <streams.h> +#include <util/memory.h> +#include <version.h> + +#include <cstdint> +#include <string> +#include <vector> + +void initialize() +{ + static const auto verify_handle = MakeUnique<ECCVerifyHandle>(); +} + +void test_one_input(const std::vector<uint8_t>& buffer) +{ + PartiallySignedTransaction psbt_mut; + const std::string raw_psbt{buffer.begin(), buffer.end()}; + std::string error; + if (!DecodeRawPSBT(psbt_mut, raw_psbt, error)) { + return; + } + const PartiallySignedTransaction psbt = psbt_mut; + + const PSBTAnalysis analysis = AnalyzePSBT(psbt); + (void)PSBTRoleName(analysis.next); + for (const PSBTInputAnalysis& input_analysis : analysis.inputs) { + (void)PSBTRoleName(input_analysis.next); + } + + (void)psbt.IsNull(); + (void)psbt.IsSane(); + + Optional<CMutableTransaction> tx = psbt.tx; + if (tx) { + const CMutableTransaction& mtx = *tx; + const PartiallySignedTransaction psbt_from_tx{mtx}; + } + + for (const PSBTInput& input : psbt.inputs) { + (void)PSBTInputSigned(input); + (void)input.IsNull(); + (void)input.IsSane(); + } + + for (const PSBTOutput& output : psbt.outputs) { + (void)output.IsNull(); + } + + for (size_t i = 0; i < psbt.tx->vin.size(); ++i) { + CTxOut tx_out; + if (psbt.GetInputUTXO(tx_out, i)) { + (void)tx_out.IsNull(); + (void)tx_out.ToString(); + } + } + + psbt_mut = psbt; + (void)FinalizePSBT(psbt_mut); + + psbt_mut = psbt; + CMutableTransaction result; + if (FinalizeAndExtractPSBT(psbt_mut, result)) { + const PartiallySignedTransaction psbt_from_tx{result}; + } + + psbt_mut = psbt; + (void)psbt_mut.Merge(psbt); +} diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index 6ed7350ea2..d79a598bf1 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -23,7 +23,17 @@ #include <boost/test/unit_test.hpp> -BOOST_FIXTURE_TEST_SUITE(miner_tests, TestingSetup) +namespace miner_tests { +struct MinerTestingSetup : public TestingSetup { + void TestPackageSelection(const CChainParams& chainparams, const CScript& scriptPubKey, const std::vector<CTransactionRef>& txFirst) EXCLUSIVE_LOCKS_REQUIRED(::cs_main, m_node.mempool->cs); + bool TestSequenceLocks(const CTransaction& tx, int flags) EXCLUSIVE_LOCKS_REQUIRED(::cs_main, m_node.mempool->cs) + { + return CheckSequenceLocks(*m_node.mempool, tx, flags); + } +}; +} // namespace miner_tests + +BOOST_FIXTURE_TEST_SUITE(miner_tests, MinerTestingSetup) // BOOST_CHECK_EXCEPTION predicates to check the specific validation error class HasReason { @@ -89,16 +99,10 @@ static CBlockIndex CreateBlockIndex(int nHeight) EXCLUSIVE_LOCKS_REQUIRED(cs_mai return index; } -static bool TestSequenceLocks(const CTransaction &tx, int flags) EXCLUSIVE_LOCKS_REQUIRED(cs_main) -{ - LOCK(::mempool.cs); - return CheckSequenceLocks(::mempool, tx, flags); -} - // Test suite for ancestor feerate transaction selection. // Implemented as an additional function, rather than a separate test case, // to allow reusing the blockchain created in CreateNewBlock_validity. -static void TestPackageSelection(const CChainParams& chainparams, const CScript& scriptPubKey, const std::vector<CTransactionRef>& txFirst) EXCLUSIVE_LOCKS_REQUIRED(cs_main, ::mempool.cs) +void MinerTestingSetup::TestPackageSelection(const CChainParams& chainparams, const CScript& scriptPubKey, const std::vector<CTransactionRef>& txFirst) { // Test the ancestor feerate transaction selection. TestMemPoolEntryHelper entry; @@ -114,19 +118,19 @@ static void TestPackageSelection(const CChainParams& chainparams, const CScript& tx.vout[0].nValue = 5000000000LL - 1000; // This tx has a low fee: 1000 satoshis uint256 hashParentTx = tx.GetHash(); // save this txid for later use - mempool.addUnchecked(entry.Fee(1000).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); + m_node.mempool->addUnchecked(entry.Fee(1000).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); // This tx has a medium fee: 10000 satoshis tx.vin[0].prevout.hash = txFirst[1]->GetHash(); tx.vout[0].nValue = 5000000000LL - 10000; uint256 hashMediumFeeTx = tx.GetHash(); - mempool.addUnchecked(entry.Fee(10000).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); + m_node.mempool->addUnchecked(entry.Fee(10000).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); // This tx has a high fee, but depends on the first transaction tx.vin[0].prevout.hash = hashParentTx; tx.vout[0].nValue = 5000000000LL - 1000 - 50000; // 50k satoshi fee uint256 hashHighFeeTx = tx.GetHash(); - mempool.addUnchecked(entry.Fee(50000).Time(GetTime()).SpendsCoinbase(false).FromTx(tx)); + m_node.mempool->addUnchecked(entry.Fee(50000).Time(GetTime()).SpendsCoinbase(false).FromTx(tx)); std::unique_ptr<CBlockTemplate> pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey); BOOST_CHECK(pblocktemplate->block.vtx[1]->GetHash() == hashParentTx); @@ -137,7 +141,7 @@ static void TestPackageSelection(const CChainParams& chainparams, const CScript& tx.vin[0].prevout.hash = hashHighFeeTx; tx.vout[0].nValue = 5000000000LL - 1000 - 50000; // 0 fee uint256 hashFreeTx = tx.GetHash(); - mempool.addUnchecked(entry.Fee(0).FromTx(tx)); + m_node.mempool->addUnchecked(entry.Fee(0).FromTx(tx)); size_t freeTxSize = ::GetSerializeSize(tx, PROTOCOL_VERSION); // Calculate a fee on child transaction that will put the package just @@ -147,7 +151,7 @@ static void TestPackageSelection(const CChainParams& chainparams, const CScript& tx.vin[0].prevout.hash = hashFreeTx; tx.vout[0].nValue = 5000000000LL - 1000 - 50000 - feeToUse; uint256 hashLowFeeTx = tx.GetHash(); - mempool.addUnchecked(entry.Fee(feeToUse).FromTx(tx)); + m_node.mempool->addUnchecked(entry.Fee(feeToUse).FromTx(tx)); pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey); // Verify that the free tx and the low fee tx didn't get selected for (size_t i=0; i<pblocktemplate->block.vtx.size(); ++i) { @@ -158,10 +162,10 @@ static void TestPackageSelection(const CChainParams& chainparams, const CScript& // Test that packages above the min relay fee do get included, even if one // of the transactions is below the min relay fee // Remove the low fee transaction and replace with a higher fee transaction - mempool.removeRecursive(CTransaction(tx), MemPoolRemovalReason::REPLACED); + m_node.mempool->removeRecursive(CTransaction(tx), MemPoolRemovalReason::REPLACED); tx.vout[0].nValue -= 2; // Now we should be just over the min relay fee hashLowFeeTx = tx.GetHash(); - mempool.addUnchecked(entry.Fee(feeToUse+2).FromTx(tx)); + m_node.mempool->addUnchecked(entry.Fee(feeToUse+2).FromTx(tx)); pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey); BOOST_CHECK(pblocktemplate->block.vtx[4]->GetHash() == hashFreeTx); BOOST_CHECK(pblocktemplate->block.vtx[5]->GetHash() == hashLowFeeTx); @@ -174,7 +178,7 @@ static void TestPackageSelection(const CChainParams& chainparams, const CScript& tx.vout[0].nValue = 5000000000LL - 100000000; tx.vout[1].nValue = 100000000; // 1BTC output uint256 hashFreeTx2 = tx.GetHash(); - mempool.addUnchecked(entry.Fee(0).SpendsCoinbase(true).FromTx(tx)); + m_node.mempool->addUnchecked(entry.Fee(0).SpendsCoinbase(true).FromTx(tx)); // This tx can't be mined by itself tx.vin[0].prevout.hash = hashFreeTx2; @@ -182,7 +186,7 @@ static void TestPackageSelection(const CChainParams& chainparams, const CScript& feeToUse = blockMinFeeRate.GetFee(freeTxSize); tx.vout[0].nValue = 5000000000LL - 100000000 - feeToUse; uint256 hashLowFeeTx2 = tx.GetHash(); - mempool.addUnchecked(entry.Fee(feeToUse).SpendsCoinbase(false).FromTx(tx)); + m_node.mempool->addUnchecked(entry.Fee(feeToUse).SpendsCoinbase(false).FromTx(tx)); pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey); // Verify that this tx isn't selected. @@ -195,7 +199,7 @@ static void TestPackageSelection(const CChainParams& chainparams, const CScript& // as well. tx.vin[0].prevout.n = 1; tx.vout[0].nValue = 100000000 - 10000; // 10k satoshi fee - mempool.addUnchecked(entry.Fee(10000).FromTx(tx)); + m_node.mempool->addUnchecked(entry.Fee(10000).FromTx(tx)); pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey); BOOST_CHECK(pblocktemplate->block.vtx[8]->GetHash() == hashLowFeeTx2); } @@ -252,7 +256,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) } LOCK(cs_main); - LOCK(::mempool.cs); + LOCK(m_node.mempool->cs); // Just to make sure we can still make simple blocks BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey)); @@ -276,12 +280,12 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) hash = tx.GetHash(); bool spendsCoinbase = i == 0; // only first tx spends coinbase // If we don't set the # of sig ops in the CTxMemPoolEntry, template creation fails - mempool.addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(spendsCoinbase).FromTx(tx)); + m_node.mempool->addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(spendsCoinbase).FromTx(tx)); tx.vin[0].prevout.hash = hash; } BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("bad-blk-sigops")); - mempool.clear(); + m_node.mempool->clear(); tx.vin[0].prevout.hash = txFirst[0]->GetHash(); tx.vout[0].nValue = BLOCKSUBSIDY; @@ -291,11 +295,11 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) hash = tx.GetHash(); bool spendsCoinbase = i == 0; // only first tx spends coinbase // If we do set the # of sig ops in the CTxMemPoolEntry, template creation passes - mempool.addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(spendsCoinbase).SigOpsCost(80).FromTx(tx)); + m_node.mempool->addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(spendsCoinbase).SigOpsCost(80).FromTx(tx)); tx.vin[0].prevout.hash = hash; } BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey)); - mempool.clear(); + m_node.mempool->clear(); // block size > limit tx.vin[0].scriptSig = CScript(); @@ -311,24 +315,24 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) tx.vout[0].nValue -= LOWFEE; hash = tx.GetHash(); bool spendsCoinbase = i == 0; // only first tx spends coinbase - mempool.addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(spendsCoinbase).FromTx(tx)); + m_node.mempool->addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(spendsCoinbase).FromTx(tx)); tx.vin[0].prevout.hash = hash; } BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey)); - mempool.clear(); + m_node.mempool->clear(); - // orphan in mempool, template creation fails + // orphan in *m_node.mempool, template creation fails hash = tx.GetHash(); - mempool.addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).FromTx(tx)); + m_node.mempool->addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).FromTx(tx)); BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("bad-txns-inputs-missingorspent")); - mempool.clear(); + m_node.mempool->clear(); // child with higher feerate than parent tx.vin[0].scriptSig = CScript() << OP_1; tx.vin[0].prevout.hash = txFirst[1]->GetHash(); tx.vout[0].nValue = BLOCKSUBSIDY-HIGHFEE; hash = tx.GetHash(); - mempool.addUnchecked(entry.Fee(HIGHFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); + m_node.mempool->addUnchecked(entry.Fee(HIGHFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); tx.vin[0].prevout.hash = hash; tx.vin.resize(2); tx.vin[1].scriptSig = CScript() << OP_1; @@ -336,34 +340,34 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) tx.vin[1].prevout.n = 0; tx.vout[0].nValue = tx.vout[0].nValue+BLOCKSUBSIDY-HIGHERFEE; //First txn output + fresh coinbase - new txn fee hash = tx.GetHash(); - mempool.addUnchecked(entry.Fee(HIGHERFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); + m_node.mempool->addUnchecked(entry.Fee(HIGHERFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey)); - mempool.clear(); + m_node.mempool->clear(); - // coinbase in mempool, template creation fails + // coinbase in *m_node.mempool, template creation fails tx.vin.resize(1); tx.vin[0].prevout.SetNull(); tx.vin[0].scriptSig = CScript() << OP_0 << OP_1; tx.vout[0].nValue = 0; hash = tx.GetHash(); // give it a fee so it'll get mined - mempool.addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(false).FromTx(tx)); + m_node.mempool->addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(false).FromTx(tx)); // Should throw bad-cb-multiple BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("bad-cb-multiple")); - mempool.clear(); + m_node.mempool->clear(); - // double spend txn pair in mempool, template creation fails + // double spend txn pair in *m_node.mempool, template creation fails tx.vin[0].prevout.hash = txFirst[0]->GetHash(); tx.vin[0].scriptSig = CScript() << OP_1; tx.vout[0].nValue = BLOCKSUBSIDY-HIGHFEE; tx.vout[0].scriptPubKey = CScript() << OP_1; hash = tx.GetHash(); - mempool.addUnchecked(entry.Fee(HIGHFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); + m_node.mempool->addUnchecked(entry.Fee(HIGHFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); tx.vout[0].scriptPubKey = CScript() << OP_2; hash = tx.GetHash(); - mempool.addUnchecked(entry.Fee(HIGHFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); + m_node.mempool->addUnchecked(entry.Fee(HIGHFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("bad-txns-inputs-missingorspent")); - mempool.clear(); + m_node.mempool->clear(); // subsidy changing int nHeight = ::ChainActive().Height(); @@ -392,7 +396,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) } BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey)); - // invalid p2sh txn in mempool, template creation fails + // invalid p2sh txn in *m_node.mempool, template creation fails tx.vin[0].prevout.hash = txFirst[0]->GetHash(); tx.vin[0].prevout.n = 0; tx.vin[0].scriptSig = CScript() << OP_1; @@ -400,15 +404,15 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) script = CScript() << OP_0; tx.vout[0].scriptPubKey = GetScriptForDestination(ScriptHash(script)); hash = tx.GetHash(); - mempool.addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); + m_node.mempool->addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); tx.vin[0].prevout.hash = hash; tx.vin[0].scriptSig = CScript() << std::vector<unsigned char>(script.begin(), script.end()); tx.vout[0].nValue -= LOWFEE; hash = tx.GetHash(); - mempool.addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(false).FromTx(tx)); + m_node.mempool->addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(false).FromTx(tx)); // Should throw block-validation-failed BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("block-validation-failed")); - mempool.clear(); + m_node.mempool->clear(); // Delete the dummy blocks again. while (::ChainActive().Tip()->nHeight > nHeight) { @@ -439,7 +443,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) tx.vout[0].scriptPubKey = CScript() << OP_1; tx.nLockTime = 0; hash = tx.GetHash(); - mempool.addUnchecked(entry.Fee(HIGHFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); + m_node.mempool->addUnchecked(entry.Fee(HIGHFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); BOOST_CHECK(CheckFinalTx(CTransaction(tx), flags)); // Locktime passes BOOST_CHECK(!TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks fail BOOST_CHECK(SequenceLocks(CTransaction(tx), flags, &prevheights, CreateBlockIndex(::ChainActive().Tip()->nHeight + 2))); // Sequence locks pass on 2nd block @@ -449,7 +453,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) tx.vin[0].nSequence = CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG | (((::ChainActive().Tip()->GetMedianTimePast()+1-::ChainActive()[1]->GetMedianTimePast()) >> CTxIn::SEQUENCE_LOCKTIME_GRANULARITY) + 1); // txFirst[1] is the 3rd block prevheights[0] = baseheight + 2; hash = tx.GetHash(); - mempool.addUnchecked(entry.Time(GetTime()).FromTx(tx)); + m_node.mempool->addUnchecked(entry.Time(GetTime()).FromTx(tx)); BOOST_CHECK(CheckFinalTx(CTransaction(tx), flags)); // Locktime passes BOOST_CHECK(!TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks fail @@ -465,7 +469,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) prevheights[0] = baseheight + 3; tx.nLockTime = ::ChainActive().Tip()->nHeight + 1; hash = tx.GetHash(); - mempool.addUnchecked(entry.Time(GetTime()).FromTx(tx)); + m_node.mempool->addUnchecked(entry.Time(GetTime()).FromTx(tx)); BOOST_CHECK(!CheckFinalTx(CTransaction(tx), flags)); // Locktime fails BOOST_CHECK(TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks pass BOOST_CHECK(IsFinalTx(CTransaction(tx), ::ChainActive().Tip()->nHeight + 2, ::ChainActive().Tip()->GetMedianTimePast())); // Locktime passes on 2nd block @@ -476,7 +480,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) prevheights.resize(1); prevheights[0] = baseheight + 4; hash = tx.GetHash(); - mempool.addUnchecked(entry.Time(GetTime()).FromTx(tx)); + m_node.mempool->addUnchecked(entry.Time(GetTime()).FromTx(tx)); BOOST_CHECK(!CheckFinalTx(CTransaction(tx), flags)); // Locktime fails BOOST_CHECK(TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks pass BOOST_CHECK(IsFinalTx(CTransaction(tx), ::ChainActive().Tip()->nHeight + 2, ::ChainActive().Tip()->GetMedianTimePast() + 1)); // Locktime passes 1 second later @@ -513,7 +517,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) ::ChainActive().Tip()->nHeight--; SetMockTime(0); - mempool.clear(); + m_node.mempool->clear(); TestPackageSelection(chainparams, scriptPubKey, txFirst); diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index eb0050a4a3..2f7a3132d8 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -713,6 +713,29 @@ BOOST_AUTO_TEST_CASE(test_IsStandard) t.vout[0].nValue = nDustThreshold; BOOST_CHECK(IsStandardTx(CTransaction(t), reason)); + // Disallowed nVersion + t.nVersion = -1; + reason.clear(); + BOOST_CHECK(!IsStandardTx(CTransaction(t), reason)); + BOOST_CHECK_EQUAL(reason, "version"); + + t.nVersion = 0; + reason.clear(); + BOOST_CHECK(!IsStandardTx(CTransaction(t), reason)); + BOOST_CHECK_EQUAL(reason, "version"); + + t.nVersion = 3; + reason.clear(); + BOOST_CHECK(!IsStandardTx(CTransaction(t), reason)); + BOOST_CHECK_EQUAL(reason, "version"); + + // Allowed nVersion + t.nVersion = 1; + BOOST_CHECK(IsStandardTx(CTransaction(t), reason)); + + t.nVersion = 2; + BOOST_CHECK(IsStandardTx(CTransaction(t), reason)); + // Check dust with odd relay fee to verify rounding: // nDustThreshold = 182 * 3702 / 1000 dustRelayFee = CFeeRate(3702); diff --git a/src/test/txvalidation_tests.cpp b/src/test/txvalidation_tests.cpp index 245c03d774..cace75f093 100644 --- a/src/test/txvalidation_tests.cpp +++ b/src/test/txvalidation_tests.cpp @@ -34,17 +34,17 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_reject_coinbase, TestChain100Setup) LOCK(cs_main); - unsigned int initialPoolSize = mempool.size(); + unsigned int initialPoolSize = m_node.mempool->size(); BOOST_CHECK_EQUAL( false, - AcceptToMemoryPool(mempool, state, MakeTransactionRef(coinbaseTx), + AcceptToMemoryPool(*m_node.mempool, state, MakeTransactionRef(coinbaseTx), nullptr /* plTxnReplaced */, true /* bypass_limits */, 0 /* nAbsurdFee */)); // Check that the transaction hasn't been added to mempool. - BOOST_CHECK_EQUAL(mempool.size(), initialPoolSize); + BOOST_CHECK_EQUAL(m_node.mempool->size(), initialPoolSize); // Check that the validation state reflects the unsuccessful attempt. BOOST_CHECK(state.IsInvalid()); diff --git a/src/test/txvalidationcache_tests.cpp b/src/test/txvalidationcache_tests.cpp index a5bc15bb9f..67f45c4ed4 100644 --- a/src/test/txvalidationcache_tests.cpp +++ b/src/test/txvalidationcache_tests.cpp @@ -17,16 +17,6 @@ bool CheckInputs(const CTransaction& tx, TxValidationState &state, const CCoinsV BOOST_AUTO_TEST_SUITE(tx_validationcache_tests) -static bool -ToMemPool(const CMutableTransaction& tx) -{ - LOCK(cs_main); - - TxValidationState state; - return AcceptToMemoryPool(mempool, state, MakeTransactionRef(tx), - nullptr /* plTxnReplaced */, true /* bypass_limits */, 0 /* nAbsurdFee */); -} - BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, TestChain100Setup) { // Make sure skipping validation of transactions that were @@ -35,6 +25,14 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, TestChain100Setup) CScript scriptPubKey = CScript() << ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG; + const auto ToMemPool = [this](const CMutableTransaction& tx) { + LOCK(cs_main); + + TxValidationState state; + return AcceptToMemoryPool(*m_node.mempool, state, MakeTransactionRef(tx), + nullptr /* plTxnReplaced */, true /* bypass_limits */, 0 /* nAbsurdFee */); + }; + // Create a double-spend of mature coinbase txn: std::vector<CMutableTransaction> spends; spends.resize(2); @@ -72,7 +70,7 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, TestChain100Setup) LOCK(cs_main); BOOST_CHECK(::ChainActive().Tip()->GetBlockHash() != block.GetHash()); } - mempool.clear(); + m_node.mempool->clear(); // Test 3: ... and should be rejected if spend2 is in the memory pool BOOST_CHECK(ToMemPool(spends[1])); @@ -81,9 +79,9 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, TestChain100Setup) LOCK(cs_main); BOOST_CHECK(::ChainActive().Tip()->GetBlockHash() != block.GetHash()); } - mempool.clear(); + m_node.mempool->clear(); - // Final sanity test: first spend in mempool, second in block, that's OK: + // Final sanity test: first spend in *m_node.mempool, second in block, that's OK: std::vector<CMutableTransaction> oneSpend; oneSpend.push_back(spends[0]); BOOST_CHECK(ToMemPool(spends[1])); @@ -94,7 +92,7 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, TestChain100Setup) } // spends[1] should have been removed from the mempool when the // block with spends[0] is accepted: - BOOST_CHECK_EQUAL(mempool.size(), 0U); + BOOST_CHECK_EQUAL(m_node.mempool->size(), 0U); } // Run CheckInputs (using CoinsTip()) on the given transaction, for all script diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp index 0c6ecdf69d..86c355fdcd 100644 --- a/src/test/util/setup_common.cpp +++ b/src/test/util/setup_common.cpp @@ -107,7 +107,6 @@ TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(cha threadGroup.create_thread(std::bind(&CScheduler::serviceQueue, &scheduler)); GetMainSignals().RegisterBackgroundSignalScheduler(scheduler); - mempool.setSanityCheck(1.0); pblocktree.reset(new CBlockTreeDB(1 << 20, true)); g_chainstate = MakeUnique<CChainState>(); ::ChainstateActive().InitCoinsDB( @@ -131,6 +130,8 @@ TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(cha } g_parallel_script_checks = true; + m_node.mempool = &::mempool; + m_node.mempool->setSanityCheck(1.0); m_node.banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME); m_node.connman = MakeUnique<CConnman>(0x1337, 0x1337); // Deterministic randomness for tests. } @@ -144,6 +145,7 @@ TestingSetup::~TestingSetup() g_rpc_node = nullptr; m_node.connman.reset(); m_node.banman.reset(); + m_node.mempool = nullptr; UnloadBlockIndex(); g_chainstate.reset(); pblocktree.reset(); diff --git a/src/test/validation_block_tests.cpp b/src/test/validation_block_tests.cpp index b7cf82906a..1fa48b325c 100644 --- a/src/test/validation_block_tests.cpp +++ b/src/test/validation_block_tests.cpp @@ -279,7 +279,7 @@ BOOST_AUTO_TEST_CASE(mempool_locks_reorg) std::list<CTransactionRef> plTxnReplaced; for (const auto& tx : txs) { BOOST_REQUIRE(AcceptToMemoryPool( - ::mempool, + *m_node.mempool, state, tx, &plTxnReplaced, @@ -290,8 +290,8 @@ BOOST_AUTO_TEST_CASE(mempool_locks_reorg) // Check that all txs are in the pool { - LOCK(::mempool.cs); - BOOST_CHECK_EQUAL(::mempool.mapTx.size(), txs.size()); + LOCK(m_node.mempool->cs); + BOOST_CHECK_EQUAL(m_node.mempool->mapTx.size(), txs.size()); } // Run a thread that simulates an RPC caller that is polling while @@ -301,8 +301,8 @@ BOOST_AUTO_TEST_CASE(mempool_locks_reorg) // the transactions invalidated by the reorg, or none of them, and // not some intermediate amount. while (true) { - LOCK(::mempool.cs); - if (::mempool.mapTx.size() == 0) { + LOCK(m_node.mempool->cs); + if (m_node.mempool->mapTx.size() == 0) { // We are done with the reorg break; } @@ -311,7 +311,7 @@ BOOST_AUTO_TEST_CASE(mempool_locks_reorg) // be atomic. So the caller assumes that the returned mempool // is consistent. That is, it has all txs that were there // before the reorg. - assert(::mempool.mapTx.size() == txs.size()); + assert(m_node.mempool->mapTx.size() == txs.size()); continue; } LOCK(cs_main); diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 08f935c24f..3c967a04c0 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -17,6 +17,7 @@ #include <util/system.h> #include <util/moneystr.h> #include <util/time.h> +#include <validationinterface.h> CTxMemPoolEntry::CTxMemPoolEntry(const CTransactionRef& _tx, const CAmount& _nFee, int64_t _nTime, unsigned int _entryHeight, @@ -403,7 +404,12 @@ void CTxMemPool::addUnchecked(const CTxMemPoolEntry &entry, setEntries &setAnces void CTxMemPool::removeUnchecked(txiter it, MemPoolRemovalReason reason) { - NotifyEntryRemoved(it->GetSharedTx(), reason); + CTransactionRef ptx = it->GetSharedTx(); + NotifyEntryRemoved(ptx, reason); + if (reason != MemPoolRemovalReason::BLOCK && reason != MemPoolRemovalReason::CONFLICT) { + GetMainSignals().TransactionRemovedFromMempool(ptx); + } + const uint256 hash = it->GetTx().GetHash(); for (const CTxIn& txin : it->GetTx().vin) mapNextTx.erase(txin.prevout); diff --git a/src/util/system.cpp b/src/util/system.cpp index 2a2ae6fdf5..563ff6a54b 100644 --- a/src/util/system.cpp +++ b/src/util/system.cpp @@ -1126,17 +1126,13 @@ fs::path AbsPathForConfigVal(const fs::path& path, bool net_specific) return fs::absolute(path, GetDataDir(net_specific)); } -int ScheduleBatchPriority() +void ScheduleBatchPriority() { #ifdef SCHED_BATCH const static sched_param param{}; - if (int ret = pthread_setschedparam(pthread_self(), SCHED_BATCH, ¶m)) { + if (pthread_setschedparam(pthread_self(), SCHED_BATCH, ¶m) != 0) { LogPrintf("Failed to pthread_setschedparam: %s\n", strerror(errno)); - return ret; } - return 0; -#else - return 1; #endif } diff --git a/src/util/system.h b/src/util/system.h index e0b6371dc9..82903b5187 100644 --- a/src/util/system.h +++ b/src/util/system.h @@ -367,10 +367,8 @@ std::string CopyrightHolders(const std::string& strPrefix); * On platforms that support it, tell the kernel the calling thread is * CPU-intensive and non-interactive. See SCHED_BATCH in sched(7) for details. * - * @return The return value of sched_setschedule(), or 1 on systems without - * sched_setschedule(). */ -int ScheduleBatchPriority(); +void ScheduleBatchPriority(); namespace util { diff --git a/src/validation.cpp b/src/validation.cpp index cc7687ae05..8f5d333170 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -129,9 +129,6 @@ CFeeRate minRelayTxFee = CFeeRate(DEFAULT_MIN_RELAY_TX_FEE); CBlockPolicyEstimator feeEstimator; CTxMemPool mempool(&feeEstimator); -/** Constant stuff for coinbase transactions we create: */ -CScript COINBASE_FLAGS; - // Internal stuff namespace { CBlockIndex* pindexBestInvalid = nullptr; @@ -5089,7 +5086,7 @@ double GuessVerificationProgress(const ChainTxData& data, const CBlockIndex *pin fTxTotal = pindex->nChainTx + (nNow - pindex->GetBlockTime()) * data.dTxRate; } - return pindex->nChainTx / fTxTotal; + return std::min<double>(pindex->nChainTx / fTxTotal, 1.0); } class CMainCleanup diff --git a/src/validation.h b/src/validation.h index 31721cfbf7..54f97e7213 100644 --- a/src/validation.h +++ b/src/validation.h @@ -23,7 +23,6 @@ #include <versionbits.h> #include <serialize.h> -#include <algorithm> #include <atomic> #include <map> #include <memory> @@ -137,7 +136,6 @@ struct BlockHasher size_t operator()(const uint256& hash) const { return ReadLE64(hash.begin()); } }; -extern CScript COINBASE_FLAGS; extern CCriticalSection cs_main; extern CBlockPolicyEstimator feeEstimator; extern CTxMemPool mempool; diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp index 663308bae9..6c0f4d5edd 100644 --- a/src/validationinterface.cpp +++ b/src/validationinterface.cpp @@ -7,9 +7,9 @@ #include <primitives/block.h> #include <scheduler.h> -#include <txmempool.h> #include <future> +#include <unordered_map> #include <utility> #include <boost/signals2/signal.hpp> @@ -46,11 +46,6 @@ struct MainSignalsInstance { static CMainSignals g_signals; -// This map has to a separate global instead of a member of MainSignalsInstance, -// because RegisterWithMempoolSignals is currently called before RegisterBackgroundSignalScheduler, -// so MainSignalsInstance hasn't been created yet. -static std::unordered_map<CTxMemPool*, boost::signals2::scoped_connection> g_connNotifyEntryRemoved; - void CMainSignals::RegisterBackgroundSignalScheduler(CScheduler& scheduler) { assert(!m_internals); m_internals.reset(new MainSignalsInstance(&scheduler)); @@ -71,17 +66,6 @@ size_t CMainSignals::CallbacksPending() { return m_internals->m_schedulerClient.CallbacksPending(); } -void CMainSignals::RegisterWithMempoolSignals(CTxMemPool& pool) { - g_connNotifyEntryRemoved.emplace(std::piecewise_construct, - std::forward_as_tuple(&pool), - std::forward_as_tuple(pool.NotifyEntryRemoved.connect(std::bind(&CMainSignals::MempoolEntryRemoved, this, std::placeholders::_1, std::placeholders::_2))) - ); -} - -void CMainSignals::UnregisterWithMempoolSignals(CTxMemPool& pool) { - g_connNotifyEntryRemoved.erase(&pool); -} - CMainSignals& GetMainSignals() { return g_signals; @@ -126,13 +110,6 @@ void SyncWithValidationInterfaceQueue() { promise.get_future().wait(); } -void CMainSignals::MempoolEntryRemoved(CTransactionRef ptx, MemPoolRemovalReason reason) { - if (reason != MemPoolRemovalReason::BLOCK && reason != MemPoolRemovalReason::CONFLICT) { - m_internals->m_schedulerClient.AddToProcessQueue([ptx, this] { - m_internals->TransactionRemovedFromMempool(ptx); - }); - } -} void CMainSignals::UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) { // Dependencies exist that require UpdatedBlockTip events to be delivered in the order in which @@ -150,6 +127,12 @@ void CMainSignals::TransactionAddedToMempool(const CTransactionRef &ptx) { }); } +void CMainSignals::TransactionRemovedFromMempool(const CTransactionRef &ptx) { + m_internals->m_schedulerClient.AddToProcessQueue([ptx, this] { + m_internals->TransactionRemovedFromMempool(ptx); + }); +} + void CMainSignals::BlockConnected(const std::shared_ptr<const CBlock> &pblock, const CBlockIndex *pindex, const std::shared_ptr<const std::vector<CTransactionRef>>& pvtxConflicted) { m_internals->m_schedulerClient.AddToProcessQueue([pblock, pindex, pvtxConflicted, this] { m_internals->BlockConnected(pblock, pindex, *pvtxConflicted); diff --git a/src/validationinterface.h b/src/validationinterface.h index 6a8059a6a0..63aad8661f 100644 --- a/src/validationinterface.h +++ b/src/validationinterface.h @@ -21,8 +21,6 @@ class CConnman; class CValidationInterface; class uint256; class CScheduler; -class CTxMemPool; -enum class MemPoolRemovalReason; // These functions dispatch to one or all registered wallets @@ -158,8 +156,6 @@ private: friend void ::UnregisterAllValidationInterfaces(); friend void ::CallFunctionInValidationInterfaceQueue(std::function<void ()> func); - void MempoolEntryRemoved(CTransactionRef tx, MemPoolRemovalReason reason); - public: /** Register a CScheduler to give callbacks which should run in the background (may only be called once) */ void RegisterBackgroundSignalScheduler(CScheduler& scheduler); @@ -170,13 +166,10 @@ public: size_t CallbacksPending(); - /** Register with mempool to call TransactionRemovedFromMempool callbacks */ - void RegisterWithMempoolSignals(CTxMemPool& pool); - /** Unregister with mempool */ - void UnregisterWithMempoolSignals(CTxMemPool& pool); void UpdatedBlockTip(const CBlockIndex *, const CBlockIndex *, bool fInitialDownload); void TransactionAddedToMempool(const CTransactionRef &); + void TransactionRemovedFromMempool(const CTransactionRef &); void BlockConnected(const std::shared_ptr<const CBlock> &, const CBlockIndex *pindex, const std::shared_ptr<const std::vector<CTransactionRef>> &); void BlockDisconnected(const std::shared_ptr<const CBlock> &, const CBlockIndex* pindex); void ChainStateFlushed(const CBlockLocator &); diff --git a/src/wallet/coincontrol.h b/src/wallet/coincontrol.h index fca4b75c45..2893d0ab3d 100644 --- a/src/wallet/coincontrol.h +++ b/src/wallet/coincontrol.h @@ -6,14 +6,18 @@ #define BITCOIN_WALLET_COINCONTROL_H #include <optional.h> +#include <outputtype.h> #include <policy/feerate.h> #include <policy/fees.h> #include <primitives/transaction.h> -#include <wallet/wallet.h> +#include <script/standard.h> const int DEFAULT_MIN_DEPTH = 0; const int DEFAULT_MAX_DEPTH = 9999999; +//! Default for -avoidpartialspends +static constexpr bool DEFAULT_AVOIDPARTIALSPENDS = false; + /** Coin Control Features. */ class CCoinControl { diff --git a/src/wallet/feebumper.cpp b/src/wallet/feebumper.cpp index 8f0b495ac4..36588eb7d1 100644 --- a/src/wallet/feebumper.cpp +++ b/src/wallet/feebumper.cpp @@ -108,12 +108,11 @@ static feebumper::Result CheckFeeRate(const CWallet& wallet, const CWalletTx& wt return feebumper::Result::OK; } -static CFeeRate EstimateFeeRate(const CWallet& wallet, const CWalletTx& wtx, CCoinControl& coin_control, CAmount& old_fee) +static CFeeRate EstimateFeeRate(const CWallet& wallet, const CWalletTx& wtx, const CAmount old_fee, CCoinControl& coin_control) { // 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 // result. - old_fee = wtx.GetDebit(ISMINE_SPENDABLE) - wtx.tx->GetValueOut(); int64_t txSize = GetVirtualTransactionSize(*(wtx.tx)); CFeeRate feerate(old_fee, txSize); feerate += CFeeRate(1); @@ -309,6 +308,8 @@ Result CreateRateBumpTransaction(CWallet& wallet, const uint256& txid, const CCo } } + old_fee = wtx.GetDebit(ISMINE_SPENDABLE) - wtx.tx->GetValueOut(); + if (coin_control.m_feerate) { // The user provided a feeRate argument. // We calculate this here to avoid compiler warning on the cs_wallet lock @@ -319,7 +320,7 @@ Result CreateRateBumpTransaction(CWallet& wallet, const uint256& txid, const CCo } } else { // The user did not provide a feeRate argument - new_coin_control.m_feerate = EstimateFeeRate(wallet, wtx, new_coin_control, old_fee); + new_coin_control.m_feerate = EstimateFeeRate(wallet, wtx, old_fee, new_coin_control); } // Fill in required inputs we are double-spending(all of them) diff --git a/src/wallet/init.cpp b/src/wallet/init.cpp index a8b3df1f2e..dd0d2ffbd7 100644 --- a/src/wallet/init.cpp +++ b/src/wallet/init.cpp @@ -8,9 +8,11 @@ #include <net.h> #include <node/context.h> #include <outputtype.h> +#include <ui_interface.h> #include <util/moneystr.h> #include <util/system.h> #include <util/translation.h> +#include <wallet/coincontrol.h> #include <wallet/wallet.h> #include <walletinitinterface.h> @@ -58,7 +60,7 @@ void WalletInit::AddWalletOptions() const gArgs.AddArg("-upgradewallet", "Upgrade wallet to latest format on startup", ArgsManager::ALLOW_ANY, OptionsCategory::WALLET); gArgs.AddArg("-wallet=<path>", "Specify wallet database path. Can be specified multiple times to load multiple wallets. Path is interpreted relative to <walletdir> if it is not absolute, and will be created if it does not exist (as a directory containing a wallet.dat file and log files). For backwards compatibility this will also accept names of existing data files in <walletdir>.)", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::WALLET); gArgs.AddArg("-walletbroadcast", strprintf("Make the wallet broadcast transactions (default: %u)", DEFAULT_WALLETBROADCAST), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET); - gArgs.AddArg("-walletdir=<dir>", "Specify directory to hold wallets (default: <datadir>/wallets if it exists, otherwise <datadir>)", ArgsManager::ALLOW_ANY, OptionsCategory::WALLET); + gArgs.AddArg("-walletdir=<dir>", "Specify directory to hold wallets (default: <datadir>/wallets if it exists, otherwise <datadir>)", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::WALLET); #if HAVE_SYSTEM gArgs.AddArg("-walletnotify=<cmd>", "Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)", ArgsManager::ALLOW_ANY, OptionsCategory::WALLET); #endif diff --git a/src/wallet/psbtwallet.cpp b/src/wallet/psbtwallet.cpp index aa13cacca4..96c1ad8d3f 100644 --- a/src/wallet/psbtwallet.cpp +++ b/src/wallet/psbtwallet.cpp @@ -39,12 +39,35 @@ TransactionError FillPSBT(const CWallet* pwallet, PartiallySignedTransaction& ps return TransactionError::SIGHASH_MISMATCH; } - complete &= SignPSBTInput(HidingSigningProvider(pwallet->GetSigningProvider(), !sign, !bip32derivs), psbtx, i, sighash_type); + // Get the scriptPubKey to know which SigningProvider to use + CScript script; + if (!input.witness_utxo.IsNull()) { + script = input.witness_utxo.scriptPubKey; + } else if (input.non_witness_utxo) { + script = input.non_witness_utxo->vout[txin.prevout.n].scriptPubKey; + } else { + // There's no UTXO so we can just skip this now + complete = false; + continue; + } + SignatureData sigdata; + input.FillSignatureData(sigdata); + const SigningProvider* provider = pwallet->GetSigningProvider(script, sigdata); + if (!provider) { + complete = false; + continue; + } + + complete &= SignPSBTInput(HidingSigningProvider(provider, !sign, !bip32derivs), psbtx, i, sighash_type); } // Fill in the bip32 keypaths and redeemscripts for the outputs so that hardware wallets can identify change for (unsigned int i = 0; i < psbtx.tx->vout.size(); ++i) { - UpdatePSBTOutput(HidingSigningProvider(pwallet->GetSigningProvider(), true, !bip32derivs), psbtx, i); + const CTxOut& out = psbtx.tx->vout.at(i); + const SigningProvider* provider = pwallet->GetSigningProvider(out.scriptPubKey); + if (provider) { + UpdatePSBTOutput(HidingSigningProvider(provider, true, !bip32derivs), psbtx, i); + } } return TransactionError::OK; diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 00742aed7a..d906f6ddf0 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -560,7 +560,11 @@ static UniValue signmessage(const JSONRPCRequest& request) throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key"); } - const SigningProvider* provider = pwallet->GetSigningProvider(); + CScript script_pub_key = GetScriptForDestination(*pkhash); + const SigningProvider* provider = pwallet->GetSigningProvider(script_pub_key); + if (!provider) { + throw JSONRPCError(RPC_WALLET_ERROR, "Private key not available"); + } CKey key; CKeyID keyID(*pkhash); @@ -947,7 +951,7 @@ static UniValue addmultisigaddress(const JSONRPCRequest& request) } RPCHelpMan{"addmultisigaddress", - "\nAdd a nrequired-to-sign multisignature address to the wallet. Requires a new wallet backup.\n" + "\nAdd an nrequired-to-sign multisignature address to the wallet. Requires a new wallet backup.\n" "Each key is a Bitcoin address or hex-encoded public key.\n" "This functionality is only intended for use with non-watchonly addresses.\n" "See `importaddress` for watchonly p2sh address support.\n" @@ -994,7 +998,7 @@ static UniValue addmultisigaddress(const JSONRPCRequest& request) if (IsHex(keys_or_addrs[i].get_str()) && (keys_or_addrs[i].get_str().length() == 66 || keys_or_addrs[i].get_str().length() == 130)) { pubkeys.push_back(HexToPubKey(keys_or_addrs[i].get_str())); } else { - pubkeys.push_back(AddrToPubKey(&spk_man, keys_or_addrs[i].get_str())); + pubkeys.push_back(AddrToPubKey(spk_man, keys_or_addrs[i].get_str())); } } @@ -2940,34 +2944,36 @@ static UniValue listunspent(const JSONRPCRequest& request) entry.pushKV("label", i->second.name); } - const SigningProvider* provider = pwallet->GetSigningProvider(); - if (scriptPubKey.IsPayToScriptHash()) { - const CScriptID& hash = CScriptID(boost::get<ScriptHash>(address)); - CScript redeemScript; - if (provider->GetCScript(hash, redeemScript)) { - entry.pushKV("redeemScript", HexStr(redeemScript.begin(), redeemScript.end())); - // Now check if the redeemScript is actually a P2WSH script - CTxDestination witness_destination; - if (redeemScript.IsPayToWitnessScriptHash()) { - bool extracted = ExtractDestination(redeemScript, witness_destination); - CHECK_NONFATAL(extracted); - // Also return the witness script - const WitnessV0ScriptHash& whash = boost::get<WitnessV0ScriptHash>(witness_destination); - CScriptID id; - CRIPEMD160().Write(whash.begin(), whash.size()).Finalize(id.begin()); - CScript witnessScript; - if (provider->GetCScript(id, witnessScript)) { - entry.pushKV("witnessScript", HexStr(witnessScript.begin(), witnessScript.end())); + const SigningProvider* provider = pwallet->GetSigningProvider(scriptPubKey); + if (provider) { + if (scriptPubKey.IsPayToScriptHash()) { + const CScriptID& hash = CScriptID(boost::get<ScriptHash>(address)); + CScript redeemScript; + if (provider->GetCScript(hash, redeemScript)) { + entry.pushKV("redeemScript", HexStr(redeemScript.begin(), redeemScript.end())); + // Now check if the redeemScript is actually a P2WSH script + CTxDestination witness_destination; + if (redeemScript.IsPayToWitnessScriptHash()) { + bool extracted = ExtractDestination(redeemScript, witness_destination); + CHECK_NONFATAL(extracted); + // Also return the witness script + const WitnessV0ScriptHash& whash = boost::get<WitnessV0ScriptHash>(witness_destination); + CScriptID id; + CRIPEMD160().Write(whash.begin(), whash.size()).Finalize(id.begin()); + CScript witnessScript; + if (provider->GetCScript(id, witnessScript)) { + entry.pushKV("witnessScript", HexStr(witnessScript.begin(), witnessScript.end())); + } } } - } - } else if (scriptPubKey.IsPayToWitnessScriptHash()) { - const WitnessV0ScriptHash& whash = boost::get<WitnessV0ScriptHash>(address); - CScriptID id; - CRIPEMD160().Write(whash.begin(), whash.size()).Finalize(id.begin()); - CScript witnessScript; - if (provider->GetCScript(id, witnessScript)) { - entry.pushKV("witnessScript", HexStr(witnessScript.begin(), witnessScript.end())); + } else if (scriptPubKey.IsPayToWitnessScriptHash()) { + const WitnessV0ScriptHash& whash = boost::get<WitnessV0ScriptHash>(address); + CScriptID id; + CRIPEMD160().Write(whash.begin(), whash.size()).Finalize(id.begin()); + CScript witnessScript; + if (provider->GetCScript(id, witnessScript)) { + entry.pushKV("witnessScript", HexStr(witnessScript.begin(), witnessScript.end())); + } } } } @@ -2978,8 +2984,11 @@ static UniValue listunspent(const JSONRPCRequest& request) entry.pushKV("spendable", out.fSpendable); entry.pushKV("solvable", out.fSolvable); if (out.fSolvable) { - auto descriptor = InferDescriptor(scriptPubKey, *pwallet->GetLegacyScriptPubKeyMan()); - entry.pushKV("desc", descriptor->ToString()); + const SigningProvider* provider = pwallet->GetSigningProvider(scriptPubKey); + if (provider) { + auto descriptor = InferDescriptor(scriptPubKey, *provider); + entry.pushKV("desc", descriptor->ToString()); + } } if (avoid_reuse) entry.pushKV("reused", reused); entry.pushKV("safe", out.fSafe); @@ -3288,7 +3297,23 @@ UniValue signrawtransactionwithwallet(const JSONRPCRequest& request) // Parse the prevtxs array ParsePrevouts(request.params[1], nullptr, coins); - return SignTransaction(mtx, &*pwallet->GetLegacyScriptPubKeyMan(), coins, request.params[2]); + std::set<const SigningProvider*> providers; + for (const std::pair<COutPoint, Coin> coin_pair : coins) { + const SigningProvider* provider = pwallet->GetSigningProvider(coin_pair.second.out.scriptPubKey); + if (provider) { + providers.insert(std::move(provider)); + } + } + if (providers.size() == 0) { + // When there are no available providers, use DUMMY_SIGNING_PROVIDER so we can check if the tx is complete + providers.insert(&DUMMY_SIGNING_PROVIDER); + } + + UniValue result(UniValue::VOBJ); + for (const SigningProvider* provider : providers) { + SignTransaction(mtx, provider, coins, request.params[2], result); + } + return result; } static UniValue bumpfee(const JSONRPCRequest& request) @@ -3653,9 +3678,10 @@ static UniValue DescribeWalletAddress(CWallet* pwallet, const CTxDestination& de { UniValue ret(UniValue::VOBJ); UniValue detail = DescribeAddress(dest); + CScript script = GetScriptForDestination(dest); const SigningProvider* provider = nullptr; if (pwallet) { - provider = pwallet->GetSigningProvider(); + provider = pwallet->GetSigningProvider(script); } ret.pushKVs(detail); ret.pushKVs(boost::apply_visitor(DescribeWalletAddressVisitor(provider), dest)); @@ -3683,52 +3709,57 @@ UniValue getaddressinfo(const JSONRPCRequest& request) } RPCHelpMan{"getaddressinfo", - "\nReturn information about the given bitcoin address. Some information requires the address\n" - "to be in the wallet.\n", + "\nReturn information about the given bitcoin address.\n" + "Some of the information will only be present if the address is in the active wallet.\n", { - {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The bitcoin address to get the information of."}, + {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The bitcoin address for which to get information."}, }, RPCResult{ "{\n" - " \"address\" : \"address\", (string) The bitcoin address validated\n" - " \"scriptPubKey\" : \"hex\", (string) The hex-encoded scriptPubKey generated by the address\n" - " \"ismine\" : true|false, (boolean) If the address is yours or not\n" - " \"iswatchonly\" : true|false, (boolean) If the address is watchonly\n" - " \"solvable\" : true|false, (boolean) Whether we know how to spend coins sent to this address, ignoring the possible lack of private keys\n" - " \"desc\" : \"desc\", (string, optional) A descriptor for spending coins sent to this address (only when solvable)\n" - " \"isscript\" : true|false, (boolean) If the key is a script\n" - " \"ischange\" : true|false, (boolean) If the address was used for change output\n" - " \"iswitness\" : true|false, (boolean) If the address is a witness address\n" - " \"witness_version\" : version (numeric, optional) The version number of the witness program\n" - " \"witness_program\" : \"hex\" (string, optional) The hex value of the witness program\n" - " \"script\" : \"type\" (string, optional) The output script type. Only if \"isscript\" is true and the redeemscript is known. Possible types: nonstandard, pubkey, pubkeyhash, scripthash, multisig, nulldata, witness_v0_keyhash, witness_v0_scripthash, witness_unknown\n" - " \"hex\" : \"hex\", (string, optional) The redeemscript for the p2sh address\n" - " \"pubkeys\" (string, optional) Array of pubkeys associated with the known redeemscript (only if \"script\" is \"multisig\")\n" + " \"address\" : \"address\", (string) The bitcoin address validated.\n" + " \"scriptPubKey\" : \"hex\", (string) The hex-encoded scriptPubKey generated by the address.\n" + " \"ismine\" : true|false, (boolean) If the address is yours.\n" + " \"iswatchonly\" : true|false, (boolean) If the address is watchonly.\n" + " \"solvable\" : true|false, (boolean) If we know how to spend coins sent to this address, ignoring the possible lack of private keys.\n" + " \"desc\" : \"desc\", (string, optional) A descriptor for spending coins sent to this address (only when solvable).\n" + " \"isscript\" : true|false, (boolean) If the key is a script.\n" + " \"ischange\" : true|false, (boolean) If the address was used for change output.\n" + " \"iswitness\" : true|false, (boolean) If the address is a witness address.\n" + " \"witness_version\" : version (numeric, optional) The version number of the witness program.\n" + " \"witness_program\" : \"hex\" (string, optional) The hex value of the witness program.\n" + " \"script\" : \"type\" (string, optional) The output script type. Only if isscript is true and the redeemscript is known. Possible\n" + " types: nonstandard, pubkey, pubkeyhash, scripthash, multisig, nulldata, witness_v0_keyhash,\n" + " witness_v0_scripthash, witness_unknown.\n" + " \"hex\" : \"hex\", (string, optional) The redeemscript for the p2sh address.\n" + " \"pubkeys\" (array, optional) Array of pubkeys associated with the known redeemscript (only if script is multisig).\n" " [\n" - " \"pubkey\"\n" + " \"pubkey\" (string)\n" " ,...\n" " ]\n" - " \"sigsrequired\" : xxxxx (numeric, optional) Number of signatures required to spend multisig output (only if \"script\" is \"multisig\")\n" - " \"pubkey\" : \"publickeyhex\", (string, optional) The hex value of the raw public key, for single-key addresses (possibly embedded in P2SH or P2WSH)\n" - " \"embedded\" : {...}, (object, optional) Information about the address embedded in P2SH or P2WSH, if relevant and known. It includes all getaddressinfo output fields for the embedded address, excluding metadata (\"timestamp\", \"hdkeypath\", \"hdseedid\") and relation to the wallet (\"ismine\", \"iswatchonly\").\n" - " \"iscompressed\" : true|false, (boolean, optional) If the pubkey is compressed\n" - " \"label\" : \"label\" (string) The label associated with the address, \"\" is the default label\n" - " \"timestamp\" : timestamp, (number, optional) The creation time of the key if available in seconds since epoch (Jan 1 1970 GMT)\n" - " \"hdkeypath\" : \"keypath\" (string, optional) The HD keypath if the key is HD and available\n" - " \"hdseedid\" : \"<hash160>\" (string, optional) The Hash160 of the HD seed\n" - " \"hdmasterfingerprint\" : \"<hash160>\" (string, optional) The fingperint of the master key.\n" - " \"labels\" (object) Array of labels associated with the address.\n" + " \"sigsrequired\" : xxxxx (numeric, optional) The number of signatures required to spend multisig output (only if script is multisig).\n" + " \"pubkey\" : \"publickeyhex\", (string, optional) The hex value of the raw public key for single-key addresses (possibly embedded in P2SH or P2WSH).\n" + " \"embedded\" : {...}, (object, optional) Information about the address embedded in P2SH or P2WSH, if relevant and known. Includes all\n" + " getaddressinfo output fields for the embedded address, excluding metadata (timestamp, hdkeypath,\n" + " hdseedid) and relation to the wallet (ismine, iswatchonly).\n" + " \"iscompressed\" : true|false, (boolean, optional) If the pubkey is compressed.\n" + " \"label\" : \"label\" (string) The label associated with the address. Defaults to \"\". Equivalent to the name field in the labels array.\n" + " \"timestamp\" : timestamp, (number, optional) The creation time of the key if available, expressed in seconds since Epoch Time (Jan 1 1970 GMT).\n" + " \"hdkeypath\" : \"keypath\" (string, optional) The HD keypath, if the key is HD and available.\n" + " \"hdseedid\" : \"<hash160>\" (string, optional) The Hash160 of the HD seed.\n" + " \"hdmasterfingerprint\" : \"<hash160>\" (string, optional) The fingerprint of the master key.\n" + " \"labels\" (object) An array of labels associated with the address. Currently limited to one label but returned\n" + " as an array to keep the API stable if multiple labels are enabled in the future.\n" " [\n" " { (json object of label data)\n" - " \"name\": \"labelname\" (string) The label\n" - " \"purpose\": \"string\" (string) Purpose of address (\"send\" for sending address, \"receive\" for receiving address)\n" + " \"name\": \"label name\" (string) The label name. Defaults to \"\". Equivalent to the label field above.\n" + " \"purpose\": \"purpose\" (string) The purpose of the associated address (send or receive).\n" " },...\n" " ]\n" "}\n" }, RPCExamples{ - HelpExampleCli("getaddressinfo", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"") - + HelpExampleRpc("getaddressinfo", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"") + HelpExampleCli("getaddressinfo", "\"bc1q09vm5lfy0j5reeulh4x5752q25uqqvz34hufdl\"") + + HelpExampleRpc("getaddressinfo", "\"bc1q09vm5lfy0j5reeulh4x5752q25uqqvz34hufdl\"") }, }.Check(request); @@ -3747,24 +3778,40 @@ UniValue getaddressinfo(const JSONRPCRequest& request) CScript scriptPubKey = GetScriptForDestination(dest); ret.pushKV("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end())); - const SigningProvider* provider = pwallet->GetSigningProvider(); + + const SigningProvider* provider = pwallet->GetSigningProvider(scriptPubKey); isminetype mine = pwallet->IsMine(dest); ret.pushKV("ismine", bool(mine & ISMINE_SPENDABLE)); - bool solvable = IsSolvable(*provider, scriptPubKey); + + bool solvable = provider && IsSolvable(*provider, scriptPubKey); ret.pushKV("solvable", solvable); + if (solvable) { ret.pushKV("desc", InferDescriptor(scriptPubKey, *provider)->ToString()); } + ret.pushKV("iswatchonly", bool(mine & ISMINE_WATCH_ONLY)); + + // Return DescribeWalletAddress fields. + // Always returned: isscript, ischange, iswitness. + // Optional: witness_version, witness_program, script, hex, pubkeys (array), + // sigsrequired, pubkey, embedded, iscompressed. UniValue detail = DescribeWalletAddress(pwallet, dest); ret.pushKVs(detail); + + // Return label field if existing. Currently only one label can be + // associated with an address, so the label should be equivalent to the + // value of the name key/value pair in the labels hash array below. if (pwallet->mapAddressBook.count(dest)) { ret.pushKV("label", pwallet->mapAddressBook[dest].name); } + ret.pushKV("ischange", pwallet->IsChange(scriptPubKey)); - ScriptPubKeyMan* spk_man = pwallet->GetScriptPubKeyMan(); + // Fetch KeyMetadata, if present, for the timestamp, hdkeypath, hdseedid, + // and hdmasterfingerprint fields. + ScriptPubKeyMan* spk_man = pwallet->GetScriptPubKeyMan(scriptPubKey); if (spk_man) { if (const CKeyMetadata* meta = spk_man->GetMetadata(dest)) { ret.pushKV("timestamp", meta->nCreateTime); @@ -3776,9 +3823,11 @@ UniValue getaddressinfo(const JSONRPCRequest& request) } } - // Currently only one label can be associated with an address, return an array - // so the API remains stable if we allow multiple labels to be associated with - // an address. + // Return a labels array containing a hash of key/value pairs for the label + // name and address purpose. The name value is equivalent to the label field + // above. Currently only one label can be associated with an address, but we + // return an array so the API remains stable if we allow multiple labels to + // be associated with an address in the future. UniValue labels(UniValue::VARR); std::map<CTxDestination, CAddressBookData>::iterator mi = pwallet->mapAddressBook.find(dest); if (mi != pwallet->mapAddressBook.end()) { diff --git a/src/wallet/test/coinselector_tests.cpp b/src/wallet/test/coinselector_tests.cpp index bc068f1499..7e9f88f6b7 100644 --- a/src/wallet/test/coinselector_tests.cpp +++ b/src/wallet/test/coinselector_tests.cpp @@ -55,7 +55,7 @@ static void add_coin(const CAmount& nValue, int nInput, CoinSet& set) set.emplace(MakeTransactionRef(tx), nInput); } -static void add_coin(const CAmount& nValue, int nAge = 6*24, bool fIsFromMe = false, int nInput=0) +static void add_coin(CWallet& wallet, const CAmount& nValue, int nAge = 6*24, bool fIsFromMe = false, int nInput=0, bool spendable = false) { balance += nValue; static int nextLockTime = 0; @@ -63,21 +63,31 @@ static void add_coin(const CAmount& nValue, int nAge = 6*24, bool fIsFromMe = fa tx.nLockTime = nextLockTime++; // so all transactions get different hashes tx.vout.resize(nInput + 1); tx.vout[nInput].nValue = nValue; + if (spendable) { + CTxDestination dest; + std::string error; + assert(wallet.GetNewDestination(OutputType::BECH32, "", dest, error)); + tx.vout[nInput].scriptPubKey = GetScriptForDestination(dest); + } if (fIsFromMe) { // IsFromMe() returns (GetDebit() > 0), and GetDebit() is 0 if vin.empty(), // so stop vin being empty, and cache a non-zero Debit to fake out IsFromMe() tx.vin.resize(1); } - std::unique_ptr<CWalletTx> wtx = MakeUnique<CWalletTx>(&testWallet, MakeTransactionRef(std::move(tx))); + std::unique_ptr<CWalletTx> wtx = MakeUnique<CWalletTx>(&wallet, MakeTransactionRef(std::move(tx))); if (fIsFromMe) { wtx->m_amounts[CWalletTx::DEBIT].Set(ISMINE_SPENDABLE, 1); } COutput output(wtx.get(), nInput, nAge, true /* spendable */, true /* solvable */, true /* safe */); vCoins.push_back(output); - testWallet.AddToWallet(*wtx.get()); + wallet.AddToWallet(*wtx.get()); wtxn.emplace_back(std::move(wtx)); } +static void add_coin(const CAmount& nValue, int nAge = 6*24, bool fIsFromMe = false, int nInput=0, bool spendable = false) +{ + add_coin(testWallet, nValue, nAge, fIsFromMe, nInput, spendable); +} static void empty_wallet(void) { @@ -252,17 +262,33 @@ BOOST_AUTO_TEST_CASE(bnb_search_test) vCoins.at(0).nInputBytes = 40; // Make sure that it has a negative effective value. The next check should assert if this somehow got through. Otherwise it will fail BOOST_CHECK(!testWallet.SelectCoinsMinConf( 1 * CENT, filter_standard, GroupCoins(vCoins), setCoinsRet, nValueRet, coin_selection_params_bnb, bnb_used)); - // Make sure that we aren't using BnB when there are preset inputs + // Test fees subtracted from output: + empty_wallet(); + add_coin(1 * CENT); + vCoins.at(0).nInputBytes = 40; + BOOST_CHECK(!testWallet.SelectCoinsMinConf( 1 * CENT, filter_standard, GroupCoins(vCoins), setCoinsRet, nValueRet, coin_selection_params_bnb, bnb_used)); + coin_selection_params_bnb.m_subtract_fee_outputs = true; + BOOST_CHECK(testWallet.SelectCoinsMinConf( 1 * CENT, filter_standard, GroupCoins(vCoins), setCoinsRet, nValueRet, coin_selection_params_bnb, bnb_used)); + BOOST_CHECK_EQUAL(nValueRet, 1 * CENT); + + // Make sure that can use BnB when there are preset inputs empty_wallet(); - add_coin(5 * CENT); - add_coin(3 * CENT); - add_coin(2 * CENT); - CCoinControl coin_control; - coin_control.fAllowOtherInputs = true; - coin_control.Select(COutPoint(vCoins.at(0).tx->GetHash(), vCoins.at(0).i)); - BOOST_CHECK(testWallet.SelectCoins(vCoins, 10 * CENT, setCoinsRet, nValueRet, coin_control, coin_selection_params_bnb, bnb_used)); - BOOST_CHECK(!bnb_used); - BOOST_CHECK(!coin_selection_params_bnb.use_bnb); + { + std::unique_ptr<CWallet> wallet = MakeUnique<CWallet>(m_chain.get(), WalletLocation(), WalletDatabase::CreateMock()); + bool firstRun; + wallet->LoadWallet(firstRun); + LOCK(wallet->cs_wallet); + add_coin(*wallet, 5 * CENT, 6 * 24, false, 0, true); + add_coin(*wallet, 3 * CENT, 6 * 24, false, 0, true); + add_coin(*wallet, 2 * CENT, 6 * 24, false, 0, true); + CCoinControl coin_control; + coin_control.fAllowOtherInputs = true; + coin_control.Select(COutPoint(vCoins.at(0).tx->GetHash(), vCoins.at(0).i)); + coin_selection_params_bnb.effective_fee = CFeeRate(0); + BOOST_CHECK(wallet->SelectCoins(vCoins, 10 * CENT, setCoinsRet, nValueRet, coin_control, coin_selection_params_bnb, bnb_used)); + BOOST_CHECK(bnb_used); + BOOST_CHECK(coin_selection_params_bnb.use_bnb); + } } BOOST_AUTO_TEST_CASE(knapsack_solver_test) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 2f2931cef1..0a8ce7caf1 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -822,7 +822,7 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose) void CWallet::LoadToWallet(CWalletTx& wtxIn) { - // If wallet doesn't have a chain (e.g wallet-tool), lock can't be taken. + // If wallet doesn't have a chain (e.g bitcoin-wallet), lock can't be taken. auto locked_chain = LockChain(); if (locked_chain) { Optional<int> block_height = locked_chain->getBlockHeight(wtxIn.m_confirm.hashBlock); @@ -1363,7 +1363,11 @@ bool CWallet::DummySignInput(CTxIn &tx_in, const CTxOut &txout, bool use_max_sig const CScript& scriptPubKey = txout.scriptPubKey; SignatureData sigdata; - const SigningProvider* provider = GetSigningProvider(); + const SigningProvider* provider = GetSigningProvider(scriptPubKey); + if (!provider) { + // We don't know about this scriptpbuKey; + return false; + } if (!ProduceSignature(*provider, use_max_sig ? DUMMY_MAXIMUM_SIGNATURE_CREATOR : DUMMY_SIGNATURE_CREATOR, scriptPubKey, sigdata)) { return false; @@ -1444,11 +1448,9 @@ bool CWallet::ImportScriptPubKeys(const std::string& label, const std::set<CScri int64_t CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wallet, bool use_max_sig) { std::vector<CTxOut> txouts; - // Look up the inputs. We should have already checked that this transaction - // IsAllFromMe(ISMINE_SPENDABLE), so every input should already be in our - // wallet, with a valid index into the vout array, and the ability to sign. for (const CTxIn& input : tx.vin) { const auto mi = wallet->mapWallet.find(input.prevout.hash); + // Can not estimate size without knowing the input details if (mi == wallet->mapWallet.end()) { return -1; } @@ -1463,8 +1465,6 @@ int64_t CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wall { CMutableTransaction txNew(tx); if (!wallet->DummySignTx(txNew, txouts, use_max_sig)) { - // This should never happen, because IsAllFromMe(ISMINE_SPENDABLE) - // implies that we can sign for every input. return -1; } return GetVirtualTransactionSize(CTransaction(txNew)); @@ -2125,7 +2125,7 @@ void CWallet::AvailableCoins(interfaces::Chain::Lock& locked_chain, std::vector< continue; } - const SigningProvider* provider = GetSigningProvider(); + const SigningProvider* provider = GetSigningProvider(wtx.tx->vout[i].scriptPubKey); bool solvable = provider ? IsSolvable(*provider, wtx.tx->vout[i].scriptPubKey) : false; bool spendable = ((mine & ISMINE_SPENDABLE) != ISMINE_NO) || (((mine & ISMINE_WATCH_ONLY) != ISMINE_NO) && (coinControl && coinControl->fAllowWatchOnly && solvable)); @@ -2160,7 +2160,7 @@ std::map<CTxDestination, std::vector<COutput>> CWallet::ListCoins(interfaces::Ch for (const COutput& coin : availableCoins) { CTxDestination address; - if (coin.fSpendable && + if ((coin.fSpendable || (IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) && coin.fSolvable)) && ExtractDestination(FindNonChangeParentOutput(*coin.tx->tx, coin.i).scriptPubKey, address)) { result[address].emplace_back(std::move(coin)); } @@ -2168,12 +2168,16 @@ std::map<CTxDestination, std::vector<COutput>> CWallet::ListCoins(interfaces::Ch std::vector<COutPoint> lockedCoins; ListLockedCoins(lockedCoins); + // Include watch-only for wallets without private keys + const bool include_watch_only = IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS); + const isminetype is_mine_filter = include_watch_only ? ISMINE_WATCH_ONLY : ISMINE_SPENDABLE; for (const COutPoint& output : lockedCoins) { auto it = mapWallet.find(output.hash); if (it != mapWallet.end()) { int depth = it->second.GetDepthInMainChain(); if (depth >= 0 && output.n < it->second.tx->vout.size() && - IsMine(it->second.tx->vout[output.n]) == ISMINE_SPENDABLE) { + IsMine(it->second.tx->vout[output.n]) == is_mine_filter + ) { CTxDestination address; if (ExtractDestination(FindNonChangeParentOutput(*it->second.tx, output.n).scriptPubKey, address)) { result[address].emplace_back( @@ -2234,7 +2238,11 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, const CoinEligibil if (effective_value > 0) { group.fee += coin.m_input_bytes < 0 ? 0 : coin_selection_params.effective_fee.GetFee(coin.m_input_bytes); group.long_term_fee += coin.m_input_bytes < 0 ? 0 : long_term_feerate.GetFee(coin.m_input_bytes); - group.effective_value += effective_value; + if (coin_selection_params.m_subtract_fee_outputs) { + group.effective_value += coin.txout.nValue; + } else { + group.effective_value += effective_value; + } ++it; } else { it = group.Discard(coin); @@ -2260,13 +2268,14 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, const CoinEligibil bool CWallet::SelectCoins(const std::vector<COutput>& vAvailableCoins, const CAmount& nTargetValue, std::set<CInputCoin>& setCoinsRet, CAmount& nValueRet, const CCoinControl& coin_control, CoinSelectionParams& coin_selection_params, bool& bnb_used) const { std::vector<COutput> vCoins(vAvailableCoins); + CAmount value_to_select = nTargetValue; + + // Default to bnb was not used. If we use it, we set it later + bnb_used = false; // coin control -> return all selected outputs (we want all selected to go into the transaction for sure) if (coin_control.HasSelected() && !coin_control.fAllowOtherInputs) { - // We didn't use BnB here, so set it to false. - bnb_used = false; - for (const COutput& out : vCoins) { if (!out.fSpendable) @@ -2285,22 +2294,30 @@ bool CWallet::SelectCoins(const std::vector<COutput>& vAvailableCoins, const CAm coin_control.ListSelected(vPresetInputs); for (const COutPoint& outpoint : vPresetInputs) { - // For now, don't use BnB if preset inputs are selected. TODO: Enable this later - bnb_used = false; - coin_selection_params.use_bnb = false; - std::map<uint256, CWalletTx>::const_iterator it = mapWallet.find(outpoint.hash); if (it != mapWallet.end()) { const CWalletTx& wtx = it->second; // Clearly invalid input, fail - if (wtx.tx->vout.size() <= outpoint.n) + if (wtx.tx->vout.size() <= outpoint.n) { return false; + } // Just to calculate the marginal byte size - nValueFromPresetInputs += wtx.tx->vout[outpoint.n].nValue; - setPresetCoins.insert(CInputCoin(wtx.tx, outpoint.n)); - } else + CInputCoin coin(wtx.tx, outpoint.n, wtx.GetSpendSize(outpoint.n, false)); + nValueFromPresetInputs += coin.txout.nValue; + if (coin.m_input_bytes <= 0) { + return false; // Not solvable, can't estimate size for fee + } + coin.effective_value = coin.txout.nValue - coin_selection_params.effective_fee.GetFee(coin.m_input_bytes); + if (coin_selection_params.use_bnb) { + value_to_select -= coin.effective_value; + } else { + value_to_select -= coin.txout.nValue; + } + setPresetCoins.insert(coin); + } else { return false; // TODO: Allow non-wallet inputs + } } // remove preset inputs from vCoins @@ -2329,14 +2346,14 @@ bool CWallet::SelectCoins(const std::vector<COutput>& vAvailableCoins, const CAm 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 || - SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, CoinEligibilityFilter(1, 6, 0), groups, setCoinsRet, nValueRet, coin_selection_params, bnb_used) || - SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, CoinEligibilityFilter(1, 1, 0), groups, setCoinsRet, nValueRet, coin_selection_params, bnb_used) || - (m_spend_zero_conf_change && SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, CoinEligibilityFilter(0, 1, 2), groups, setCoinsRet, nValueRet, coin_selection_params, bnb_used)) || - (m_spend_zero_conf_change && SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, CoinEligibilityFilter(0, 1, std::min((size_t)4, max_ancestors/3), std::min((size_t)4, max_descendants/3)), groups, setCoinsRet, nValueRet, coin_selection_params, bnb_used)) || - (m_spend_zero_conf_change && SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, CoinEligibilityFilter(0, 1, max_ancestors/2, max_descendants/2), groups, setCoinsRet, nValueRet, coin_selection_params, bnb_used)) || - (m_spend_zero_conf_change && SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, CoinEligibilityFilter(0, 1, max_ancestors-1, max_descendants-1), groups, setCoinsRet, nValueRet, coin_selection_params, bnb_used)) || - (m_spend_zero_conf_change && !fRejectLongChains && SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, CoinEligibilityFilter(0, 1, std::numeric_limits<uint64_t>::max()), groups, setCoinsRet, nValueRet, coin_selection_params, bnb_used)); + bool res = value_to_select <= 0 || + SelectCoinsMinConf(value_to_select, CoinEligibilityFilter(1, 6, 0), groups, setCoinsRet, nValueRet, coin_selection_params, bnb_used) || + SelectCoinsMinConf(value_to_select, CoinEligibilityFilter(1, 1, 0), groups, setCoinsRet, nValueRet, coin_selection_params, bnb_used) || + (m_spend_zero_conf_change && SelectCoinsMinConf(value_to_select, CoinEligibilityFilter(0, 1, 2), groups, setCoinsRet, nValueRet, coin_selection_params, bnb_used)) || + (m_spend_zero_conf_change && SelectCoinsMinConf(value_to_select, CoinEligibilityFilter(0, 1, std::min((size_t)4, max_ancestors/3), std::min((size_t)4, max_descendants/3)), groups, setCoinsRet, nValueRet, coin_selection_params, bnb_used)) || + (m_spend_zero_conf_change && SelectCoinsMinConf(value_to_select, CoinEligibilityFilter(0, 1, max_ancestors/2, max_descendants/2), groups, setCoinsRet, nValueRet, coin_selection_params, bnb_used)) || + (m_spend_zero_conf_change && SelectCoinsMinConf(value_to_select, CoinEligibilityFilter(0, 1, max_ancestors-1, max_descendants-1), groups, setCoinsRet, nValueRet, coin_selection_params, bnb_used)) || + (m_spend_zero_conf_change && !fRejectLongChains && SelectCoinsMinConf(value_to_select, CoinEligibilityFilter(0, 1, std::numeric_limits<uint64_t>::max()), groups, setCoinsRet, nValueRet, coin_selection_params, bnb_used)); // because SelectCoinsMinConf clears the setCoinsRet, we now add the possible inputs to the coinset util::insert(setCoinsRet, setPresetCoins); @@ -2362,8 +2379,9 @@ bool CWallet::SignTransaction(CMutableTransaction& tx) const CAmount& amount = mi->second.tx->vout[input.prevout.n].nValue; SignatureData sigdata; - const SigningProvider* provider = GetSigningProvider(); + const SigningProvider* provider = GetSigningProvider(scriptPubKey); if (!provider) { + // We don't know about this scriptpbuKey; return false; } @@ -2519,7 +2537,8 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std int& nChangePosInOut, std::string& strFailReason, const CCoinControl& coin_control, bool sign) { CAmount nValue = 0; - ReserveDestination reservedest(this); + const OutputType change_type = TransactionChangeType(coin_control.m_change_type ? *coin_control.m_change_type : m_default_change_type, vecSend); + ReserveDestination reservedest(this, change_type); int nChangePosRequest = nChangePosInOut; unsigned int nSubtractFeeFromAmount = 0; for (const auto& recipient : vecSend) @@ -2578,8 +2597,7 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std return false; } CTxDestination dest; - const OutputType change_type = TransactionChangeType(coin_control.m_change_type ? *coin_control.m_change_type : m_default_change_type, vecSend); - bool ret = reservedest.GetReservedDestination(change_type, dest, true); + bool ret = reservedest.GetReservedDestination(dest, true); if (!ret) { strFailReason = "Keypool ran out, please call keypoolrefill first"; @@ -2602,7 +2620,8 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std // BnB selector is the only selector used when this is true. // That should only happen on the first pass through the loop. - coin_selection_params.use_bnb = nSubtractFeeFromAmount == 0; // If we are doing subtract fee from recipient, then don't use BnB + coin_selection_params.use_bnb = true; + coin_selection_params.m_subtract_fee_outputs = nSubtractFeeFromAmount != 0; // If we are doing subtract fee from recipient, don't use effective values // Start with no fee and loop until there is enough fee while (true) { @@ -2616,7 +2635,9 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std nValueToSelect += nFeeRet; // vouts to the payees - coin_selection_params.tx_noinputs_size = 11; // Static vsize overhead + outputs vsize. 4 nVersion, 4 nLocktime, 1 input count, 1 output count, 1 witness overhead (dummy, flag, stack size) + if (!coin_selection_params.m_subtract_fee_outputs) { + coin_selection_params.tx_noinputs_size = 11; // Static vsize overhead + outputs vsize. 4 nVersion, 4 nLocktime, 1 input count, 1 output count, 1 witness overhead (dummy, flag, stack size) + } for (const auto& recipient : vecSend) { CTxOut txout(recipient.nAmount, recipient.scriptPubKey); @@ -2633,7 +2654,9 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std } } // Include the fee cost for outputs. Note this is only used for BnB right now - coin_selection_params.tx_noinputs_size += ::GetSerializeSize(txout, PROTOCOL_VERSION); + if (!coin_selection_params.m_subtract_fee_outputs) { + coin_selection_params.tx_noinputs_size += ::GetSerializeSize(txout, PROTOCOL_VERSION); + } if (IsDust(txout, chain().relayDustFee())) { @@ -2652,7 +2675,7 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std } // Choose coins to use - bool bnb_used; + bool bnb_used = false; if (pick_new_inputs) { nValueIn = 0; setCoins.clear(); @@ -2825,7 +2848,7 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std const CScript& scriptPubKey = coin.txout.scriptPubKey; SignatureData sigdata; - const SigningProvider* provider = GetSigningProvider(); + const SigningProvider* provider = GetSigningProvider(scriptPubKey); if (!provider || !ProduceSignature(*provider, MutableTransactionSignatureCreator(&txNew, nIn, coin.txout.nValue, SIGHASH_ALL), scriptPubKey, sigdata)) { strFailReason = _("Signing transaction failed").translated; @@ -2921,7 +2944,7 @@ DBErrors CWallet::LoadWallet(bool& fFirstRunRet) { // Even if we don't use this lock in this function, we want to preserve // lock order in LoadToWallet if query of chain state is needed to know - // tx status. If lock can't be taken (e.g wallet-tool), tx confirmation + // tx status. If lock can't be taken (e.g bitcoin-wallet), tx confirmation // status may be not reliable. auto locked_chain = LockChain(); LOCK(cs_wallet); @@ -3098,8 +3121,8 @@ bool CWallet::GetNewChangeDestination(const OutputType type, CTxDestination& des m_spk_man->TopUp(); - ReserveDestination reservedest(this); - if (!reservedest.GetReservedDestination(type, dest, true)) { + ReserveDestination reservedest(this, type); + if (!reservedest.GetReservedDestination(dest, true)) { error = "Error: Keypool ran out, please call keypoolrefill first"; return false; } @@ -3265,7 +3288,7 @@ std::set<CTxDestination> CWallet::GetLabelAddresses(const std::string& label) co return result; } -bool ReserveDestination::GetReservedDestination(const OutputType type, CTxDestination& dest, bool internal) +bool ReserveDestination::GetReservedDestination(CTxDestination& dest, bool internal) { m_spk_man = pwallet->GetLegacyScriptPubKeyMan(); if (!m_spk_man) { @@ -3286,7 +3309,6 @@ bool ReserveDestination::GetReservedDestination(const OutputType type, CTxDestin fInternal = keypool.fInternal; } assert(vchPubKey.IsValid()); - m_spk_man->LearnRelatedScripts(vchPubKey, type); address = GetDestinationForKey(vchPubKey, type); dest = address; return true; @@ -3294,8 +3316,10 @@ bool ReserveDestination::GetReservedDestination(const OutputType type, CTxDestin void ReserveDestination::KeepDestination() { - if (nIndex != -1) + if (nIndex != -1) { m_spk_man->KeepDestination(nIndex); + m_spk_man->LearnRelatedScripts(vchPubKey, type); + } nIndex = -1; vchPubKey = CPubKey(); address = CNoDestination(); @@ -3651,9 +3675,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain, } if (auto spk_man = walletInstance->m_spk_man.get()) { - std::string error; if (!spk_man->Upgrade(prev_version, error)) { - chain.initError(error); return nullptr; } } @@ -4024,12 +4046,17 @@ bool CWallet::Lock() return true; } -ScriptPubKeyMan* CWallet::GetScriptPubKeyMan() const +ScriptPubKeyMan* CWallet::GetScriptPubKeyMan(const CScript& script) const +{ + return m_spk_man.get(); +} + +const SigningProvider* CWallet::GetSigningProvider(const CScript& script) const { return m_spk_man.get(); } -const SigningProvider* CWallet::GetSigningProvider() const +const SigningProvider* CWallet::GetSigningProvider(const CScript& script, SignatureData& sigdata) const { return m_spk_man.get(); } diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index a6b9c0131a..51df4a9a8b 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -71,8 +71,6 @@ static const CAmount WALLET_INCREMENTAL_RELAY_FEE = 5000; static const bool DEFAULT_SPEND_ZEROCONF_CHANGE = true; //! Default for -walletrejectlongchains static const bool DEFAULT_WALLET_REJECT_LONG_CHAINS = false; -//! Default for -avoidpartialspends -static const bool DEFAULT_AVOIDPARTIALSPENDS = false; //! -txconfirmtarget default static const unsigned int DEFAULT_TX_CONFIRM_TARGET = 6; //! -walletrbf default @@ -140,8 +138,9 @@ class ReserveDestination { protected: //! The wallet to reserve from - CWallet* pwallet; + CWallet* const pwallet; LegacyScriptPubKeyMan* m_spk_man{nullptr}; + OutputType const type; //! The index of the address's key in the keypool int64_t nIndex{-1}; //! The public key for the address @@ -153,10 +152,9 @@ protected: public: //! Construct a ReserveDestination object. This does NOT reserve an address yet - explicit ReserveDestination(CWallet* pwalletIn) - { - pwallet = pwalletIn; - } + explicit ReserveDestination(CWallet* pwallet, OutputType type) + : pwallet(pwallet) + , type(type) { } ReserveDestination(const ReserveDestination&) = delete; ReserveDestination& operator=(const ReserveDestination&) = delete; @@ -168,7 +166,7 @@ public: } //! Reserve an address - bool GetReservedDestination(const OutputType type, CTxDestination& pubkey, bool internal); + bool GetReservedDestination(CTxDestination& pubkey, bool internal); //! Return reserved address void ReturnDestination(); //! Keep the address. Do not return it's key to the keypool when this object goes out of scope @@ -584,6 +582,8 @@ struct CoinSelectionParams size_t change_spend_size = 0; CFeeRate effective_fee = CFeeRate(0); size_t tx_noinputs_size = 0; + //! Indicate that we are subtracting the fee from outputs + bool m_subtract_fee_outputs = false; CoinSelectionParams(bool use_bnb, size_t change_output_size, size_t change_spend_size, CFeeRate effective_fee, size_t tx_noinputs_size) : use_bnb(use_bnb), change_output_size(change_output_size), change_spend_size(change_spend_size), effective_fee(effective_fee), tx_noinputs_size(tx_noinputs_size) {} CoinSelectionParams() {} @@ -1128,8 +1128,13 @@ public: LogPrintf(("%s " + fmt).c_str(), GetDisplayName(), parameters...); }; - ScriptPubKeyMan* GetScriptPubKeyMan() const; - const SigningProvider* GetSigningProvider() const; + //! Get the ScriptPubKeyMan for a script + ScriptPubKeyMan* GetScriptPubKeyMan(const CScript& script) const; + + //! Get the SigningProvider for a script + const SigningProvider* GetSigningProvider(const CScript& script) const; + const SigningProvider* GetSigningProvider(const CScript& script, SignatureData& sigdata) const; + LegacyScriptPubKeyMan* GetLegacyScriptPubKeyMan() const; // Temporary LegacyScriptPubKeyMan accessors and aliases. diff --git a/test/README.md b/test/README.md index 24a9389fac..c3e4ae9ad2 100644 --- a/test/README.md +++ b/test/README.md @@ -258,6 +258,7 @@ Use the `-v` option for verbose output. |-----------|:----------:|:-------------------------------------------:|-------------- | [`lint-python.sh`](lint/lint-python.sh) | [flake8](https://gitlab.com/pycqa/flake8) | [3.7.8](https://github.com/bitcoin/bitcoin/pull/15257) | `pip3 install flake8==3.7.8` | [`lint-shell.sh`](lint/lint-shell.sh) | [ShellCheck](https://github.com/koalaman/shellcheck) | [0.6.0](https://github.com/bitcoin/bitcoin/pull/15166) | [details...](https://github.com/koalaman/shellcheck#installing) +| [`lint-shell.sh`](lint/lint-shell.sh) | [yq](https://github.com/kislyuk/yq) | default | `pip3 install yq` | [`lint-spelling.sh`](lint/lint-spelling.sh) | [codespell](https://github.com/codespell-project/codespell) | [1.15.0](https://github.com/bitcoin/bitcoin/pull/16186) | `pip3 install codespell==1.15.0` Please be aware that on Linux distributions all dependencies are usually available as packages, but could be outdated. diff --git a/test/config.ini.in b/test/config.ini.in index 060c553da2..9687206ee1 100644 --- a/test/config.ini.in +++ b/test/config.ini.in @@ -16,6 +16,7 @@ RPCAUTH=@abs_top_srcdir@/share/rpcauth/rpcauth.py # Which components are enabled. These are commented out by `configure` if they were disabled when running config. @ENABLE_WALLET_TRUE@ENABLE_WALLET=true @BUILD_BITCOIN_CLI_TRUE@ENABLE_CLI=true +@BUILD_BITCOIN_WALLET_TRUE@ENABLE_WALLET_TOOL=true @BUILD_BITCOIND_TRUE@ENABLE_BITCOIND=true @ENABLE_FUZZ_TRUE@ENABLE_FUZZ=true @ENABLE_ZMQ_TRUE@ENABLE_ZMQ=true diff --git a/test/functional/interface_bitcoin_cli.py b/test/functional/interface_bitcoin_cli.py index 373a2bdee0..f04a58cd19 100755 --- a/test/functional/interface_bitcoin_cli.py +++ b/test/functional/interface_bitcoin_cli.py @@ -12,6 +12,9 @@ class TestBitcoinCli(BitcoinTestFramework): self.setup_clean_chain = True self.num_nodes = 1 + def skip_test_if_missing_module(self): + self.skip_if_no_cli() + def run_test(self): """Main test logic""" diff --git a/test/functional/interface_rest.py b/test/functional/interface_rest.py index a036dfc790..797fcc828a 100755 --- a/test/functional/interface_rest.py +++ b/test/functional/interface_rest.py @@ -151,7 +151,7 @@ class RESTTest (BitcoinTestFramework): bin_response = self.test_rest_request("/getutxos", http_method='POST', req_type=ReqType.BIN, body=bin_request, ret_type=RetType.BYTES) output = BytesIO(bin_response) - chain_height, = unpack("i", output.read(4)) + chain_height, = unpack("<i", output.read(4)) response_hash = output.read(32)[::-1].hex() assert_equal(bb_hash, response_hash) # check if getutxo's chaintip during calculation was fine diff --git a/test/functional/mempool_accept.py b/test/functional/mempool_accept.py index c466b120f2..0eef1d3ddf 100755 --- a/test/functional/mempool_accept.py +++ b/test/functional/mempool_accept.py @@ -267,6 +267,12 @@ class MempoolAcceptanceTest(BitcoinTestFramework): rawtxs=[tx.serialize().hex()], ) tx.deserialize(BytesIO(hex_str_to_bytes(raw_tx_reference))) + tx.vin[0].scriptSig = CScript([b'a' * 1648]) # Some too large scriptSig (>1650 bytes) + self.check_mempool_result( + result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'scriptsig-size'}], + rawtxs=[tx.serialize().hex()], + ) + tx.deserialize(BytesIO(hex_str_to_bytes(raw_tx_reference))) output_p2sh_burn = CTxOut(nValue=540, scriptPubKey=CScript([OP_HASH160, hash160(b'burn'), OP_EQUAL])) 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 diff --git a/test/functional/p2p_segwit.py b/test/functional/p2p_segwit.py index 0c7edbf434..fdb70097ee 100755 --- a/test/functional/p2p_segwit.py +++ b/test/functional/p2p_segwit.py @@ -1116,7 +1116,7 @@ class SegWitTest(BitcoinTestFramework): MAX_PROGRAM_LENGTH = 10000 # This program is 19 max pushes (9937 bytes), then 64 more opcode-bytes. - long_witness_program = CScript([b'a' * 520] * 19 + [OP_DROP] * 63 + [OP_TRUE]) + long_witness_program = CScript([b'a' * MAX_SCRIPT_ELEMENT_SIZE] * 19 + [OP_DROP] * 63 + [OP_TRUE]) assert len(long_witness_program) == MAX_PROGRAM_LENGTH + 1 long_witness_hash = sha256(long_witness_program) long_script_pubkey = CScript([OP_0, long_witness_hash]) @@ -1140,7 +1140,7 @@ class SegWitTest(BitcoinTestFramework): test_witness_block(self.nodes[0], self.test_node, block, accepted=False) # Try again with one less byte in the witness program - witness_program = CScript([b'a' * 520] * 19 + [OP_DROP] * 62 + [OP_TRUE]) + witness_program = CScript([b'a' * MAX_SCRIPT_ELEMENT_SIZE] * 19 + [OP_DROP] * 62 + [OP_TRUE]) assert len(witness_program) == MAX_PROGRAM_LENGTH witness_hash = sha256(witness_program) script_pubkey = CScript([OP_0, witness_hash]) diff --git a/test/functional/rpc_fundrawtransaction.py b/test/functional/rpc_fundrawtransaction.py index 693051edc0..6f1ae0d3ba 100755 --- a/test/functional/rpc_fundrawtransaction.py +++ b/test/functional/rpc_fundrawtransaction.py @@ -92,6 +92,7 @@ class RawTransactionsTest(BitcoinTestFramework): self.test_option_feerate() self.test_address_reuse() self.test_option_subtract_fee_from_outputs() + self.test_subtract_fee_with_presets() def test_change_position(self): """Ensure setting changePosition in fundraw with an exact match is handled properly.""" @@ -741,5 +742,17 @@ class RawTransactionsTest(BitcoinTestFramework): # The total subtracted from the outputs is equal to the fee. assert_equal(share[0] + share[2] + share[3], result[0]['fee']) + def test_subtract_fee_with_presets(self): + self.log.info("Test fundrawtxn subtract fee from outputs with preset inputs that are sufficient") + + addr = self.nodes[0].getnewaddress() + txid = self.nodes[0].sendtoaddress(addr, 10) + vout = find_vout_for_address(self.nodes[0], txid, addr) + + rawtx = self.nodes[0].createrawtransaction([{'txid': txid, 'vout': vout}], [{self.nodes[0].getnewaddress(): 5}]) + fundedtx = self.nodes[0].fundrawtransaction(rawtx, {'subtractFeeFromOutputs': [0]}) + signedtx = self.nodes[0].signrawtransactionwithwallet(fundedtx['hex']) + self.nodes[0].sendrawtransaction(signedtx['hex']) + if __name__ == '__main__': RawTransactionsTest().main() diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py index c56c0d06ff..f468f9eaec 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -12,6 +12,7 @@ import os import pdb import random import shutil +import subprocess import sys import tempfile import time @@ -121,6 +122,9 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass): except KeyError: self.log.exception("Key error") self.success = TestStatus.FAILED + except subprocess.CalledProcessError as e: + self.log.exception("Called Process failed with '{}'".format(e.output)) + self.success = TestStatus.FAILED except Exception: self.log.exception("Unexpected exception caught during testing") self.success = TestStatus.FAILED @@ -596,6 +600,11 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass): if not self.is_wallet_compiled(): raise SkipTest("wallet has not been compiled.") + def skip_if_no_wallet_tool(self): + """Skip the running test if bitcoin-wallet has not been compiled.""" + if not self.is_wallet_tool_compiled(): + raise SkipTest("bitcoin-wallet has not been compiled") + def skip_if_no_cli(self): """Skip the running test if bitcoin-cli has not been compiled.""" if not self.is_cli_compiled(): @@ -609,6 +618,10 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass): """Checks whether the wallet module was compiled.""" return self.config["components"].getboolean("ENABLE_WALLET") + def is_wallet_tool_compiled(self): + """Checks whether bitcoin-wallet was compiled.""" + return self.config["components"].getboolean("ENABLE_WALLET_TOOL") + def is_zmq_compiled(self): """Checks whether the zmq module was compiled.""" return self.config["components"].getboolean("ENABLE_ZMQ") diff --git a/test/functional/test_framework/wallet_util.py b/test/functional/test_framework/wallet_util.py index c0dfa4c3f0..3d81a61120 100755 --- a/test/functional/test_framework/wallet_util.py +++ b/test/functional/test_framework/wallet_util.py @@ -88,6 +88,11 @@ def get_multisig(node): p2sh_p2wsh_script=CScript([OP_HASH160, witness_script, OP_EQUAL]).hex(), p2sh_p2wsh_addr=script_to_p2sh_p2wsh(script_code)) +def labels_value(name="", purpose="receive"): + """Generate a getaddressinfo labels array from a name and purpose. + Often used as the value of a labels kwarg for calling test_address below.""" + return [{"name": name, "purpose": purpose}] + def test_address(node, address, **kwargs): """Get address info for `address` and test whether the returned values are as expected.""" addr_info = node.getaddressinfo(address) diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index 9b4a5d2030..4156e22720 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -364,9 +364,10 @@ def main(): def run_tests(*, test_list, src_dir, build_dir, tmpdir, jobs=1, enable_coverage=False, args=None, combined_logs_len=0, failfast=False, runs_ci, use_term_control): args = args or [] - # Warn if bitcoind is already running (unix only) + # Warn if bitcoind is already running + # pidof might fail or return an empty string if bitcoind is not running try: - if subprocess.check_output(["pidof", "bitcoind"]) is not None: + if subprocess.check_output(["pidof", "bitcoind"]) not in [b'']: print("%sWARNING!%s There is already a bitcoind process running on this system. Tests may fail unexpectedly due to resource contention!" % (BOLD[1], BOLD[0])) except (OSError, subprocess.SubprocessError): pass diff --git a/test/functional/tool_wallet.py b/test/functional/tool_wallet.py index 355cd7af75..32ef257456 100755 --- a/test/functional/tool_wallet.py +++ b/test/functional/tool_wallet.py @@ -23,6 +23,7 @@ class ToolWalletTest(BitcoinTestFramework): def skip_test_if_missing_module(self): self.skip_if_no_wallet() + self.skip_if_no_wallet_tool() def bitcoin_wallet_process(self, *args): binary = self.config["environment"]["BUILDDIR"] + '/src/bitcoin-wallet' + self.config["environment"]["EXEEXT"] diff --git a/test/functional/wallet_basic.py b/test/functional/wallet_basic.py index 550037923e..130fa3cfaf 100755 --- a/test/functional/wallet_basic.py +++ b/test/functional/wallet_basic.py @@ -15,6 +15,10 @@ from test_framework.util import ( connect_nodes, wait_until, ) +from test_framework.wallet_util import ( + labels_value, + test_address, +) class WalletTest(BitcoinTestFramework): @@ -390,7 +394,7 @@ class WalletTest(BitcoinTestFramework): for label in [u'рыба', u'𝅘𝅥𝅯']: addr = self.nodes[0].getnewaddress() self.nodes[0].setlabel(addr, label) - assert_equal(self.nodes[0].getaddressinfo(addr)['label'], label) + test_address(self.nodes[0], addr, label=label, labels=labels_value(name=label)) assert label in self.nodes[0].listlabels() self.nodes[0].rpc.ensure_ascii = True # restore to default diff --git a/test/functional/wallet_bumpfee.py b/test/functional/wallet_bumpfee.py index 9d6aa36c35..0c08655833 100755 --- a/test/functional/wallet_bumpfee.py +++ b/test/functional/wallet_bumpfee.py @@ -101,7 +101,8 @@ def test_simple_bumpfee_succeeds(self, mode, rbf_node, peer_node, dest_address): else: bumped_tx = rbf_node.bumpfee(rbfid) assert_equal(bumped_tx["errors"], []) - assert bumped_tx["fee"] - abs(rbftx["fee"]) > 0 + assert bumped_tx["fee"] > -rbftx["fee"] + assert_equal(bumped_tx["origfee"], -rbftx["fee"]) # check that bumped_tx propagates, original tx was evicted and has a wallet conflict self.sync_mempools((rbf_node, peer_node)) assert bumped_tx["txid"] in rbf_node.getrawmempool() diff --git a/test/functional/wallet_import_with_label.py b/test/functional/wallet_import_with_label.py index 2a9051b1e8..e356fce469 100755 --- a/test/functional/wallet_import_with_label.py +++ b/test/functional/wallet_import_with_label.py @@ -11,7 +11,10 @@ with and without a label. """ from test_framework.test_framework import BitcoinTestFramework -from test_framework.wallet_util import test_address +from test_framework.wallet_util import ( + labels_value, + test_address, +) class ImportWithLabel(BitcoinTestFramework): @@ -36,7 +39,8 @@ class ImportWithLabel(BitcoinTestFramework): address, iswatchonly=True, ismine=False, - label=label) + label=label, + labels=labels_value(name=label)) self.log.info( "Import the watch-only address's private key without a " @@ -47,7 +51,8 @@ class ImportWithLabel(BitcoinTestFramework): test_address(self.nodes[1], address, - label=label) + label=label, + labels=labels_value(name=label)) self.log.info( "Test importaddress without label and importprivkey with label." @@ -59,7 +64,8 @@ class ImportWithLabel(BitcoinTestFramework): address2, iswatchonly=True, ismine=False, - label="") + label="", + labels=labels_value()) self.log.info( "Import the watch-only address's private key with a " @@ -71,7 +77,8 @@ class ImportWithLabel(BitcoinTestFramework): test_address(self.nodes[1], address2, - label=label2) + label=label2, + labels=labels_value(name=label2)) self.log.info("Test importaddress with label and importprivkey with label.") self.log.info("Import a watch-only address with a label.") @@ -82,7 +89,8 @@ class ImportWithLabel(BitcoinTestFramework): address3, iswatchonly=True, ismine=False, - label=label3_addr) + label=label3_addr, + labels=labels_value(name=label3_addr)) self.log.info( "Import the watch-only address's private key with a " @@ -94,7 +102,8 @@ class ImportWithLabel(BitcoinTestFramework): test_address(self.nodes[1], address3, - label=label3_priv) + label=label3_priv, + labels=labels_value(name=label3_priv)) self.log.info( "Test importprivkey won't label new dests with the same " @@ -109,6 +118,7 @@ class ImportWithLabel(BitcoinTestFramework): iswatchonly=True, ismine=False, label=label4_addr, + labels=labels_value(name=label4_addr), embedded=None) self.log.info( @@ -123,10 +133,13 @@ class ImportWithLabel(BitcoinTestFramework): test_address(self.nodes[1], embedded_addr, - label="") + label="", + labels=labels_value()) + test_address(self.nodes[1], address4, - label=label4_addr) + label=label4_addr, + labels=labels_value(name=label4_addr)) self.stop_nodes() diff --git a/test/functional/wallet_importmulti.py b/test/functional/wallet_importmulti.py index 23748e5dd7..5febac5998 100755 --- a/test/functional/wallet_importmulti.py +++ b/test/functional/wallet_importmulti.py @@ -29,6 +29,7 @@ from test_framework.util import ( from test_framework.wallet_util import ( get_key, get_multisig, + labels_value, test_address, ) @@ -121,7 +122,7 @@ class ImportMultiTest(BitcoinTestFramework): self.test_importmulti({"scriptPubKey": key.p2pkh_script, "timestamp": "now", "internal": True, - "label": "Example label"}, + "label": "Unsuccessful labelling for internal addresses"}, success=False, error_code=-8, error_message='Internal addresses should not have a label') @@ -550,7 +551,7 @@ class ImportMultiTest(BitcoinTestFramework): self.log.info("Should not import a p2sh-p2wpkh address from descriptor without checksum and private key") self.test_importmulti({"desc": "sh(wpkh(" + key.pubkey + "))", "timestamp": "now", - "label": "Descriptor import test", + "label": "Unsuccessful P2SH-P2WPKH descriptor import", "keys": [key.privkey]}, success=False, error_code=-5, @@ -558,17 +559,19 @@ class ImportMultiTest(BitcoinTestFramework): # Test importing of a P2SH-P2WPKH address via descriptor + private key key = get_key(self.nodes[0]) + p2sh_p2wpkh_label = "Successful P2SH-P2WPKH descriptor import" self.log.info("Should import a p2sh-p2wpkh address from descriptor and private key") self.test_importmulti({"desc": descsum_create("sh(wpkh(" + key.pubkey + "))"), "timestamp": "now", - "label": "Descriptor import test", + "label": p2sh_p2wpkh_label, "keys": [key.privkey]}, success=True) test_address(self.nodes[1], key.p2sh_p2wpkh_addr, solvable=True, ismine=True, - label="Descriptor import test") + label=p2sh_p2wpkh_label, + labels=labels_value(name=p2sh_p2wpkh_label)) # Test ranged descriptor fails if range is not specified xpriv = "tprv8ZgxMBicQKsPeuVhWwi6wuMQGfPKi9Li5GtX35jVNknACgqe3CY4g5xgkfDDJcmtF7o1QnxWDRYw4H5P26PXq7sbcUkEqeR4fg3Kxp2tigg" @@ -628,17 +631,19 @@ class ImportMultiTest(BitcoinTestFramework): # Test importing of a P2PKH address via descriptor key = get_key(self.nodes[0]) + p2pkh_label = "P2PKH descriptor import" self.log.info("Should import a p2pkh address from descriptor") self.test_importmulti({"desc": descsum_create("pkh(" + key.pubkey + ")"), "timestamp": "now", - "label": "Descriptor import test"}, + "label": p2pkh_label}, True, warnings=["Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag."]) test_address(self.nodes[1], key.p2pkh_addr, solvable=True, ismine=False, - label="Descriptor import test") + label=p2pkh_label, + labels=labels_value(name=p2pkh_label)) # Test import fails if both desc and scriptPubKey are provided key = get_key(self.nodes[0]) @@ -675,7 +680,7 @@ class ImportMultiTest(BitcoinTestFramework): # Import pubkeys with key origin info self.log.info("Addresses should have hd keypath and master key id after import with key origin") pub_addr = self.nodes[1].getnewaddress() - pub_addr = self.nodes[1].getnewaddress() + pub_addr = self.nodes[1].getnewaddress(address_type="bech32") info = self.nodes[1].getaddressinfo(pub_addr) pub = info['pubkey'] pub_keypath = info['hdkeypath'] @@ -693,7 +698,7 @@ class ImportMultiTest(BitcoinTestFramework): assert_equal(pub_import_info['hdkeypath'], pub_keypath) # Import privkeys with key origin info - priv_addr = self.nodes[1].getnewaddress() + priv_addr = self.nodes[1].getnewaddress(address_type="bech32") info = self.nodes[1].getaddressinfo(priv_addr) priv = self.nodes[1].dumpprivkey(priv_addr) priv_keypath = info['hdkeypath'] @@ -742,8 +747,8 @@ class ImportMultiTest(BitcoinTestFramework): self.nodes[1].createwallet(wallet_name="noprivkeys", disable_private_keys=True) wrpc = self.nodes[1].get_wallet_rpc("noprivkeys") - addr1 = self.nodes[0].getnewaddress() - addr2 = self.nodes[0].getnewaddress() + addr1 = self.nodes[0].getnewaddress(address_type="bech32") + addr2 = self.nodes[0].getnewaddress(address_type="bech32") pub1 = self.nodes[0].getaddressinfo(addr1)['pubkey'] pub2 = self.nodes[0].getaddressinfo(addr2)['pubkey'] result = wrpc.importmulti( @@ -761,15 +766,15 @@ class ImportMultiTest(BitcoinTestFramework): assert result[0]['success'] assert result[1]['success'] assert_equal(wrpc.getwalletinfo()["keypoolsize"], 2) - newaddr1 = wrpc.getnewaddress() + newaddr1 = wrpc.getnewaddress(address_type="bech32") assert_equal(addr1, newaddr1) - newaddr2 = wrpc.getnewaddress() + newaddr2 = wrpc.getnewaddress(address_type="bech32") assert_equal(addr2, newaddr2) # Import some public keys to the internal keypool of a no privkey wallet self.log.info("Adding pubkey to internal keypool of disableprivkey wallet") - addr1 = self.nodes[0].getnewaddress() - addr2 = self.nodes[0].getnewaddress() + addr1 = self.nodes[0].getnewaddress(address_type="bech32") + addr2 = self.nodes[0].getnewaddress(address_type="bech32") pub1 = self.nodes[0].getaddressinfo(addr1)['pubkey'] pub2 = self.nodes[0].getaddressinfo(addr2)['pubkey'] result = wrpc.importmulti( @@ -789,15 +794,15 @@ class ImportMultiTest(BitcoinTestFramework): assert result[0]['success'] assert result[1]['success'] assert_equal(wrpc.getwalletinfo()["keypoolsize_hd_internal"], 2) - newaddr1 = wrpc.getrawchangeaddress() + newaddr1 = wrpc.getrawchangeaddress(address_type="bech32") assert_equal(addr1, newaddr1) - newaddr2 = wrpc.getrawchangeaddress() + newaddr2 = wrpc.getrawchangeaddress(address_type="bech32") assert_equal(addr2, newaddr2) # Import a multisig and make sure the keys don't go into the keypool self.log.info('Imported scripts with pubkeys should not have their pubkeys go into the keypool') - addr1 = self.nodes[0].getnewaddress() - addr2 = self.nodes[0].getnewaddress() + addr1 = self.nodes[0].getnewaddress(address_type="bech32") + addr2 = self.nodes[0].getnewaddress(address_type="bech32") pub1 = self.nodes[0].getaddressinfo(addr1)['pubkey'] pub2 = self.nodes[0].getaddressinfo(addr2)['pubkey'] result = wrpc.importmulti( diff --git a/test/functional/wallet_labels.py b/test/functional/wallet_labels.py index b71dae9f40..27371d43bb 100755 --- a/test/functional/wallet_labels.py +++ b/test/functional/wallet_labels.py @@ -13,6 +13,10 @@ from collections import defaultdict from test_framework.test_framework import BitcoinTestFramework from test_framework.util import assert_equal, assert_raises_rpc_error +from test_framework.wallet_util import ( + labels_value, + test_address, +) class WalletLabelsTest(BitcoinTestFramework): def set_test_params(self): @@ -152,14 +156,14 @@ class Label: def verify(self, node): if self.receive_address is not None: assert self.receive_address in self.addresses - for address in self.addresses: - assert_equal( - node.getaddressinfo(address)['labels'][0], - {"name": self.name, - "purpose": self.purpose[address]}) - assert_equal(node.getaddressinfo(address)['label'], self.name) - + test_address( + node, + address, + label=self.name, + labels=labels_value(name=self.name, purpose=self.purpose[address]) + ) + assert self.name in node.listlabels() assert_equal( node.getaddressesbylabel(self.name), {address: {"purpose": self.purpose[address]} for address in self.addresses}) diff --git a/test/functional/wallet_listreceivedby.py b/test/functional/wallet_listreceivedby.py index 5e94068930..afd473306d 100755 --- a/test/functional/wallet_listreceivedby.py +++ b/test/functional/wallet_listreceivedby.py @@ -11,6 +11,10 @@ from test_framework.util import ( assert_equal, assert_raises_rpc_error, ) +from test_framework.wallet_util import ( + labels_value, + test_address, +) class ReceivedByTest(BitcoinTestFramework): @@ -19,6 +23,7 @@ class ReceivedByTest(BitcoinTestFramework): def skip_test_if_missing_module(self): self.skip_if_no_wallet() + self.skip_if_no_cli() def run_test(self): # Generate block to get out of IBD @@ -126,7 +131,7 @@ class ReceivedByTest(BitcoinTestFramework): # set pre-state label = '' address = self.nodes[1].getnewaddress() - assert_equal(self.nodes[1].getaddressinfo(address)['label'], label) + test_address(self.nodes[1], address, label=label, labels=labels_value(name=label)) received_by_label_json = [r for r in self.nodes[1].listreceivedbylabel() if r["label"] == label][0] balance_by_label = self.nodes[1].getreceivedbylabel(label) diff --git a/test/fuzz/test_runner.py b/test/fuzz/test_runner.py index f19cf924d2..fde99fe496 100755 --- a/test/fuzz/test_runner.py +++ b/test/fuzz/test_runner.py @@ -78,7 +78,7 @@ def main(): os.path.join(config["environment"]["BUILDDIR"], 'src', 'test', 'fuzz', test_list_selection[0]), '-help=1', ], - timeout=1, + timeout=10, check=True, stderr=subprocess.PIPE, universal_newlines=True, diff --git a/test/lint/lint-circular-dependencies.sh b/test/lint/lint-circular-dependencies.sh index ccd12b5823..1538ad77b1 100755 --- a/test/lint/lint-circular-dependencies.sh +++ b/test/lint/lint-circular-dependencies.sh @@ -18,18 +18,13 @@ EXPECTED_CIRCULAR_DEPENDENCIES=( "qt/bitcoingui -> qt/walletframe -> qt/bitcoingui" "qt/bitcoingui -> qt/walletview -> qt/bitcoingui" "qt/clientmodel -> qt/peertablemodel -> qt/clientmodel" - "qt/paymentserver -> qt/walletmodel -> qt/paymentserver" "qt/recentrequeststablemodel -> qt/walletmodel -> qt/recentrequeststablemodel" "qt/sendcoinsdialog -> qt/walletmodel -> qt/sendcoinsdialog" "qt/transactiontablemodel -> qt/walletmodel -> qt/transactiontablemodel" - "qt/walletmodel -> qt/walletmodeltransaction -> qt/walletmodel" "txmempool -> validation -> txmempool" - "wallet/coincontrol -> wallet/wallet -> wallet/coincontrol" "wallet/fees -> wallet/wallet -> wallet/fees" "wallet/wallet -> wallet/walletdb -> wallet/wallet" "policy/fees -> txmempool -> validation -> policy/fees" - "qt/guiutil -> qt/walletmodel -> qt/optionsmodel -> qt/guiutil" - "txmempool -> validation -> validationinterface -> txmempool" "wallet/scriptpubkeyman -> wallet/wallet -> wallet/scriptpubkeyman" ) diff --git a/test/lint/lint-shell.sh b/test/lint/lint-shell.sh index 69fc3cf368..63624e3ae0 100755 --- a/test/lint/lint-shell.sh +++ b/test/lint/lint-shell.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # -# Copyright (c) 2018 The Bitcoin Core developers +# Copyright (c) 2018-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. # @@ -16,16 +16,45 @@ if [ "$TRAVIS" = "true" ]; then unset LC_ALL fi -if ! command -v shellcheck > /dev/null; then - echo "Skipping shell linting since shellcheck is not installed." - exit 0 -fi - # Disabled warnings: disabled=( SC2046 # Quote this to prevent word splitting. SC2086 # Double quote to prevent globbing and word splitting. SC2162 # read without -r will mangle backslashes. ) -shellcheck -e "$(IFS=","; echo "${disabled[*]}")" \ - $(git ls-files -- "*.sh" | grep -vE 'src/(secp256k1|univalue)/') +disabled_gitian=( + SC2094 # Make sure not to read and write the same file in the same pipeline. + SC2129 # Consider using { cmd1; cmd2; } >> file instead of individual redirects. + SC2230 # which is non-standard. Use builtin 'command -v' instead. +) + +EXIT_CODE=0 + +if ! command -v shellcheck > /dev/null; then + echo "Skipping shell linting since shellcheck is not installed." + exit $EXIT_CODE +fi + +EXCLUDE="--exclude=$(IFS=','; echo "${disabled[*]}")" +if ! shellcheck "$EXCLUDE" $(git ls-files -- '*.sh' | grep -vE 'src/(leveldb|secp256k1|univalue)/'); then + EXIT_CODE=1 +fi + +if ! command -v yq > /dev/null; then + echo "Skipping Gitian desriptor scripts checking since yq is not installed." + exit $EXIT_CODE +fi + +EXCLUDE_GITIAN=${EXCLUDE}",$(IFS=','; echo "${disabled_gitian[*]}")" +for descriptor in $(git ls-files -- 'contrib/gitian-descriptors/*.yml') +do + echo + echo "$descriptor" + # Use #!/bin/bash as gitian-builder/bin/gbuild does to complete a script. + SCRIPT=$'#!/bin/bash\n'$(yq -r .script "$descriptor") + if ! echo "$SCRIPT" | shellcheck "$EXCLUDE_GITIAN" -; then + EXIT_CODE=1 + fi +done + +exit $EXIT_CODE diff --git a/test/sanitizer_suppressions/lsan b/test/sanitizer_suppressions/lsan index 90a92a5115..d2cb618d4e 100644 --- a/test/sanitizer_suppressions/lsan +++ b/test/sanitizer_suppressions/lsan @@ -1,5 +1,4 @@ # Suppress warnings triggered in dependencies -leak:libcrypto leak:libqminimal leak:libQt5Core leak:libQt5Gui diff --git a/test/sanitizer_suppressions/ubsan b/test/sanitizer_suppressions/ubsan index e7c690fabe..f5de358bcb 100644 --- a/test/sanitizer_suppressions/ubsan +++ b/test/sanitizer_suppressions/ubsan @@ -42,3 +42,45 @@ unsigned-integer-overflow:stl_bvector.h unsigned-integer-overflow:txmempool.cpp unsigned-integer-overflow:util/strencodings.cpp unsigned-integer-overflow:validation.cpp + +implicit-integer-sign-change:*/include/c++/*/bits/*.h +implicit-integer-sign-change:*/new_allocator.h +implicit-integer-sign-change:/usr/include/boost/date_time/format_date_parser.hpp +implicit-integer-sign-change:arith_uint256.cpp +implicit-integer-sign-change:bech32.cpp +implicit-integer-sign-change:bloom.cpp +implicit-integer-sign-change:chain.* +implicit-integer-sign-change:coins.h +implicit-integer-sign-change:compat/stdin.cpp +implicit-integer-sign-change:compressor.h +implicit-integer-sign-change:crypto/* +implicit-integer-sign-change:key.cpp +implicit-integer-sign-change:noui.cpp +implicit-integer-sign-change:prevector.h +implicit-integer-sign-change:protocol.cpp +implicit-integer-sign-change:script/bitcoinconsensus.cpp +implicit-integer-sign-change:script/interpreter.cpp +implicit-integer-sign-change:serialize.h +implicit-integer-sign-change:test/arith_uint256_tests.cpp +implicit-integer-sign-change:test/coins_tests.cpp +implicit-integer-sign-change:test/pow_tests.cpp +implicit-integer-sign-change:test/prevector_tests.cpp +implicit-integer-sign-change:test/sighash_tests.cpp +implicit-integer-sign-change:test/streams_tests.cpp +implicit-integer-sign-change:test/transaction_tests.cpp +implicit-integer-sign-change:txmempool.cpp +implicit-integer-sign-change:util/strencodings.* +implicit-integer-sign-change:validation.cpp +implicit-integer-sign-change:zmq/zmqpublishnotifier.cpp +implicit-signed-integer-truncation,implicit-integer-sign-change:chain.h +implicit-signed-integer-truncation,implicit-integer-sign-change:test/skiplist_tests.cpp +implicit-signed-integer-truncation:chain.h +implicit-signed-integer-truncation:crypto/* +implicit-signed-integer-truncation:cuckoocache.h +implicit-signed-integer-truncation:leveldb/* +implicit-signed-integer-truncation:streams.h +implicit-signed-integer-truncation:test/arith_uint256_tests.cpp +implicit-signed-integer-truncation:test/skiplist_tests.cpp +implicit-signed-integer-truncation:torcontrol.cpp +implicit-unsigned-integer-truncation:crypto/* +implicit-unsigned-integer-truncation:leveldb/* |