aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/ci.yml76
-rw-r--r--.travis.yml38
-rw-r--r--Makefile.am14
-rw-r--r--build_msvc/bench_bitcoin/bench_bitcoin.vcxproj.in3
-rw-r--r--build_msvc/bitcoin.sln14
-rw-r--r--build_msvc/libtest_util/libtest_util.vcxproj.in16
-rw-r--r--build_msvc/msvc-autogen.py1
-rw-r--r--build_msvc/test_bitcoin/test_bitcoin.vcxproj3
-rw-r--r--build_msvc/vcpkg-packages.txt2
-rw-r--r--ci/README.md15
-rwxr-xr-xci/extended_lint/04_install.sh12
-rwxr-xr-xci/extended_lint/06_script.sh9
-rwxr-xr-xci/lint/04_install.sh3
-rwxr-xr-xci/test/00_setup_env.sh25
-rw-r--r--ci/test/00_setup_env_mac.sh2
-rw-r--r--ci/test/00_setup_env_mac_host.sh2
-rw-r--r--ci/test/00_setup_env_native_asan.sh5
-rw-r--r--ci/test/00_setup_env_native_centos.sh14
-rw-r--r--ci/test/00_setup_env_native_trusty.sh14
-rw-r--r--ci/test/00_setup_env_native_tsan.sh6
-rw-r--r--ci/test/00_setup_env_s390x.sh15
-rwxr-xr-xci/test/04_install.sh51
-rwxr-xr-xci/test/05_before_script.sh10
-rwxr-xr-xci/test/06_script_a.sh26
-rwxr-xr-xci/test/06_script_b.sh11
-rw-r--r--configure.ac118
-rwxr-xr-xcontrib/devtools/symbol-check.py40
-rwxr-xr-xcontrib/gitian-build.py2
-rw-r--r--contrib/gitian-descriptors/gitian-linux.yml24
-rw-r--r--contrib/gitian-descriptors/gitian-osx-signer.yml2
-rw-r--r--contrib/gitian-descriptors/gitian-osx.yml14
-rw-r--r--contrib/gitian-descriptors/gitian-win-signer.yml6
-rw-r--r--contrib/gitian-descriptors/gitian-win.yml13
-rw-r--r--contrib/verify-commits/README.md2
-rw-r--r--depends/.gitignore2
-rw-r--r--depends/Makefile9
-rw-r--r--depends/README.md18
-rw-r--r--depends/config.site.in4
-rw-r--r--depends/hosts/darwin.mk2
-rw-r--r--depends/packages/libevent.mk17
-rw-r--r--depends/packages/packages.mk4
-rw-r--r--depends/packages/qt.mk17
-rw-r--r--depends/packages/xcb_proto.mk5
-rw-r--r--depends/patches/libevent/fix_android_arc4random_addrandom.patch68
-rw-r--r--doc/README.md2
-rw-r--r--doc/build-osx.md2
-rw-r--r--doc/dependencies.md4
-rw-r--r--doc/developer-notes.md40
-rw-r--r--doc/release-notes.md19
-rw-r--r--doc/release-notes/release-notes-0.19.0.1.md1089
-rw-r--r--doc/release-notes/release-notes-0.19.0.md1086
-rw-r--r--doc/release-process.md2
-rw-r--r--share/qt/Info.plist.in2
-rw-r--r--src/Makefile.am2
-rw-r--r--src/Makefile.bench.include5
-rw-r--r--src/Makefile.qt.include1
-rw-r--r--src/Makefile.qttest.include12
-rw-r--r--src/Makefile.test.include196
-rw-r--r--src/Makefile.test_util.include31
-rw-r--r--src/bitcoin-cli.cpp3
-rw-r--r--src/bitcoin-wallet.cpp4
-rw-r--r--src/consensus/validation.h4
-rw-r--r--src/cuckoocache.h4
-rw-r--r--src/init.cpp8
-rw-r--r--src/interfaces/wallet.cpp29
-rw-r--r--src/interfaces/wallet.h12
-rw-r--r--src/key.cpp20
-rw-r--r--src/key.h10
-rw-r--r--src/miner.cpp2
-rw-r--r--src/net.cpp10
-rw-r--r--src/node/context.h7
-rw-r--r--src/node/psbt.cpp6
-rw-r--r--src/node/psbt.h11
-rw-r--r--src/prevector.h1
-rw-r--r--src/protocol.h1
-rw-r--r--src/psbt.cpp1
-rw-r--r--src/psbt.h3
-rw-r--r--src/pubkey.cpp24
-rw-r--r--src/pubkey.h22
-rw-r--r--src/qt/bantablemodel.cpp2
-rw-r--r--src/qt/bitcoingui.cpp2
-rw-r--r--src/qt/coincontroldialog.cpp2
-rw-r--r--src/qt/forms/modaloverlay.ui10
-rw-r--r--src/qt/forms/openuridialog.ui6
-rw-r--r--src/qt/forms/optionsdialog.ui3
-rw-r--r--src/qt/forms/receivecoinsdialog.ui6
-rw-r--r--src/qt/forms/sendcoinsdialog.ui2
-rw-r--r--src/qt/forms/sendcoinsentry.ui3
-rw-r--r--src/qt/forms/signverifymessagedialog.ui3
-rw-r--r--src/qt/guiutil.cpp127
-rw-r--r--src/qt/openuridialog.cpp3
-rw-r--r--src/qt/optionsdialog.cpp10
-rw-r--r--src/qt/paymentserver.h6
-rw-r--r--src/qt/peertablemodel.cpp2
-rw-r--r--src/qt/receiverequestdialog.cpp1
-rw-r--r--src/qt/receiverequestdialog.h4
-rw-r--r--src/qt/recentrequeststablemodel.cpp10
-rw-r--r--src/qt/recentrequeststablemodel.h6
-rw-r--r--src/qt/sendcoinsdialog.cpp84
-rw-r--r--src/qt/sendcoinsdialog.h3
-rw-r--r--src/qt/sendcoinsentry.cpp2
-rw-r--r--src/qt/sendcoinsentry.h6
-rw-r--r--src/qt/sendcoinsrecipient.h74
-rw-r--r--src/qt/signverifymessagedialog.cpp4
-rw-r--r--src/qt/test/rpcnestedtests.cpp1
-rw-r--r--src/qt/test/wallettests.cpp10
-rw-r--r--src/qt/transactiondesc.cpp5
-rw-r--r--src/qt/walletcontroller.cpp7
-rw-r--r--src/qt/walletcontroller.h4
-rw-r--r--src/qt/walletmodel.cpp2
-rw-r--r--src/qt/walletmodel.h58
-rw-r--r--src/qt/walletmodeltransaction.h3
-rw-r--r--src/random.cpp70
-rw-r--r--src/random.h24
-rw-r--r--src/randomenv.cpp25
-rw-r--r--src/rpc/blockchain.cpp10
-rw-r--r--src/rpc/blockchain.h2
-rw-r--r--src/rpc/mining.cpp5
-rw-r--r--src/rpc/protocol.h3
-rw-r--r--src/rpc/rawtransaction.cpp10
-rw-r--r--src/rpc/rawtransaction_util.cpp8
-rw-r--r--src/rpc/rawtransaction_util.h4
-rw-r--r--src/rpc/util.cpp6
-rw-r--r--src/rpc/util.h2
-rw-r--r--src/script/descriptor.cpp4
-rw-r--r--src/script/interpreter.cpp8
-rw-r--r--src/script/sign.h2
-rw-r--r--src/script/standard.cpp8
-rw-r--r--src/support/lockedpool.cpp8
-rw-r--r--src/test/checkqueue_tests.cpp1
-rw-r--r--src/test/crypto_tests.cpp15
-rw-r--r--src/test/dbwrapper_tests.cpp12
-rw-r--r--src/test/fuzz/descriptor_parse.cpp3
-rw-r--r--src/test/fuzz/deserialize.cpp270
-rw-r--r--src/test/fuzz/integer.cpp127
-rw-r--r--src/test/fuzz/parse_hd_keypath.cpp13
-rw-r--r--src/test/fuzz/parse_numbers.cpp35
-rw-r--r--src/test/fuzz/parse_script.cpp16
-rw-r--r--src/test/fuzz/parse_univalue.cpp91
-rw-r--r--src/test/fuzz/transaction.cpp22
-rw-r--r--src/test/fuzz/tx_in.cpp33
-rw-r--r--src/test/fuzz/tx_out.cpp35
-rw-r--r--src/test/miner_tests.cpp98
-rw-r--r--src/test/transaction_tests.cpp34
-rw-r--r--src/test/txvalidation_tests.cpp6
-rw-r--r--src/test/txvalidationcache_tests.cpp26
-rw-r--r--src/test/util/setup_common.cpp4
-rw-r--r--src/test/validation_block_tests.cpp12
-rw-r--r--src/tinyformat.h459
-rw-r--r--src/txmempool.cpp8
-rw-r--r--src/util/system.cpp8
-rw-r--r--src/util/system.h4
-rw-r--r--src/validation.cpp3
-rw-r--r--src/validation.h2
-rw-r--r--src/validationinterface.cpp31
-rw-r--r--src/validationinterface.h9
-rw-r--r--src/wallet/coincontrol.h6
-rw-r--r--src/wallet/feebumper.cpp7
-rw-r--r--src/wallet/init.cpp4
-rw-r--r--src/wallet/psbtwallet.cpp27
-rw-r--r--src/wallet/rpcwallet.cpp191
-rw-r--r--src/wallet/scriptpubkeyman.cpp40
-rw-r--r--src/wallet/scriptpubkeyman.h19
-rw-r--r--src/wallet/test/coinselector_tests.cpp52
-rw-r--r--src/wallet/wallet.cpp138
-rw-r--r--src/wallet/wallet.h30
-rw-r--r--test/README.md1
-rwxr-xr-xtest/functional/create_cache.py1
-rwxr-xr-xtest/functional/feature_config_args.py1
-rwxr-xr-xtest/functional/feature_csv_activation.py1
-rwxr-xr-xtest/functional/feature_dbcrash.py1
-rwxr-xr-xtest/functional/feature_loadblock.py1
-rwxr-xr-xtest/functional/feature_maxuploadtarget.py1
-rwxr-xr-xtest/functional/feature_pruning.py1
-rwxr-xr-xtest/functional/feature_rbf.py1
-rwxr-xr-xtest/functional/feature_shutdown.py1
-rwxr-xr-xtest/functional/interface_bitcoin_cli.py3
-rwxr-xr-xtest/functional/interface_http.py1
-rwxr-xr-xtest/functional/interface_rest.py3
-rwxr-xr-xtest/functional/interface_rpc.py1
-rwxr-xr-xtest/functional/mempool_accept.py7
-rwxr-xr-xtest/functional/mempool_limit.py1
-rwxr-xr-xtest/functional/mining_basic.py1
-rwxr-xr-xtest/functional/mining_getblocktemplate_longpoll.py1
-rwxr-xr-xtest/functional/mining_prioritisetransaction.py1
-rwxr-xr-xtest/functional/p2p_disconnect_ban.py1
-rwxr-xr-xtest/functional/p2p_segwit.py5
-rwxr-xr-xtest/functional/rpc_bind.py1
-rwxr-xr-xtest/functional/rpc_blockchain.py1
-rwxr-xr-xtest/functional/rpc_createmultisig.py1
-rwxr-xr-xtest/functional/rpc_deriveaddresses.py1
-rwxr-xr-xtest/functional/rpc_fundrawtransaction.py13
-rwxr-xr-xtest/functional/rpc_getblockstats.py1
-rwxr-xr-xtest/functional/rpc_help.py1
-rwxr-xr-xtest/functional/rpc_misc.py1
-rwxr-xr-xtest/functional/rpc_named_arguments.py1
-rwxr-xr-xtest/functional/rpc_net.py1
-rwxr-xr-xtest/functional/rpc_preciousblock.py1
-rwxr-xr-xtest/functional/rpc_psbt.py6
-rwxr-xr-xtest/functional/rpc_rawtransaction.py1
-rwxr-xr-xtest/functional/rpc_users.py1
-rwxr-xr-xtest/functional/test_framework/test_framework.py9
-rwxr-xr-xtest/functional/test_framework/test_node.py14
-rw-r--r--test/functional/test_framework/util.py5
-rwxr-xr-xtest/functional/test_framework/wallet_util.py5
-rwxr-xr-xtest/functional/wallet_abandonconflict.py5
-rwxr-xr-xtest/functional/wallet_address_types.py1
-rwxr-xr-xtest/functional/wallet_basic.py7
-rwxr-xr-xtest/functional/wallet_bumpfee.py3
-rwxr-xr-xtest/functional/wallet_createwallet.py1
-rwxr-xr-xtest/functional/wallet_hd.py1
-rwxr-xr-xtest/functional/wallet_implicitsegwit.py1
-rwxr-xr-xtest/functional/wallet_import_rescan.py1
-rwxr-xr-xtest/functional/wallet_import_with_label.py31
-rwxr-xr-xtest/functional/wallet_importmulti.py41
-rwxr-xr-xtest/functional/wallet_labels.py18
-rwxr-xr-xtest/functional/wallet_listreceivedby.py6
-rwxr-xr-xtest/functional/wallet_multiwallet.py1
-rwxr-xr-xtest/functional/wallet_txn_clone.py1
-rwxr-xr-xtest/functional/wallet_txn_doublespend.py1
-rwxr-xr-xtest/functional/wallet_watchonly.py1
-rwxr-xr-xtest/fuzz/test_runner.py34
-rwxr-xr-xtest/lint/lint-circular-dependencies.sh5
-rwxr-xr-xtest/lint/lint-locale-dependence.sh1
-rwxr-xr-xtest/lint/lint-shell.sh45
-rw-r--r--test/sanitizer_suppressions/ubsan42
226 files changed, 3833 insertions, 2503 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000000..f1d5efaa8d
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,76 @@
+name: bitcoin-core-ci
+
+on:
+ push:
+jobs:
+ build:
+ runs-on: windows-latest
+ env:
+ PYTHONUTF8: 1
+ QT_DOWNLOAD_URL: 'https://github.com/sipsorcery/qt_win_binary/releases/download/v1.4/Qt5.9.8_x64_static_vs2019.zip'
+ QT_DOWNLOAD_HASH: 'f285cbb02bec3b3f3cc2621e3fa7d5edf0d6a66fa30c57859e583acda954ea80'
+ QT_LOCAL_PATH: 'C:\Qt5.9.8_x64_static_vs2019'
+ VCPKG_INSTALL_PATH: "$env:VCPKG_INSTALLATION_ROOT/installed"
+ PLATFORM: x64
+ steps:
+ - uses: actions/checkout@v1
+
+ - uses: actions/cache@v1
+ id: vcpkgcache
+ with:
+ path: C:/vcpkg/installed
+ key: ${{ runner.os }}-vcpkg
+
+ - name: Update vcpkg and install packages
+ if: steps.vcpkgcache.outputs.cache-hit != 'true'
+ run: |
+ $env:PACKAGES = Get-Content -Path "$env:GITHUB_WORKSPACE/build_msvc/vcpkg-packages.txt"
+ Write-Host "vcpkg list: $env:PACKAGES"
+ cd $env:VCPKG_INSTALLATION_ROOT
+ git pull origin master
+ .\bootstrap-vcpkg.bat
+ .\vcpkg install --triplet $env:PLATFORM-windows-static $env:PACKAGES.split() > $null
+ - name: Install prebuilt Qt libraries
+ run: |
+ if(!(Test-Path -Path ($env:QT_LOCAL_PATH))) {
+ Write-Host "Downloading Qt binaries.";
+ Invoke-WebRequest -Uri $env:QT_DOWNLOAD_URL -Out qtdownload.zip;
+ Write-Host "Qt binaries successfully downloaded, checking hash against $env:QT_DOWNLOAD_HASH...";
+ if((Get-FileHash qtdownload.zip).Hash -eq $env:QT_DOWNLOAD_HASH) {
+ Expand-Archive qtdownload.zip -DestinationPath $env:QT_LOCAL_PATH;
+ Write-Host "Qt binary download matched the expected hash.";
+ }
+ else {
+ Write-Host "ERROR: Qt binary download did not match the expected hash.";
+ exit 1
+ }
+ }
+ else {
+ Write-Host "Qt binaries already present.";
+ }
+ - name: Generate project files
+ run: python build_msvc\msvc-autogen.py
+ - name: Setup MSBuild.exe
+ uses: warrenbuckley/Setup-MSBuild@v1
+ - name: vcpkg integration
+ run: C:/vcpkg/vcpkg.exe integrate install
+ - name: Build
+ run: msbuild build_msvc\bitcoin.sln /m /v:n /p:Configuration=Release
+ - name: Run test_bticoin
+ shell: cmd
+ run: src\test_bitcoin.exe -k stdout -e stdout 2> NUL
+ - name: Run bench_bitcoin
+ shell: cmd
+ run: src\bench_bitcoin.exe -evals=1 -scaling=0 > NUL
+ - name: bitcoin-util-test
+ run: python test\util\bitcoin-util-test.py
+ - name: rpcauth-test
+ shell: cmd
+ run: python test\util\rpcauth-test.py
+# This step fails due to character UTF encoding error. If anyone knows how Python deals with Unicode they might be
+# able to decipher the error message.
+# - name: test_runner
+# shell: cmd
+# run: |
+# python test\functional\test_runner.py --ansi --ci --quiet --combinedlogslen=4000 --failfast --exclude feature_fee_estimation
+
diff --git a/.travis.yml b/.travis.yml
index 73e62cd2b0..4f9dbeded4 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"
@@ -113,14 +105,14 @@ jobs:
FILE_ENV="./ci/test/00_setup_env_i686.sh"
- stage: test
- name: 'x86_64 Linux [GOAL: install] [bionic] [uses qt5 dev package instead of depends Qt to speed up build and avoid timeout] [unsigned char]'
+ name: 'x86_64 Linux [GOAL: install] [CentOS 7] [no depends, only system libs]'
env: >-
- FILE_ENV="./ci/test/00_setup_env_native_qt5.sh"
+ FILE_ENV="./ci/test/00_setup_env_native_centos.sh"
- stage: test
- name: 'x86_64 Linux [GOAL: install] [trusty] [no functional tests, no depends, only system libs]'
+ name: 'x86_64 Linux [GOAL: install] [bionic] [uses qt5 dev package instead of depends Qt to speed up build and avoid timeout] [unsigned char]'
env: >-
- FILE_ENV="./ci/test/00_setup_env_native_trusty.sh"
+ FILE_ENV="./ci/test/00_setup_env_native_qt5.sh"
- stage: test
name: 'x86_64 Linux [GOAL: install] [xenial] [no depends, only system libs, sanitizers: thread (TSan), no wallet]'
@@ -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/Makefile.am b/Makefile.am
index deae2c1b57..f121c33b24 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -99,7 +99,7 @@ $(OSX_APP)/Contents/PkgInfo:
$(OSX_APP)/Contents/Resources/empty.lproj:
$(MKDIR_P) $(@D)
- @touch $@
+ @touch $@
$(OSX_APP)/Contents/Info.plist: $(OSX_PLIST)
$(MKDIR_P) $(@D)
@@ -189,7 +189,16 @@ $(BITCOIN_WALLET_BIN): FORCE
$(MAKE) -C src $(@F)
if USE_LCOV
-LCOV_FILTER_PATTERN=-p "/usr/include/" -p "/usr/lib/" -p "src/leveldb/" -p "src/bench/" -p "src/univalue" -p "src/crypto/ctaes" -p "src/secp256k1"
+LCOV_FILTER_PATTERN = \
+ -p "/usr/include/" \
+ -p "/usr/lib/" \
+ -p "/usr/lib64/" \
+ -p "src/leveldb/" \
+ -p "src/bench/" \
+ -p "src/univalue" \
+ -p "src/crypto/ctaes" \
+ -p "src/secp256k1" \
+ -p "depends"
baseline.info:
$(LCOV) -c -i -d $(abs_builddir)/src -o $@
@@ -321,4 +330,3 @@ clean-local: clean-docs
rm -rf coverage_percent.txt test_bitcoin.coverage/ total.coverage/ test/tmp/ cache/ $(OSX_APP)
rm -rf test/functional/__pycache__ test/functional/test_framework/__pycache__ test/cache share/rpcauth/__pycache__
rm -rf osx_volname dist/ dpi36.background.tiff dpi72.background.tiff
-
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 d63636259d..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 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 38e5e6871b..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 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_centos.sh b/ci/test/00_setup_env_native_centos.sh
new file mode 100644
index 0000000000..56b915b6c7
--- /dev/null
+++ b/ci/test/00_setup_env_native_centos.sh
@@ -0,0 +1,14 @@
+#!/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 DOCKER_NAME_TAG=centos:7
+export DOCKER_PACKAGES="gcc-c++ libtool make git python3 python36-zmq"
+export PACKAGES="boost-devel libevent-devel libdb4-devel libdb4-cxx-devel miniupnpc-devel zeromq-devel qt5-qtbase-devel qt5-qttools-devel qrencode-devel"
+export NO_DEPENDS=1
+export GOAL="install"
+export BITCOIN_CONFIG="--enable-reduce-exports"
diff --git a/ci/test/00_setup_env_native_trusty.sh b/ci/test/00_setup_env_native_trusty.sh
deleted file mode 100644
index 893c1f6b53..0000000000
--- a/ci/test/00_setup_env_native_trusty.sh
+++ /dev/null
@@ -1,14 +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.UTF-8
-
-export DOCKER_NAME_TAG=ubuntu:14.04
-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"
-export BITCOIN_CONFIG="--enable-zmq --with-incompatible-bdb --with-gui=no"
diff --git a/ci/test/00_setup_env_native_tsan.sh b/ci/test/00_setup_env_native_tsan.sh
index 9c38e87b48..e9b7a7bba1 100644
--- a/ci/test/00_setup_env_native_tsan.sh
+++ b/ci/test/00_setup_env_native_tsan.sh
@@ -10,4 +10,8 @@ export DOCKER_NAME_TAG=ubuntu:16.04
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 e70a8a9ea9..c721345250 100755
--- a/ci/test/04_install.sh
+++ b/ci/test/04_install.sh
@@ -6,6 +6,10 @@
export LC_ALL=C.UTF-8
+if [[ $DOCKER_NAME_TAG == centos* ]]; then
+ export LC_ALL=en_US.utf8
+fi
+
if [ "$TRAVIS_OS_NAME" == "osx" ]; then
set +o errexit
pushd /usr/local/Homebrew || exit 1
@@ -33,16 +37,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 ASAN_OPTIONS="detect_stack_use_after_return=1:check_initialization_order=1:strict_init_order=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"
@@ -50,19 +48,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
@@ -72,17 +78,34 @@ 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
DOCKER_EXEC dpkg --add-architecture "$DPKG_ADD_ARCH"
fi
-if [ "$TRAVIS_OS_NAME" != "osx" ]; then
+if [[ $DOCKER_NAME_TAG == centos* ]]; then
+ ${CI_RETRY_EXE} DOCKER_EXEC yum -y install epel-release
+ ${CI_RETRY_EXE} DOCKER_EXEC yum -y install $DOCKER_PACKAGES $PACKAGES
+elif [ "$TRAVIS_OS_NAME" != "osx" ]; then
${CI_RETRY_EXE} DOCKER_EXEC apt-get update
${CI_RETRY_EXE} DOCKER_EXEC apt-get install --no-install-recommends --no-upgrade -y $PACKAGES $DOCKER_PACKAGES
fi
+if [ ! -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 2025037bd4..e7d14202a7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -243,27 +243,27 @@ AC_ARG_ENABLE(man,
enable_man=yes)
AM_CONDITIONAL(ENABLE_MAN, test "$enable_man" != no)
-# Enable debug
+dnl Enable debug
AC_ARG_ENABLE([debug],
[AS_HELP_STRING([--enable-debug],
[use compiler flags and macros suited for debugging (default is no)])],
[enable_debug=$enableval],
[enable_debug=no])
-# Enable different -fsanitize options
+dnl Enable different -fsanitize options
AC_ARG_WITH([sanitizers],
[AS_HELP_STRING([--with-sanitizers],
[comma separated list of extra sanitizers to build with (default is none enabled)])],
[use_sanitizers=$withval])
-# Enable gprof profiling
+dnl Enable gprof profiling
AC_ARG_ENABLE([gprof],
[AS_HELP_STRING([--enable-gprof],
[use gprof profiling compiler flags (default is no)])],
[enable_gprof=$enableval],
[enable_gprof=no])
-# Turn warnings into errors
+dnl Turn warnings into errors
AC_ARG_ENABLE([werror],
[AS_HELP_STRING([--enable-werror],
[Treat certain compiler warnings as errors (default is no)])],
@@ -274,15 +274,15 @@ AC_LANG_PUSH([C++])
AX_CHECK_COMPILE_FLAG([-Werror],[CXXFLAG_WERROR="-Werror"],[CXXFLAG_WERROR=""])
if test "x$enable_debug" = xyes; then
- # Clear default -g -O2 flags
+ dnl Clear default -g -O2 flags
if test "x$CXXFLAGS_overridden" = xno; then
CXXFLAGS=""
fi
- # Disable all optimizations
+ dnl Disable all optimizations
AX_CHECK_COMPILE_FLAG([-O0], [[DEBUG_CXXFLAGS="$DEBUG_CXXFLAGS -O0"]],,[[$CXXFLAG_WERROR]])
- # Prefer -g3, fall back to -g if that is unavailable.
+ dnl Prefer -g3, fall back to -g if that is unavailable.
AX_CHECK_COMPILE_FLAG(
[-g3],
[[DEBUG_CXXFLAGS="$DEBUG_CXXFLAGS -g3"]],
@@ -295,19 +295,19 @@ if test "x$enable_debug" = xyes; then
fi
if test x$use_sanitizers != x; then
- # First check if the compiler accepts flags. If an incompatible pair like
- # -fsanitize=address,thread is used here, this check will fail. This will also
- # fail if a bad argument is passed, e.g. -fsanitize=undfeined
+ dnl First check if the compiler accepts flags. If an incompatible pair like
+ dnl -fsanitize=address,thread is used here, this check will fail. This will also
+ dnl fail if a bad argument is passed, e.g. -fsanitize=undfeined
AX_CHECK_COMPILE_FLAG(
[[-fsanitize=$use_sanitizers]],
[[SANITIZER_CXXFLAGS=-fsanitize=$use_sanitizers]],
[AC_MSG_ERROR([compiler did not accept requested flags])])
- # Some compilers (e.g. GCC) require additional libraries like libasan,
- # libtsan, libubsan, etc. Make sure linking still works with the sanitize
- # flag. This is a separate check so we can give a better error message when
- # the sanitize flags are supported by the compiler but the actual sanitizer
- # libs are missing.
+ dnl Some compilers (e.g. GCC) require additional libraries like libasan,
+ dnl libtsan, libubsan, etc. Make sure linking still works with the sanitize
+ dnl flag. This is a separate check so we can give a better error message when
+ dnl the sanitize flags are supported by the compiler but the actual sanitizer
+ dnl libs are missing.
AX_CHECK_LINK_FLAG(
[[-fsanitize=$use_sanitizers]],
[[SANITIZER_LDFLAGS=-fsanitize=$use_sanitizers]],
@@ -344,9 +344,9 @@ if test "x$CXXFLAGS_overridden" = "xno"; then
AX_CHECK_COMPILE_FLAG([-Wredundant-decls],[WARN_CXXFLAGS="$WARN_CXXFLAGS -Wredundant-decls"],,[[$CXXFLAG_WERROR]])
AX_CHECK_COMPILE_FLAG([-Wunused-variable],[WARN_CXXFLAGS="$WARN_CXXFLAGS -Wunused-variable"],,[[$CXXFLAG_WERROR]])
- ## Some compilers (gcc) ignore unknown -Wno-* options, but warn about all
- ## unknown options if any other warning is produced. Test the -Wfoo case, and
- ## set the -Wno-foo case if it works.
+ dnl Some compilers (gcc) ignore unknown -Wno-* options, but warn about all
+ dnl unknown options if any other warning is produced. Test the -Wfoo case, and
+ dnl set the -Wno-foo case if it works.
AX_CHECK_COMPILE_FLAG([-Wunused-parameter],[NOWARN_CXXFLAGS="$NOWARN_CXXFLAGS -Wno-unused-parameter"],,[[$CXXFLAG_WERROR]])
AX_CHECK_COMPILE_FLAG([-Wself-assign],[NOWARN_CXXFLAGS="$NOWARN_CXXFLAGS -Wno-self-assign"],,[[$CXXFLAG_WERROR]])
AX_CHECK_COMPILE_FLAG([-Wunused-local-typedef],[NOWARN_CXXFLAGS="$NOWARN_CXXFLAGS -Wno-unused-local-typedef"],,[[$CXXFLAG_WERROR]])
@@ -361,9 +361,9 @@ enable_shani=no
if test "x$use_asm" = "xyes"; then
-# Check for optional instruction set support. Enabling these does _not_ imply that all code will
-# be compiled with them, rather that specific objects/libs may use them after checking for runtime
-# compatibility.
+dnl Check for optional instruction set support. Enabling these does _not_ imply that all code will
+dnl be compiled with them, rather that specific objects/libs may use them after checking for runtime
+dnl compatibility.
AX_CHECK_COMPILE_FLAG([-msse4.2],[[SSE42_CXXFLAGS="-msse4.2"]],,[[$CXXFLAG_WERROR]])
AX_CHECK_COMPILE_FLAG([-msse4.1],[[SSE41_CXXFLAGS="-msse4.1"]],,[[$CXXFLAG_WERROR]])
AX_CHECK_COMPILE_FLAG([-mavx -mavx2],[[AVX2_CXXFLAGS="-mavx -mavx2"]],,[[$CXXFLAG_WERROR]])
@@ -506,8 +506,8 @@ case $host in
AC_CHECK_LIB([iphlpapi], [main],, AC_MSG_ERROR(libiphlpapi missing))
AC_CHECK_LIB([crypt32], [main],, AC_MSG_ERROR(libcrypt32 missing))
- # -static is interpreted by libtool, where it has a different meaning.
- # In libtool-speak, it's -all-static.
+ dnl -static is interpreted by libtool, where it has a different meaning.
+ dnl In libtool-speak, it's -all-static.
AX_CHECK_LINK_FLAG([[-static]],[LIBTOOL_APP_LDFLAGS="$LIBTOOL_APP_LDFLAGS -all-static"])
AC_PATH_PROG([MAKENSIS], [makensis], none)
@@ -555,8 +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).
- bdb_prefix=`$BREW --prefix berkeley-db4 2>/dev/null`
- qt5_prefix=`$BREW --prefix qt5 2>/dev/null`
+ bdb_prefix=$($BREW --prefix berkeley-db4 2>/dev/null)
+ qt5_prefix=$($BREW --prefix qt5 2>/dev/null)
if test x$bdb_prefix != x; then
CPPFLAGS="$CPPFLAGS -I$bdb_prefix/include"
LIBS="$LIBS -L$bdb_prefix/lib"
@@ -673,11 +673,11 @@ AC_C_BIGENDIAN
dnl Check for pthread compile/link requirements
AX_PTHREAD
-# The following macro will add the necessary defines to bitcoin-config.h, but
-# they also need to be passed down to any subprojects. Pull the results out of
-# the cache and add them to CPPFLAGS.
+dnl The following macro will add the necessary defines to bitcoin-config.h, but
+dnl they also need to be passed down to any subprojects. Pull the results out of
+dnl the cache and add them to CPPFLAGS.
AC_SYS_LARGEFILE
-# detect POSIX or GNU variant of strerror_r
+dnl detect POSIX or GNU variant of strerror_r
AC_FUNC_STRERROR_R
if test x$ac_cv_sys_file_offset_bits != x &&
@@ -700,12 +700,12 @@ AX_GCC_FUNC_ATTRIBUTE([dllimport])
if test x$use_glibc_compat != xno; then
- #glibc absorbed clock_gettime in 2.17. librt (its previous location) is safe to link
- #in anyway for back-compat.
+ dnl glibc absorbed clock_gettime in 2.17. librt (its previous location) is safe to link
+ dnl in anyway for back-compat.
AC_CHECK_LIB([rt],[clock_gettime],, AC_MSG_ERROR(librt missing))
- #__fdelt_chk's params and return type have changed from long unsigned int to long int.
- # See which one is present here.
+ dnl __fdelt_chk's params and return type have changed from long unsigned int to long int.
+ dnl See which one is present here.
AC_MSG_CHECKING(__fdelt_chk type)
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#ifdef _FORTIFY_SOURCE
#undef _FORTIFY_SOURCE
@@ -741,22 +741,22 @@ if test "x$enable_gprof" = xyes; then
fi
if test x$TARGET_OS != xwindows; then
- # All windows code is PIC, forcing it on just adds useless compile warnings
+ dnl All windows code is PIC, forcing it on just adds useless compile warnings
AX_CHECK_COMPILE_FLAG([-fPIC],[PIC_FLAGS="-fPIC"])
fi
-# All versions of gcc that we commonly use for building are subject to bug
-# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90348. To work around that, set
-# -fstack-reuse=none for all gcc builds. (Only gcc understands this flag)
+dnl All versions of gcc that we commonly use for building are subject to bug
+dnl https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90348. To work around that, set
+dnl -fstack-reuse=none for all gcc builds. (Only gcc understands this flag)
AX_CHECK_COMPILE_FLAG([-fstack-reuse=none],[HARDENED_CXXFLAGS="$HARDENED_CXXFLAGS -fstack-reuse=none"])
if test x$use_hardening != xno; then
use_hardening=yes
AX_CHECK_COMPILE_FLAG([-Wstack-protector],[HARDENED_CXXFLAGS="$HARDENED_CXXFLAGS -Wstack-protector"])
AX_CHECK_COMPILE_FLAG([-fstack-protector-all],[HARDENED_CXXFLAGS="$HARDENED_CXXFLAGS -fstack-protector-all"])
- # When enable_debug is yes, all optimizations are disabled.
- # However, FORTIFY_SOURCE requires that there is some level of optimization, otherwise it does nothing and just creates a compiler warning.
- # Since FORTIFY_SOURCE is a no-op without optimizations, do not enable it when enable_debug is yes.
+ dnl When enable_debug is yes, all optimizations are disabled.
+ dnl However, FORTIFY_SOURCE requires that there is some level of optimization, otherwise it does nothing and just creates a compiler warning.
+ dnl Since FORTIFY_SOURCE is a no-op without optimizations, do not enable it when enable_debug is yes.
if test x$enable_debug != xyes; then
AX_CHECK_PREPROC_FLAG([-D_FORTIFY_SOURCE=2],[
AX_CHECK_PREPROC_FLAG([-U_FORTIFY_SOURCE],[
@@ -783,12 +783,13 @@ fi
dnl this flag screws up non-darwin gcc even when the check fails. special-case it.
if test x$TARGET_OS = xdarwin; then
AX_CHECK_LINK_FLAG([[-Wl,-dead_strip]], [LDFLAGS="$LDFLAGS -Wl,-dead_strip"])
+ AX_CHECK_LINK_FLAG([[-Wl,-dead_strip_dylibs]], [LDFLAGS="$LDFLAGS -Wl,-dead_strip_dylibs"])
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 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
+dnl FD_ZERO may be dependent on a declaration of memcpy, e.g. in SmartOS
+dnl check that it fails to build without memcpy, then that it builds with
AC_MSG_CHECKING(FD_ZERO memcpy dependence)
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <cstddef>
@@ -826,7 +827,7 @@ AC_CHECK_DECLS([getifaddrs, freeifaddrs],,,
)
AC_CHECK_DECLS([strnlen])
-# Check for daemon(3), unrelated to --with-daemon (although used by it)
+dnl Check for daemon(3), unrelated to --with-daemon (although used by it)
AC_CHECK_DECLS([daemon])
AC_CHECK_DECLS([le16toh, le32toh, le64toh, htole16, htole32, htole64, be16toh, be32toh, be64toh, htobe16, htobe32, htobe64],,,
@@ -892,19 +893,19 @@ if test "x$use_thread_local" = xyes || { test "x$use_thread_local" = xauto && te
[
case $host in
*mingw*)
- # mingw32's implementation of thread_local has also been shown to behave
- # erroneously under concurrent usage; see:
- # https://gist.github.com/jamesob/fe9a872051a88b2025b1aa37bfa98605
+ dnl mingw32's implementation of thread_local has also been shown to behave
+ dnl erroneously under concurrent usage; see:
+ dnl https://gist.github.com/jamesob/fe9a872051a88b2025b1aa37bfa98605
AC_MSG_RESULT(no)
;;
*darwin*)
- # TODO enable thread_local on later versions of Darwin where it is
- # supported (per https://stackoverflow.com/a/29929949)
+ dnl TODO enable thread_local on later versions of Darwin where it is
+ dnl supported (per https://stackoverflow.com/a/29929949)
AC_MSG_RESULT(no)
;;
*freebsd*)
- # FreeBSD's implementation of thread_local is also buggy (per
- # https://groups.google.com/d/msg/bsdmailinglist/22ncTZAbDp4/Dii_pII5AwAJ)
+ dnl FreeBSD's implementation of thread_local is also buggy (per
+ dnl https://groups.google.com/d/msg/bsdmailinglist/22ncTZAbDp4/Dii_pII5AwAJ)
AC_MSG_RESULT(no)
;;
*)
@@ -920,7 +921,7 @@ if test "x$use_thread_local" = xyes || { test "x$use_thread_local" = xauto && te
LDFLAGS="$TEMP_LDFLAGS"
fi
-# Check for different ways of gathering OS randomness
+dnl Check for different ways of gathering OS randomness
AC_MSG_CHECKING(for Linux getrandom syscall)
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <unistd.h>
#include <sys/syscall.h>
@@ -974,7 +975,7 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <stdint.h>
[ AC_MSG_RESULT(no)]
)
-# Check for reduced exports
+dnl Check for reduced exports
if test x$use_reduce_exports = xyes; then
AX_CHECK_COMPILE_FLAG([-fvisibility=hidden],[RE_CXXFLAGS="-fvisibility=hidden"],
[AC_MSG_ERROR([Cannot set default symbol visibility. Use --disable-reduce-exports.])])
@@ -986,7 +987,7 @@ AC_LINK_IFELSE(
[[ #include <cstdlib> ]],
[[ int nErr = std::system(""); ]]
)],
- [ AC_MSG_RESULT(yes); AC_DEFINE(HAVE_STD__SYSTEM, 1, Define to 1 if you have the `std::system' function.)],
+ [ AC_MSG_RESULT(yes); AC_DEFINE(HAVE_STD__SYSTEM, 1, Define to 1 if std::system is available.)],
[ AC_MSG_RESULT(no) ]
)
@@ -996,11 +997,10 @@ AC_LINK_IFELSE(
[[ ]],
[[ int nErr = ::_wsystem(""); ]]
)],
- [ AC_MSG_RESULT(yes); AC_DEFINE(HAVE_WSYSTEM, 1, Define to 1 if you have the `::wsystem' function.)],
+ [ AC_MSG_RESULT(yes); AC_DEFINE(HAVE_WSYSTEM, 1, Define to 1 if ::wsystem is available.)],
[ AC_MSG_RESULT(no) ]
)
-# Define to 1 if std::system or ::wsystem (Windows) is available
AC_DEFINE([HAVE_SYSTEM], [HAVE_STD__SYSTEM || HAVE_WSYSTEM], [std::system or ::wsystem])
LEVELDB_CPPFLAGS=
@@ -1471,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")
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&section=all&arch=any&searchon=names&keywords=g%2B%2B)
-# - libc version 2.11.3 (https://packages.debian.org/search?suite=default&section=all&arch=any&searchon=names&keywords=libc6)
-# - libstdc++ version 4.4.5 (https://packages.debian.org/search?suite=default&section=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&section=all)
-# - libc version 2.11.1 (http://packages.ubuntu.com/search?keywords=libc6&searchon=names&suite=lucid&section=all)
-# - libstdc++ version 4.4.3 (http://packages.ubuntu.com/search?suite=lucid&section=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&section=all)
+# - libc version 2.23.0 (https://packages.ubuntu.com/search?keywords=libc6&searchon=names&suite=xenial&section=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 712352d6b7..e38fa6fcb0 100755
--- a/contrib/gitian-build.py
+++ b/contrib/gitian-build.py
@@ -51,7 +51,7 @@ def build():
os.chdir('gitian-builder')
os.makedirs('inputs', exist_ok=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(['wget', '-O', 'inputs/osslsigncode-2.0.tar.gz', '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'])
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 1f5b9d4507..70b7bb111d 100644
--- a/contrib/gitian-descriptors/gitian-win-signer.yml
+++ b/contrib/gitian-descriptors/gitian-win-signer.yml
@@ -19,7 +19,7 @@ files:
script: |
set -e -o pipefail
- BUILD_DIR=`pwd`
+ BUILD_DIR="$PWD"
SIGDIR=${BUILD_DIR}/signature/win
UNSIGNED_DIR=${BUILD_DIR}/unsigned
@@ -35,7 +35,7 @@ script: |
./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/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/.gitignore b/depends/.gitignore
index 72734102c5..19c506ce54 100644
--- a/depends/.gitignore
+++ b/depends/.gitignore
@@ -8,5 +8,7 @@ i686*
mips*
arm*
aarch64*
+powerpc*
riscv32*
riscv64*
+s390x*
diff --git a/depends/Makefile b/depends/Makefile
index cec99777ff..f81bc3001b 100644
--- a/depends/Makefile
+++ b/depends/Makefile
@@ -9,6 +9,7 @@ WORK_PATH = $(BASEDIR)/work
BASE_CACHE ?= $(BASEDIR)/built
SDK_PATH ?= $(BASEDIR)/SDKs
NO_QT ?=
+NO_QR ?=
RAPIDCHECK ?=
NO_WALLET ?=
NO_ZMQ ?=
@@ -100,7 +101,10 @@ $(host_arch)_$(host_os)_id_string+=$(shell $(host_CXX) --version 2>/dev/null)
$(host_arch)_$(host_os)_id_string+=$(shell $(host_RANLIB) --version 2>/dev/null)
$(host_arch)_$(host_os)_id_string+=$(shell $(host_STRIP) --version 2>/dev/null)
-qt_packages_$(NO_QT) = $(qt_packages) $(qt_$(host_os)_packages) $(qt_$(host_arch)_$(host_os)_packages)
+qrencode_packages_$(NO_QR) = $(qrencode_packages)
+
+qt_packages_$(NO_QT) = $(qt_packages) $(qt_$(host_os)_packages) $(qt_$(host_arch)_$(host_os)_packages) $(qrencode_packages_)
+
wallet_packages_$(NO_WALLET) = $(wallet_packages)
upnp_packages_$(NO_UPNP) = $(upnp_packages)
zmq_packages_$(NO_ZMQ) = $(zmq_packages)
@@ -154,6 +158,7 @@ $(host_prefix)/share/config.site : config.site.in $(host_prefix)/.stamp_$(final_
-e 's|@LDFLAGS@|$(strip $(host_LDFLAGS) $(host_$(release_type)_LDFLAGS))|' \
-e 's|@allow_host_packages@|$(ALLOW_HOST_PACKAGES)|' \
-e 's|@no_qt@|$(NO_QT)|' \
+ -e 's|@no_qr@|$(NO_QR)|' \
-e 's|@no_zmq@|$(NO_ZMQ)|' \
-e 's|@no_wallet@|$(NO_WALLET)|' \
-e 's|@no_upnp@|$(NO_UPNP)|' \
@@ -186,7 +191,7 @@ $(host_prefix)/share/config.site: check-packages
check-packages: check-sources
clean-all: clean
- @rm -rf $(SOURCES_PATH) x86_64* i686* mips* arm* aarch64* riscv32* riscv64*
+ @rm -rf $(SOURCES_PATH) x86_64* i686* mips* arm* aarch64* powerpc* riscv32* riscv64* s390x*
clean:
@rm -rf $(WORK_PATH) $(BASE_CACHE) $(BUILD)
diff --git a/depends/README.md b/depends/README.md
index e5e2a8a653..93f619983f 100644
--- a/depends/README.md
+++ b/depends/README.md
@@ -12,24 +12,27 @@ For example:
make HOST=x86_64-w64-mingw32 -j4
-**Bitcoin's configure script by default will ignore the depends output.** In
+**Bitcoin Core's configure script by default will ignore the depends output.** In
order for it to pick up libraries, tools, and settings from the depends build,
you must point it at the appropriate `--prefix` directory generated by the
build. In the above example, a prefix dir named x86_64-w64-mingw32 will be
created. To use it for Bitcoin:
- ./configure --prefix=`pwd`/depends/x86_64-w64-mingw32
+ ./configure --prefix=$PWD/depends/x86_64-w64-mingw32
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
+- `powerpc64-linux-gnu` for Linux POWER 64-bit (big endian)
+- `powerpc64le-linux-gnu` for Linux POWER 64-bit (little endian)
- `riscv32-linux-gnu` for Linux RISC-V 32 bit
- `riscv64-linux-gnu` for Linux RISC-V 64 bit
+- `s390x-linux-gnu` for Linux S390X
- `armv7a-linux-android` for Android ARM 32 bit
- `aarch64-linux-android` for Android ARM 64 bit
- `i686-linux-android` for Android x86 32 bit
@@ -61,6 +64,10 @@ For linux AARCH64 cross compilation:
sudo apt-get install g++-aarch64-linux-gnu binutils-aarch64-linux-gnu
+For linux POWER 64-bit cross compilation (there are no packages for 32-bit):
+
+ sudo apt-get install g++-powerpc64-linux-gnu binutils-powerpc64-linux-gnu g++-powerpc64le-linux-gnu binutils-powerpc64le-linux-gnu
+
For linux RISC-V 64-bit cross compilation (there are no packages for 32-bit):
sudo apt-get install g++-riscv64-linux-gnu binutils-riscv64-linux-gnu
@@ -68,6 +75,10 @@ For linux RISC-V 64-bit cross compilation (there are no packages for 32-bit):
RISC-V known issue: gcc-7.3.0 and gcc-7.3.1 result in a broken `test_bitcoin` executable (see https://github.com/bitcoin/bitcoin/pull/13543),
this is apparently fixed in gcc-8.1.0.
+For linux S390X cross compilation:
+
+ sudo apt-get install g++-s390x-linux-gnu binutils-s390x-linux-gnu
+
### Dependency Options
The following can be set when running make: make FOO=bar
@@ -76,6 +87,7 @@ The following can be set when running make: make FOO=bar
SDK_PATH: Path where sdk's can be found (used by macOS)
FALLBACK_DOWNLOAD_PATH: If a source file can't be fetched, try here before giving up
NO_QT: Don't download/build/cache qt and its dependencies
+ NO_QR: Don't download/build/cache packages needed for enabling qrencode
NO_ZMQ: Don't download/build/cache packages needed for enabling zeromq
NO_WALLET: Don't download/build/cache libs needed to enable the wallet
NO_UPNP: Don't download/build/cache packages needed for enabling upnp
diff --git a/depends/config.site.in b/depends/config.site.in
index dee568bc25..c5731e5269 100644
--- a/depends/config.site.in
+++ b/depends/config.site.in
@@ -17,6 +17,10 @@ if test -z $with_qt_bindir && test -z "@no_qt@"; then
with_qt_bindir=$depends_prefix/native/bin
fi
+if test -z $with_qrencode && test -n "@no_qr@"; then
+ with_qrencode=no
+fi
+
if test -z $enable_wallet && test -n "@no_wallet@"; then
enable_wallet=no
fi
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/packages.mk b/depends/packages/packages.mk
index 09f3187ac4..d8ccb208cc 100644
--- a/depends/packages/packages.mk
+++ b/depends/packages/packages.mk
@@ -1,6 +1,8 @@
packages:=boost libevent
-qt_packages = qrencode zlib
+qt_packages = zlib
+
+qrencode_packages = qrencode
qt_linux_packages:=qt expat libxcb xcb_proto libXau xproto freetype fontconfig
qt_android_packages=qt
diff --git a/depends/packages/qt.mk b/depends/packages/qt.mk
index 6ac6ba6838..2087fec14d 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,11 @@ $(package)_config_opts += -no-feature-vnc
$(package)_config_opts += -no-feature-wizard
$(package)_config_opts += -no-feature-xml
+$(package)_config_opts_darwin = -no-dbus
+$(package)_config_opts_darwin += -no-opengl
+
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 +124,20 @@ $(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_powerpc64_linux = -platform linux-g++ -xplatform bitcoin-linux-g++
+$(package)_config_opts_powerpc64le_linux = -platform linux-g++ -xplatform bitcoin-linux-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_s390x_linux = -platform linux-g++ -xplatform bitcoin-linux-g++
+
+$(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 +147,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
diff --git a/depends/packages/xcb_proto.mk b/depends/packages/xcb_proto.mk
index 85d01ecd2f..01203a0718 100644
--- a/depends/packages/xcb_proto.mk
+++ b/depends/packages/xcb_proto.mk
@@ -4,11 +4,6 @@ $(package)_download_path=https://xcb.freedesktop.org/dist
$(package)_file_name=xcb-proto-$($(package)_version).tar.bz2
$(package)_sha256_hash=7ef40ddd855b750bc597d2a435da21e55e502a0fefa85b274f2c922800baaf05
-define $(package)_set_vars
- $(package)_config_opts=--disable-shared --enable-option-checking
- $(package)_config_opts_linux=--with-pic
-endef
-
define $(package)_config_cmds
$($(package)_autoconf)
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/doc/README.md b/doc/README.md
index 46b311b251..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)
diff --git a/doc/build-osx.md b/doc/build-osx.md
index e435798e95..bf655538c7 100644
--- a/doc/build-osx.md
+++ b/doc/build-osx.md
@@ -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/dependencies.md b/doc/dependencies.md
index bfb663866d..b739881a7a 100644
--- a/doc/dependencies.md
+++ b/doc/dependencies.md
@@ -13,10 +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 | | |
+| MiniUPnPc | [2.0.20180203](https://miniupnp.tuxfamily.org/files) | | No | | |
| 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 5f9c18f2f5..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)
@@ -63,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,
@@ -77,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
@@ -208,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
@@ -234,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
@@ -276,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
@@ -312,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
@@ -373,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
@@ -387,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.
@@ -401,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.
@@ -467,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.
@@ -546,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.
diff --git a/doc/release-notes.md b/doc/release-notes.md
index 33a127e0d0..cdf83178c6 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.
@@ -69,6 +68,10 @@ 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
--------
@@ -87,6 +90,8 @@ Low-level Changes section below.
GUI changes
-----------
+- The "Start Bitcoin Core on system login" option has been removed on macOS.
+
Wallet
------
@@ -99,6 +104,10 @@ Low-level changes
Tests
-----
+- It is now an error to use an unqualified `walletdir=path` setting in the config file if running on testnet or regtest
+ networks. The setting now needs to be qualified as `chain.walletdir=path` or placed in the appropriate `[chain]`
+ section. (#17447)
+
- `-fallbackfee` was 0 (disabled) by default for the main chain, but 0.0002 by default for the test chains. Now it is 0
by default for all chains. Testnet and regtest users will have to add `fallbackfee=0.0002` to their configuration if
they weren't setting it and they want it to keep working like before. (#16524)
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 6d1e7c69e9..36d79a0c34 100644
--- a/doc/release-process.md
+++ b/doc/release-process.md
@@ -116,7 +116,7 @@ Ensure gitian-builder is up-to-date:
pushd ./gitian-builder
mkdir -p inputs
- wget -O osslsigncode-2.0.tar.gz -P inputs https://github.com/mtrojnar/osslsigncode/archive/2.0.tar.gz
+ wget -O inputs/osslsigncode-2.0.tar.gz https://github.com/mtrojnar/osslsigncode/archive/2.0.tar.gz
echo '5a60e0a4b3e0b4d655317b2f12a810211c50242138322b16e7e01c6fbb89d92f inputs/osslsigncode-2.0.tar.gz' | sha256sum -c
popd
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 ffb97f26d7..27c87688b4 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -717,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 acd712c8a2..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) \
diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include
index 93e60ff832..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 \
diff --git a/src/Makefile.qttest.include b/src/Makefile.qttest.include
index 37e1da2a78..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
diff --git a/src/Makefile.test.include b/src/Makefile.test.include
index a2c76df91c..0225edf29e 100644
--- a/src/Makefile.test.include
+++ b/src/Makefile.test.include
@@ -4,11 +4,15 @@
FUZZ_TARGETS = \
+ test/fuzz/addr_info_deserialize \
test/fuzz/address_deserialize \
test/fuzz/addrman_deserialize \
test/fuzz/banentry_deserialize \
test/fuzz/bech32 \
test/fuzz/block_deserialize \
+ test/fuzz/block_file_info_deserialize \
+ test/fuzz/block_filter_deserialize \
+ test/fuzz/block_header_and_short_txids_deserialize \
test/fuzz/blockheader_deserialize \
test/fuzz/blocklocator_deserialize \
test/fuzz/blockmerkleroot \
@@ -20,16 +24,37 @@ FUZZ_TARGETS = \
test/fuzz/descriptor_parse \
test/fuzz/diskblockindex_deserialize \
test/fuzz/eval_script \
+ test/fuzz/fee_rate_deserialize \
+ test/fuzz/flat_file_pos_deserialize \
+ test/fuzz/integer \
test/fuzz/inv_deserialize \
+ test/fuzz/key_origin_info_deserialize \
+ test/fuzz/merkle_block_deserialize \
test/fuzz/messageheader_deserialize \
test/fuzz/netaddr_deserialize \
+ test/fuzz/out_point_deserialize \
+ test/fuzz/parse_hd_keypath \
test/fuzz/parse_iso8601 \
+ test/fuzz/partial_merkle_tree_deserialize \
+ test/fuzz/partially_signed_transaction_deserialize \
+ test/fuzz/prefilled_transaction_deserialize \
+ test/fuzz/parse_numbers \
+ test/fuzz/parse_script \
+ test/fuzz/parse_univalue \
test/fuzz/psbt \
+ test/fuzz/psbt_input_deserialize \
+ test/fuzz/psbt_output_deserialize \
+ test/fuzz/pub_key_deserialize \
test/fuzz/script \
+ test/fuzz/script_deserialize \
test/fuzz/script_flags \
test/fuzz/service_deserialize \
test/fuzz/spanparsing \
+ test/fuzz/sub_net_deserialize \
test/fuzz/transaction \
+ test/fuzz/tx_in \
+ test/fuzz/tx_in_deserialize \
+ test/fuzz/tx_out \
test/fuzz/txoutcompressor_deserialize \
test/fuzz/txundo_deserialize
@@ -58,33 +83,22 @@ 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) \
+ $(LIBBITCOIN_CLI) \
$(LIBUNIVALUE) \
$(LIBLEVELDB) \
$(LIBLEVELDB_SSE42) \
@@ -198,7 +212,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
@@ -359,6 +373,12 @@ test_fuzz_eval_script_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_eval_script_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
test_fuzz_eval_script_LDADD = $(FUZZ_SUITE_LD_COMMON)
+test_fuzz_integer_SOURCES = $(FUZZ_SUITE) test/fuzz/integer.cpp
+test_fuzz_integer_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
+test_fuzz_integer_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+test_fuzz_integer_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_integer_LDADD = $(FUZZ_SUITE_LD_COMMON)
+
test_fuzz_txoutcompressor_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
test_fuzz_txoutcompressor_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DTXOUTCOMPRESSOR_DESERIALIZE=1
test_fuzz_txoutcompressor_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
@@ -383,6 +403,150 @@ test_fuzz_transaction_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_transaction_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
test_fuzz_transaction_LDADD = $(FUZZ_SUITE_LD_COMMON)
+test_fuzz_addr_info_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+test_fuzz_addr_info_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DADDR_INFO_DESERIALIZE=1
+test_fuzz_addr_info_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+test_fuzz_addr_info_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_addr_info_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
+
+test_fuzz_block_file_info_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+test_fuzz_block_file_info_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCK_FILE_INFO_DESERIALIZE=1
+test_fuzz_block_file_info_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+test_fuzz_block_file_info_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_block_file_info_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
+
+test_fuzz_block_filter_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+test_fuzz_block_filter_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCK_FILTER_DESERIALIZE=1
+test_fuzz_block_filter_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+test_fuzz_block_filter_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_block_filter_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
+
+test_fuzz_block_header_and_short_txids_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+test_fuzz_block_header_and_short_txids_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCK_HEADER_AND_SHORT_TXIDS_DESERIALIZE=1
+test_fuzz_block_header_and_short_txids_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+test_fuzz_block_header_and_short_txids_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_block_header_and_short_txids_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
+
+test_fuzz_fee_rate_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+test_fuzz_fee_rate_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DFEE_RATE_DESERIALIZE=1
+test_fuzz_fee_rate_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+test_fuzz_fee_rate_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_fee_rate_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
+
+test_fuzz_flat_file_pos_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+test_fuzz_flat_file_pos_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DFLAT_FILE_POS_DESERIALIZE=1
+test_fuzz_flat_file_pos_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+test_fuzz_flat_file_pos_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_flat_file_pos_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
+
+test_fuzz_key_origin_info_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+test_fuzz_key_origin_info_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DKEY_ORIGIN_INFO_DESERIALIZE=1
+test_fuzz_key_origin_info_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+test_fuzz_key_origin_info_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_key_origin_info_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
+
+test_fuzz_merkle_block_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+test_fuzz_merkle_block_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMERKLE_BLOCK_DESERIALIZE=1
+test_fuzz_merkle_block_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+test_fuzz_merkle_block_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_merkle_block_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
+
+test_fuzz_out_point_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+test_fuzz_out_point_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DOUT_POINT_DESERIALIZE=1
+test_fuzz_out_point_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+test_fuzz_out_point_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_out_point_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
+
+test_fuzz_partially_signed_transaction_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+test_fuzz_partially_signed_transaction_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DPARTIALLY_SIGNED_TRANSACTION_DESERIALIZE=1
+test_fuzz_partially_signed_transaction_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+test_fuzz_partially_signed_transaction_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_partially_signed_transaction_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
+
+test_fuzz_partial_merkle_tree_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+test_fuzz_partial_merkle_tree_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DPARTIAL_MERKLE_TREE_DESERIALIZE=1
+test_fuzz_partial_merkle_tree_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+test_fuzz_partial_merkle_tree_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_partial_merkle_tree_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
+
+test_fuzz_prefilled_transaction_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+test_fuzz_prefilled_transaction_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DPREFILLED_TRANSACTION_DESERIALIZE=1
+test_fuzz_prefilled_transaction_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+test_fuzz_prefilled_transaction_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_prefilled_transaction_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
+
+test_fuzz_psbt_input_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+test_fuzz_psbt_input_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DPSBT_INPUT_DESERIALIZE=1
+test_fuzz_psbt_input_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+test_fuzz_psbt_input_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_psbt_input_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
+
+test_fuzz_psbt_output_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+test_fuzz_psbt_output_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DPSBT_OUTPUT_DESERIALIZE=1
+test_fuzz_psbt_output_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+test_fuzz_psbt_output_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_psbt_output_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
+
+test_fuzz_pub_key_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+test_fuzz_pub_key_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DPUB_KEY_DESERIALIZE=1
+test_fuzz_pub_key_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+test_fuzz_pub_key_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_pub_key_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
+
+test_fuzz_script_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+test_fuzz_script_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DSCRIPT_DESERIALIZE=1
+test_fuzz_script_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+test_fuzz_script_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_script_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
+
+test_fuzz_sub_net_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+test_fuzz_sub_net_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DSUB_NET_DESERIALIZE=1
+test_fuzz_sub_net_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+test_fuzz_sub_net_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_sub_net_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
+
+test_fuzz_tx_in_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+test_fuzz_tx_in_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DTX_IN_DESERIALIZE=1
+test_fuzz_tx_in_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+test_fuzz_tx_in_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_tx_in_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
+
+test_fuzz_tx_in_SOURCES = $(FUZZ_SUITE) test/fuzz/tx_in.cpp
+test_fuzz_tx_in_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
+test_fuzz_tx_in_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+test_fuzz_tx_in_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_tx_in_LDADD = $(FUZZ_SUITE_LD_COMMON)
+
+test_fuzz_tx_out_SOURCES = $(FUZZ_SUITE) test/fuzz/tx_out.cpp
+test_fuzz_tx_out_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
+test_fuzz_tx_out_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+test_fuzz_tx_out_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_tx_out_LDADD = $(FUZZ_SUITE_LD_COMMON)
+
+test_fuzz_parse_hd_keypath_SOURCES = $(FUZZ_SUITE) test/fuzz/parse_hd_keypath.cpp
+test_fuzz_parse_hd_keypath_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
+test_fuzz_parse_hd_keypath_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+test_fuzz_parse_hd_keypath_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_parse_hd_keypath_LDADD = $(FUZZ_SUITE_LD_COMMON)
+
+test_fuzz_parse_script_SOURCES = $(FUZZ_SUITE) test/fuzz/parse_script.cpp
+test_fuzz_parse_script_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
+test_fuzz_parse_script_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+test_fuzz_parse_script_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_parse_script_LDADD = $(FUZZ_SUITE_LD_COMMON)
+
+test_fuzz_parse_numbers_SOURCES = $(FUZZ_SUITE) test/fuzz/parse_numbers.cpp
+test_fuzz_parse_numbers_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
+test_fuzz_parse_numbers_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+test_fuzz_parse_numbers_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_parse_numbers_LDADD = $(FUZZ_SUITE_LD_COMMON)
+
+test_fuzz_parse_univalue_SOURCES = $(FUZZ_SUITE) test/fuzz/parse_univalue.cpp
+test_fuzz_parse_univalue_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
+test_fuzz_parse_univalue_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+test_fuzz_parse_univalue_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_parse_univalue_LDADD = $(FUZZ_SUITE_LD_COMMON)
+
endif # ENABLE_FUZZ
nodist_test_test_bitcoin_SOURCES = $(GENERATED_TEST_FILES)
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-cli.cpp b/src/bitcoin-cli.cpp
index 592fcbe8dd..1035e730b8 100644
--- a/src/bitcoin-cli.cpp
+++ b/src/bitcoin-cli.cpp
@@ -256,7 +256,6 @@ public:
return batch[ID_BLOCKCHAININFO];
}
result.pushKV("version", batch[ID_NETWORKINFO]["result"]["version"]);
- result.pushKV("protocolversion", batch[ID_NETWORKINFO]["result"]["protocolversion"]);
result.pushKV("blocks", batch[ID_BLOCKCHAININFO]["result"]["blocks"]);
result.pushKV("headers", batch[ID_BLOCKCHAININFO]["result"]["headers"]);
result.pushKV("verificationprogress", batch[ID_BLOCKCHAININFO]["result"]["verificationprogress"]);
@@ -266,9 +265,7 @@ public:
result.pushKV("difficulty", batch[ID_BLOCKCHAININFO]["result"]["difficulty"]);
result.pushKV("chain", UniValue(batch[ID_BLOCKCHAININFO]["result"]["chain"]));
if (!batch[ID_WALLETINFO]["result"].isNull()) {
- result.pushKV("walletversion", batch[ID_WALLETINFO]["result"]["walletversion"]);
result.pushKV("balance", batch[ID_WALLETINFO]["result"]["balance"]);
- result.pushKV("keypoololdest", batch[ID_WALLETINFO]["result"]["keypoololdest"]);
result.pushKV("keypoolsize", batch[ID_WALLETINFO]["result"]["keypoolsize"]);
if (!batch[ID_WALLETINFO]["result"]["unlocked_until"].isNull()) {
result.pushKV("unlocked_until", batch[ID_WALLETINFO]["result"]["unlocked_until"]);
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/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/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 421768441e..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__);
}
@@ -1262,7 +1262,6 @@ bool AppInitMain(NodeContext& node)
}, 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
@@ -1635,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);
diff --git a/src/key.h b/src/key.h
index 6a86b0411d..1d401a0c8a 100644
--- a/src/key.h
+++ b/src/key.h
@@ -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/node/psbt.cpp b/src/node/psbt.cpp
index 12559c5a5f..9a30c3f083 100644
--- a/src/node/psbt.cpp
+++ b/src/node/psbt.cpp
@@ -7,6 +7,7 @@
#include <node/psbt.h>
#include <policy/policy.h>
#include <policy/settings.h>
+#include <tinyformat.h>
#include <numeric>
@@ -39,6 +40,11 @@ PSBTAnalysis AnalyzePSBT(PartiallySignedTransaction psbtx)
calc_fee = false;
}
+ if (!utxo.IsNull() && utxo.scriptPubKey.IsUnspendable()) {
+ result.SetInvalid(strprintf("PSBT is not valid. Input %u spends unspendable output", i));
+ return result;
+ }
+
// Check if it is final
if (!utxo.IsNull() && !PSBTInputSigned(input)) {
input_analysis.is_final = false;
diff --git a/src/node/psbt.h b/src/node/psbt.h
index e04366a20f..7384dc415c 100644
--- a/src/node/psbt.h
+++ b/src/node/psbt.h
@@ -30,6 +30,17 @@ struct PSBTAnalysis {
Optional<CAmount> fee; //!< Amount of fee being paid by the transaction
std::vector<PSBTInputAnalysis> inputs; //!< More information about the individual inputs of the transaction
PSBTRole next; //!< Which of the BIP 174 roles needs to handle the transaction next
+ std::string error; //!< Error message
+
+ void SetInvalid(std::string err_msg)
+ {
+ estimated_vsize = nullopt;
+ estimated_feerate = nullopt;
+ fee = nullopt;
+ inputs.clear();
+ next = PSBTRole::CREATOR;
+ error = err_msg;
+ }
};
/**
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/protocol.h b/src/protocol.h
index 3032310fa1..db07efb9f9 100644
--- a/src/protocol.h
+++ b/src/protocol.h
@@ -237,6 +237,7 @@ const std::vector<std::string> &getAllNetMessageTypes();
/** nServices flags */
enum ServiceFlags : uint64_t {
+ // NOTE: When adding here, be sure to update qt/guiutil.cpp's formatServicesStr too
// Nothing
NODE_NONE = 0,
// NODE_NETWORK means that the node is capable of serving the complete block chain. It is currently
diff --git a/src/psbt.cpp b/src/psbt.cpp
index c306079b1e..9ede62efdf 100644
--- a/src/psbt.cpp
+++ b/src/psbt.cpp
@@ -348,6 +348,7 @@ TransactionError CombinePSBTs(PartiallySignedTransaction& out, const std::vector
std::string PSBTRoleName(PSBTRole role) {
switch (role) {
+ case PSBTRole::CREATOR: return "creator";
case PSBTRole::UPDATER: return "updater";
case PSBTRole::SIGNER: return "signer";
case PSBTRole::FINALIZER: return "finalizer";
diff --git a/src/psbt.h b/src/psbt.h
index 6a5c468058..d507d5b6b7 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
@@ -560,6 +560,7 @@ struct PartiallySignedTransaction
};
enum class PSBTRole {
+ CREATOR,
UPDATER,
SIGNER,
FINALIZER,
diff --git a/src/pubkey.cpp b/src/pubkey.cpp
index d38df716bd..21e51a380d 100644
--- a/src/pubkey.cpp
+++ b/src/pubkey.cpp
@@ -171,6 +171,7 @@ bool CPubKey::Verify(const uint256 &hash, const std::vector<unsigned char>& vchS
return false;
secp256k1_pubkey pubkey;
secp256k1_ecdsa_signature sig;
+ assert(secp256k1_context_verify && "secp256k1_context_verify must be initialized to use CPubKey.");
if (!secp256k1_ec_pubkey_parse(secp256k1_context_verify, &pubkey, vch, size())) {
return false;
}
@@ -190,14 +191,15 @@ bool CPubKey::RecoverCompact(const uint256 &hash, const std::vector<unsigned cha
bool fComp = ((vchSig[0] - 27) & 4) != 0;
secp256k1_pubkey pubkey;
secp256k1_ecdsa_recoverable_signature sig;
+ assert(secp256k1_context_verify && "secp256k1_context_verify must be initialized to use CPubKey.");
if (!secp256k1_ecdsa_recoverable_signature_parse_compact(secp256k1_context_verify, &sig, &vchSig[1], recid)) {
return false;
}
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;
@@ -207,6 +209,7 @@ bool CPubKey::IsFullyValid() const {
if (!IsValid())
return false;
secp256k1_pubkey pubkey;
+ assert(secp256k1_context_verify && "secp256k1_context_verify must be initialized to use CPubKey.");
return secp256k1_ec_pubkey_parse(secp256k1_context_verify, &pubkey, vch, size());
}
@@ -214,11 +217,12 @@ bool CPubKey::Decompress() {
if (!IsValid())
return false;
secp256k1_pubkey pubkey;
+ assert(secp256k1_context_verify && "secp256k1_context_verify must be initialized to use CPubKey.");
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,19 +231,20 @@ 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);
secp256k1_pubkey pubkey;
+ assert(secp256k1_context_verify && "secp256k1_context_verify must be initialized to use CPubKey.");
if (!secp256k1_ec_pubkey_parse(secp256k1_context_verify, &pubkey, vch, size())) {
return false;
}
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 +256,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]) {
@@ -273,6 +278,7 @@ bool CExtPubKey::Derive(CExtPubKey &out, unsigned int _nChild) const {
/* static */ bool CPubKey::CheckLowS(const std::vector<unsigned char>& vchSig) {
secp256k1_ecdsa_signature sig;
+ assert(secp256k1_context_verify && "secp256k1_context_verify must be initialized to use CPubKey.");
if (!ecdsa_signature_parse_der_lax(secp256k1_context_verify, &sig, vchSig.data(), vchSig.size())) {
return false;
}
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/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index 2aeba6d82c..8444984b27 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -341,6 +341,7 @@ void BitcoinGUI::createActions()
m_close_wallet_action->setStatusTip(tr("Close wallet"));
m_create_wallet_action = new QAction(tr("Create Wallet..."), this);
+ m_create_wallet_action->setEnabled(false);
m_create_wallet_action->setStatusTip(tr("Create a new wallet"));
showHelpMessageAction = new QAction(tr("&Command-line options"), this);
@@ -618,6 +619,7 @@ void BitcoinGUI::setWalletController(WalletController* wallet_controller)
m_wallet_controller = wallet_controller;
+ m_create_wallet_action->setEnabled(true);
m_open_wallet_action->setEnabled(true);
m_open_wallet_action->setMenu(m_open_wallet_menu);
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/openuridialog.ui b/src/qt/forms/openuridialog.ui
index 2acec314fd..1b7291ab9d 100644
--- a/src/qt/forms/openuridialog.ui
+++ b/src/qt/forms/openuridialog.ui
@@ -24,7 +24,11 @@
</widget>
</item>
<item>
- <widget class="QValidatedLineEdit" name="uriEdit"/>
+ <widget class="QValidatedLineEdit" name="uriEdit">
+ <property name="placeholderText">
+ <string notr="true">bitcoin:</string>
+ </property>
+ </widget>
</item>
</layout>
</item>
diff --git a/src/qt/forms/optionsdialog.ui b/src/qt/forms/optionsdialog.ui
index 240a7a7e92..fea759dee0 100644
--- a/src/qt/forms/optionsdialog.ui
+++ b/src/qt/forms/optionsdialog.ui
@@ -685,6 +685,9 @@
<property name="toolTip">
<string>Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |.</string>
</property>
+ <property name="placeholderText">
+ <string notr="true">https://example.com/tx/%s</string>
+ </property>
</widget>
</item>
</layout>
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/forms/sendcoinsentry.ui b/src/qt/forms/sendcoinsentry.ui
index 843d909f68..934363af1f 100644
--- a/src/qt/forms/sendcoinsentry.ui
+++ b/src/qt/forms/sendcoinsentry.ui
@@ -144,6 +144,9 @@
<property name="toolTip">
<string>Enter a label for this address to add it to the list of used addresses</string>
</property>
+ <property name="placeholderText">
+ <string>Enter a label for this address to add it to the list of used addresses</string>
+ </property>
</widget>
</item>
<item row="2" column="0">
diff --git a/src/qt/forms/signverifymessagedialog.ui b/src/qt/forms/signverifymessagedialog.ui
index 202edf27d4..f42d19093b 100644
--- a/src/qt/forms/signverifymessagedialog.ui
+++ b/src/qt/forms/signverifymessagedialog.ui
@@ -121,6 +121,9 @@
</property>
<item>
<widget class="QLineEdit" name="signatureOut_SM">
+ <property name="placeholderText">
+ <string>Click "Sign Message" to generate signature</string>
+ </property>
<property name="font">
<font>
<italic>true</italic>
diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp
index c4e0321f28..843de651e5 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, &currentItemURL, nullptr);
-#endif
-#else
- LSSharedFileListItemResolve(item, resolutionFlags, &currentItemURL, 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; }
@@ -815,32 +731,33 @@ QString formatDurationStr(int secs)
return strList.join(" ");
}
+QString serviceFlagToStr(const quint64 mask, const int bit)
+{
+ switch (ServiceFlags(mask)) {
+ case NODE_NONE: abort(); // impossible
+ case NODE_NETWORK: return "NETWORK";
+ case NODE_GETUTXO: return "GETUTXO";
+ case NODE_BLOOM: return "BLOOM";
+ case NODE_WITNESS: return "WITNESS";
+ case NODE_NETWORK_LIMITED: return "NETWORK_LIMITED";
+ // Not using default, so we get warned when a case is missing
+ }
+ if (bit < 8) {
+ return QString("%1[%2]").arg("UNKNOWN").arg(mask);
+ } else {
+ return QString("%1[2^%2]").arg("UNKNOWN").arg(bit);
+ }
+}
+
QString formatServicesStr(quint64 mask)
{
QStringList strList;
- // Just scan the last 8 bits for now.
- for (int i = 0; i < 8; i++) {
- uint64_t check = 1 << i;
+ for (int i = 0; i < 64; i++) {
+ uint64_t check = 1LL << i;
if (mask & check)
{
- switch (check)
- {
- case NODE_NETWORK:
- strList.append("NETWORK");
- break;
- case NODE_GETUTXO:
- strList.append("GETUTXO");
- break;
- case NODE_BLOOM:
- strList.append("BLOOM");
- break;
- case NODE_WITNESS:
- strList.append("WITNESS");
- break;
- default:
- strList.append(QString("%1[%2]").arg("UNKNOWN").arg(check));
- }
+ strList.append(serviceFlagToStr(check, i));
}
}
diff --git a/src/qt/openuridialog.cpp b/src/qt/openuridialog.cpp
index 199804f84d..9dc64bb23a 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>
@@ -15,7 +15,6 @@ OpenURIDialog::OpenURIDialog(QWidget *parent) :
ui(new Ui::OpenURIDialog)
{
ui->setupUi(this);
- ui->uriEdit->setPlaceholderText("bitcoin:");
}
OpenURIDialog::~OpenURIDialog()
diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp
index 57cafaaac0..3fffb8a288 100644
--- a/src/qt/optionsdialog.cpp
+++ b/src/qt/optionsdialog.cpp
@@ -71,17 +71,17 @@ 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 */
+ /* remove Wallet tab and 3rd party-URL textbox in case of -disablewallet */
if (!enableWallet) {
ui->tabWidget->removeTab(ui->tabWidget->indexOf(ui->tabWallet));
+ ui->thirdPartyTxUrlsLabel->setVisible(false);
+ ui->thirdPartyTxUrls->setVisible(false);
}
/* Display elements init */
@@ -110,8 +110,6 @@ OptionsDialog::OptionsDialog(QWidget *parent, bool enableWallet) :
ui->lang->addItem(locale.nativeLanguageName() + QString(" (") + langStr + QString(")"), QVariant(langStr));
}
}
- ui->thirdPartyTxUrls->setPlaceholderText("https://example.com/tx/%s");
-
ui->unit->setModel(new BitcoinUnits(this));
/* Widget-to-option mapper */
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..610dfbb85a 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>
@@ -36,7 +37,6 @@ SendCoinsEntry::SendCoinsEntry(const PlatformStyle *_platformStyle, QWidget *par
if (platformStyle->getUseExtraSpacing())
ui->payToLayout->setSpacing(4);
- ui->addAsLabel->setPlaceholderText(tr("Enter a label for this address to add it to your address book"));
// normal bitcoin address field
GUIUtil::setupAddressWidget(ui->payTo, this);
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..81e9d33a60 100644
--- a/src/qt/signverifymessagedialog.cpp
+++ b/src/qt/signverifymessagedialog.cpp
@@ -35,8 +35,6 @@ SignVerifyMessageDialog::SignVerifyMessageDialog(const PlatformStyle *_platformS
ui->verifyMessageButton_VM->setIcon(platformStyle->SingleColorIcon(":/icons/transaction_0"));
ui->clearButton_VM->setIcon(platformStyle->SingleColorIcon(":/icons/remove"));
- ui->signatureOut_SM->setPlaceholderText(tr("Click \"Sign Message\" to generate signature"));
-
GUIUtil::setupAddressWidget(ui->addressIn_SM, this);
GUIUtil::setupAddressWidget(ui->addressIn_VM, this);
@@ -136,7 +134,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/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/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/random.cpp b/src/random.cpp
index 47d76d8700..99927fc5d2 100644
--- a/src/random.cpp
+++ b/src/random.cpp
@@ -6,6 +6,7 @@
#include <random.h>
#include <compat/cpuid.h>
+#include <crypto/sha256.h>
#include <crypto/sha512.h>
#include <support/cleanse.h>
#ifdef WIN32
@@ -178,7 +179,7 @@ static uint64_t GetRdSeed() noexcept
/* Access to other hardware random number generators could be added here later,
* assuming it is sufficiently fast (in the order of a few hundred CPU cycles).
* Slower sources should probably be invoked separately, and/or only from
- * RandAddSeedSleep (which is called during idle background operation).
+ * RandAddPeriodic (which is called once a minute).
*/
static void InitHardwareRand() {}
static void ReportHardwareRand() {}
@@ -359,6 +360,9 @@ class RNGState {
uint64_t m_counter GUARDED_BY(m_mutex) = 0;
bool m_strongly_seeded GUARDED_BY(m_mutex) = false;
+ Mutex m_events_mutex;
+ CSHA256 m_events_hasher GUARDED_BY(m_events_mutex);
+
public:
RNGState() noexcept
{
@@ -369,6 +373,35 @@ public:
{
}
+ void AddEvent(uint32_t event_info) noexcept
+ {
+ LOCK(m_events_mutex);
+
+ m_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);
+ m_events_hasher.Write((const unsigned char*)&perfcounter, sizeof(perfcounter));
+ }
+
+ /**
+ * Feed (the hash of) all events added through AddEvent() to hasher.
+ */
+ void SeedEvents(CSHA512& hasher) noexcept
+ {
+ // 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.
+ LOCK(m_events_mutex);
+
+ unsigned char events_hash[32];
+ m_events_hasher.Finalize(events_hash);
+ hasher.Write(events_hash, 32);
+
+ // Re-initialize the hasher with the finalized state to use later.
+ m_events_hasher.Reset();
+ m_events_hasher.Write(events_hash, 32);
+ }
+
/** Extract up to 32 bytes of entropy from the RNG state, mixing in new entropy from hasher.
*
* If this function has never been called with strong_seed = true, false is returned.
@@ -415,17 +448,7 @@ RNGState& GetRNGState() noexcept
/* 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
- * of MilliSleep in SeedSleep, which can (and does) support interruptions which
- * cause a boost::thread_interrupted to be thrown.
- *
- * This means that SeedSleep, and all functions that invoke it are throwing.
- * However, we know that GetRandBytes() and GetStrongRandBytes() never trigger
- * this sleeping logic, so they are noexcept. The same is true for all the
- * GetRand*() functions that use GetRandBytes() indirectly.
- *
- * TODO: After moving away from interruptible boost-based thread management,
- * everything can become noexcept here.
+ * None of the RNG code should ever throw any exception.
*/
static void SeedTimestamp(CSHA512& hasher) noexcept
@@ -449,7 +472,7 @@ static void SeedFast(CSHA512& hasher) noexcept
SeedTimestamp(hasher);
}
-static void SeedSlow(CSHA512& hasher) noexcept
+static void SeedSlow(CSHA512& hasher, RNGState& rng) noexcept
{
unsigned char buffer[32];
@@ -460,6 +483,9 @@ static void SeedSlow(CSHA512& hasher) noexcept
GetOSRand(buffer);
hasher.Write(buffer, sizeof(buffer));
+ // Add the events hasher into the mix
+ rng.SeedEvents(hasher);
+
// High-precision timestamp.
//
// Note that we also commit to a timestamp in the Fast seeder, so we indirectly commit to a
@@ -477,7 +503,7 @@ static void SeedStrengthen(CSHA512& hasher, RNGState& rng, int microseconds) noe
Strengthen(strengthen_seed, microseconds, hasher);
}
-static void SeedPeriodic(CSHA512& hasher, RNGState& rng)
+static void SeedPeriodic(CSHA512& hasher, RNGState& rng) noexcept
{
// Everything that the 'fast' seeder includes
SeedFast(hasher);
@@ -485,10 +511,13 @@ static void SeedPeriodic(CSHA512& hasher, RNGState& rng)
// High-precision timestamp
SeedTimestamp(hasher);
+ // Add the events hasher into the mix
+ rng.SeedEvents(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);
+ LogPrint(BCLog::RAND, "Feeding %i bytes of dynamic environment data into RNG\n", hasher.Size() - old_size);
// Strengthen for 10 ms
SeedStrengthen(hasher, rng, 10000);
@@ -500,7 +529,7 @@ static void SeedStartup(CSHA512& hasher, RNGState& rng) noexcept
SeedHardwareSlow(hasher);
// Everything that the 'slow' seeder includes.
- SeedSlow(hasher);
+ SeedSlow(hasher, rng);
// Dynamic environment data (performance monitoring, ...)
auto old_size = hasher.Size();
@@ -508,7 +537,7 @@ static void SeedStartup(CSHA512& hasher, RNGState& rng) noexcept
// Static environment data
RandAddStaticEnv(hasher);
- LogPrintf("Feeding %i bytes of environment data into RNG\n", hasher.Size() - old_size);
+ LogPrint(BCLog::RAND, "Feeding %i bytes of environment data into RNG\n", hasher.Size() - old_size);
// Strengthen for 100 ms
SeedStrengthen(hasher, rng, 100000);
@@ -520,7 +549,7 @@ enum class RNGLevel {
PERIODIC, //!< Called by RandAddPeriodic()
};
-static void ProcRand(unsigned char* out, int num, RNGLevel level)
+static void ProcRand(unsigned char* out, int num, RNGLevel level) noexcept
{
// Make sure the RNG is initialized first (as all Seed* function possibly need hwrand to be available).
RNGState& rng = GetRNGState();
@@ -533,7 +562,7 @@ static void ProcRand(unsigned char* out, int num, RNGLevel level)
SeedFast(hasher);
break;
case RNGLevel::SLOW:
- SeedSlow(hasher);
+ SeedSlow(hasher, rng);
break;
case RNGLevel::PERIODIC:
SeedPeriodic(hasher, rng);
@@ -551,7 +580,8 @@ static void ProcRand(unsigned char* out, int num, RNGLevel level)
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 RandAddPeriodic() { ProcRand(nullptr, 0, RNGLevel::PERIODIC); }
+void RandAddPeriodic() noexcept { ProcRand(nullptr, 0, RNGLevel::PERIODIC); }
+void RandAddEvent(const uint32_t event_info) noexcept { GetRNGState().AddEvent(event_info); }
bool g_mock_deterministic_tests{false};
diff --git a/src/random.h b/src/random.h
index 2d8ab085e3..e1b105168d 100644
--- a/src/random.h
+++ b/src/random.h
@@ -40,17 +40,17 @@
* These entropy sources are slower, but designed to make sure the RNG state contains
* fresh data that is unpredictable to attackers.
*
- * - RandAddSeedSleep() seeds everything that fast seeding includes, but additionally:
- * - A high-precision timestamp before and after sleeping 1ms.
- * - (On Windows) Once every 10 minutes, performance monitoring data from the OS.
- - - Once every minute, strengthen the entropy for 10 ms using repeated SHA512.
- * These just exploit the fact the system is idle to improve the quality of the RNG
- * slightly.
+ * - RandAddPeriodic() seeds everything that fast seeding includes, but additionally:
+ * - A high-precision timestamp
+ * - Dynamic environment data (performance monitoring, ...)
+ * - Strengthen the entropy for 10 ms using repeated SHA512.
+ * This is run once every minute.
*
* On first use of the RNG (regardless of what function is called first), all entropy
* 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.
+ * - Dynamic environment data (performance monitoring, ...)
+ * - Static environment data
* - Strengthen the entropy for 100 ms using repeated SHA512.
*
* When mixing in new entropy, H = SHA512(entropy || old_rng_state) is computed, and
@@ -87,7 +87,15 @@ void GetStrongRandBytes(unsigned char* buf, int num) noexcept;
*
* Thread-safe.
*/
-void RandAddPeriodic();
+void RandAddPeriodic() noexcept;
+
+/**
+ * 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) noexcept;
/**
* Fast randomness source. This is seeded once with secure random data, but
diff --git a/src/randomenv.cpp b/src/randomenv.cpp
index ec42ddabc3..6992c720ff 100644
--- a/src/randomenv.cpp
+++ b/src/randomenv.cpp
@@ -197,19 +197,30 @@ void AddAllCPUID(CSHA512& hasher)
// 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) {
- for (uint32_t subleaf = 0;; ++subleaf) {
+ 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 over subleaves for leaf 4, 11, 13
- if (leaf != 4 && leaf != 11 && leaf != 13) break;
- if ((leaf == 4 || leaf == 13) && ax == 0) break;
- if (leaf == 11 && (cx & 0xFF00) == 0) break;
+ // 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) {
+ for (uint32_t leaf = 0x80000001; leaf <= ext_max && leaf <= 0x800000FF; ++leaf) {
AddCPUID(hasher, leaf, 0, ax, bx, cx, dx);
}
}
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..3ffeee73de 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)
@@ -1672,6 +1674,7 @@ UniValue analyzepsbt(const JSONRPCRequest& request)
" \"estimated_feerate\" : feerate (numeric, optional) Estimated feerate of the final signed transaction in " + CURRENCY_UNIT + "/kB. Shown only if all UTXO slots in the PSBT have been filled.\n"
" \"fee\" : fee (numeric, optional) The transaction fee paid. Shown only if all UTXO slots in the PSBT have been filled.\n"
" \"next\" : \"role\" (string) Role of the next person that this psbt needs to go to\n"
+ " \"error\" : \"error\" (string) Error message if there is one\n"
"}\n"
},
RPCExamples {
@@ -1724,7 +1727,7 @@ UniValue analyzepsbt(const JSONRPCRequest& request)
}
inputs_result.push_back(input_univ);
}
- result.pushKV("inputs", inputs_result);
+ if (!inputs_result.empty()) result.pushKV("inputs", inputs_result);
if (psbta.estimated_vsize != nullopt) {
result.pushKV("estimated_vsize", (int)*psbta.estimated_vsize);
@@ -1736,6 +1739,9 @@ UniValue analyzepsbt(const JSONRPCRequest& request)
result.pushKV("fee", ValueFromAmount(*psbta.fee));
}
result.pushKV("next", PSBTRoleName(psbta.next));
+ if (!psbta.error.empty()) {
+ result.pushKV("error", psbta.error);
+ }
return result;
}
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/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/descriptor_parse.cpp b/src/test/fuzz/descriptor_parse.cpp
index c4c25854fd..47d5038c26 100644
--- a/src/test/fuzz/descriptor_parse.cpp
+++ b/src/test/fuzz/descriptor_parse.cpp
@@ -3,11 +3,14 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <chainparams.h>
+#include <pubkey.h>
#include <script/descriptor.h>
#include <test/fuzz/fuzz.h>
+#include <util/memory.h>
void initialize()
{
+ static const auto verify_handle = MakeUnique<ECCVerifyHandle>();
SelectParams(CBaseChainParams::REGTEST);
}
diff --git a/src/test/fuzz/deserialize.cpp b/src/test/fuzz/deserialize.cpp
index bcd8691359..bd05283b78 100644
--- a/src/test/fuzz/deserialize.cpp
+++ b/src/test/fuzz/deserialize.cpp
@@ -5,18 +5,25 @@
#include <addrdb.h>
#include <addrman.h>
#include <blockencodings.h>
+#include <blockfilter.h>
#include <chain.h>
#include <coins.h>
#include <compressor.h>
#include <consensus/merkle.h>
+#include <key.h>
+#include <merkleblock.h>
#include <net.h>
#include <primitives/block.h>
#include <protocol.h>
+#include <psbt.h>
#include <pubkey.h>
+#include <script/keyorigin.h>
#include <streams.h>
#include <undo.h>
#include <version.h>
+#include <exception>
+#include <stdexcept>
#include <stdint.h>
#include <unistd.h>
@@ -30,137 +37,186 @@ void initialize()
static const auto verify_handle = MakeUnique<ECCVerifyHandle>();
}
-void test_one_input(const std::vector<uint8_t>& buffer)
+namespace {
+
+struct invalid_fuzzing_input_exception : public std::exception {
+};
+
+template <typename T>
+CDataStream Serialize(const T& obj)
+{
+ CDataStream ds(SER_NETWORK, INIT_PROTO_VERSION);
+ ds << obj;
+ return ds;
+}
+
+template <typename T>
+T Deserialize(CDataStream ds)
+{
+ T obj;
+ ds >> obj;
+ return obj;
+}
+
+template <typename T>
+void DeserializeFromFuzzingInput(const std::vector<uint8_t>& buffer, T& obj)
{
CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION);
try {
- int nVersion;
- ds >> nVersion;
- ds.SetVersion(nVersion);
- } catch (const std::ios_base::failure& e) {
- return;
+ int version;
+ ds >> version;
+ ds.SetVersion(version);
+ } catch (const std::ios_base::failure&) {
+ throw invalid_fuzzing_input_exception();
+ }
+ try {
+ ds >> obj;
+ } catch (const std::ios_base::failure&) {
+ throw invalid_fuzzing_input_exception();
}
+ assert(buffer.empty() || !Serialize(obj).empty());
+}
+
+template <typename T>
+void AssertEqualAfterSerializeDeserialize(const T& obj)
+{
+ assert(Deserialize<T>(Serialize(obj)) == obj);
+}
-#if BLOCK_DESERIALIZE
- try
- {
- CBlock block;
- ds >> block;
- } catch (const std::ios_base::failure& e) {return;}
+} // namespace
+
+void test_one_input(const std::vector<uint8_t>& buffer)
+{
+ try {
+#if BLOCK_FILTER_DESERIALIZE
+ BlockFilter block_filter;
+ DeserializeFromFuzzingInput(buffer, block_filter);
+#elif ADDR_INFO_DESERIALIZE
+ CAddrInfo addr_info;
+ DeserializeFromFuzzingInput(buffer, addr_info);
+#elif BLOCK_FILE_INFO_DESERIALIZE
+ CBlockFileInfo block_file_info;
+ DeserializeFromFuzzingInput(buffer, block_file_info);
+#elif BLOCK_HEADER_AND_SHORT_TXIDS_DESERIALIZE
+ CBlockHeaderAndShortTxIDs block_header_and_short_txids;
+ DeserializeFromFuzzingInput(buffer, block_header_and_short_txids);
+#elif FEE_RATE_DESERIALIZE
+ CFeeRate fee_rate;
+ DeserializeFromFuzzingInput(buffer, fee_rate);
+ AssertEqualAfterSerializeDeserialize(fee_rate);
+#elif MERKLE_BLOCK_DESERIALIZE
+ CMerkleBlock merkle_block;
+ DeserializeFromFuzzingInput(buffer, merkle_block);
+#elif OUT_POINT_DESERIALIZE
+ COutPoint out_point;
+ DeserializeFromFuzzingInput(buffer, out_point);
+ AssertEqualAfterSerializeDeserialize(out_point);
+#elif PARTIAL_MERKLE_TREE_DESERIALIZE
+ CPartialMerkleTree partial_merkle_tree;
+ DeserializeFromFuzzingInput(buffer, partial_merkle_tree);
+#elif PUB_KEY_DESERIALIZE
+ CPubKey pub_key;
+ DeserializeFromFuzzingInput(buffer, pub_key);
+ // TODO: The following equivalence should hold for CPubKey? Fix.
+ // AssertEqualAfterSerializeDeserialize(pub_key);
+#elif SCRIPT_DESERIALIZE
+ CScript script;
+ DeserializeFromFuzzingInput(buffer, script);
+#elif SUB_NET_DESERIALIZE
+ CSubNet sub_net;
+ DeserializeFromFuzzingInput(buffer, sub_net);
+ AssertEqualAfterSerializeDeserialize(sub_net);
+#elif TX_IN_DESERIALIZE
+ CTxIn tx_in;
+ DeserializeFromFuzzingInput(buffer, tx_in);
+ AssertEqualAfterSerializeDeserialize(tx_in);
+#elif FLAT_FILE_POS_DESERIALIZE
+ FlatFilePos flat_file_pos;
+ DeserializeFromFuzzingInput(buffer, flat_file_pos);
+ AssertEqualAfterSerializeDeserialize(flat_file_pos);
+#elif KEY_ORIGIN_INFO_DESERIALIZE
+ KeyOriginInfo key_origin_info;
+ DeserializeFromFuzzingInput(buffer, key_origin_info);
+ AssertEqualAfterSerializeDeserialize(key_origin_info);
+#elif PARTIALLY_SIGNED_TRANSACTION_DESERIALIZE
+ PartiallySignedTransaction partially_signed_transaction;
+ DeserializeFromFuzzingInput(buffer, partially_signed_transaction);
+#elif PREFILLED_TRANSACTION_DESERIALIZE
+ PrefilledTransaction prefilled_transaction;
+ DeserializeFromFuzzingInput(buffer, prefilled_transaction);
+#elif PSBT_INPUT_DESERIALIZE
+ PSBTInput psbt_input;
+ DeserializeFromFuzzingInput(buffer, psbt_input);
+#elif PSBT_OUTPUT_DESERIALIZE
+ PSBTOutput psbt_output;
+ DeserializeFromFuzzingInput(buffer, psbt_output);
+#elif BLOCK_DESERIALIZE
+ CBlock block;
+ DeserializeFromFuzzingInput(buffer, block);
#elif BLOCKLOCATOR_DESERIALIZE
- try
- {
- CBlockLocator bl;
- ds >> bl;
- } catch (const std::ios_base::failure& e) {return;}
+ CBlockLocator bl;
+ DeserializeFromFuzzingInput(buffer, bl);
#elif BLOCKMERKLEROOT
- try
- {
- CBlock block;
- ds >> block;
- bool mutated;
- BlockMerkleRoot(block, &mutated);
- } catch (const std::ios_base::failure& e) {return;}
+ CBlock block;
+ DeserializeFromFuzzingInput(buffer, block);
+ bool mutated;
+ BlockMerkleRoot(block, &mutated);
#elif ADDRMAN_DESERIALIZE
- try
- {
- CAddrMan am;
- ds >> am;
- } catch (const std::ios_base::failure& e) {return;}
+ CAddrMan am;
+ DeserializeFromFuzzingInput(buffer, am);
#elif BLOCKHEADER_DESERIALIZE
- try
- {
- CBlockHeader bh;
- ds >> bh;
- } catch (const std::ios_base::failure& e) {return;}
+ CBlockHeader bh;
+ DeserializeFromFuzzingInput(buffer, bh);
#elif BANENTRY_DESERIALIZE
- try
- {
- CBanEntry be;
- ds >> be;
- } catch (const std::ios_base::failure& e) {return;}
+ CBanEntry be;
+ DeserializeFromFuzzingInput(buffer, be);
#elif TXUNDO_DESERIALIZE
- try
- {
- CTxUndo tu;
- ds >> tu;
- } catch (const std::ios_base::failure& e) {return;}
+ CTxUndo tu;
+ DeserializeFromFuzzingInput(buffer, tu);
#elif BLOCKUNDO_DESERIALIZE
- try
- {
- CBlockUndo bu;
- ds >> bu;
- } catch (const std::ios_base::failure& e) {return;}
+ CBlockUndo bu;
+ DeserializeFromFuzzingInput(buffer, bu);
#elif COINS_DESERIALIZE
- try
- {
- Coin coin;
- ds >> coin;
- } catch (const std::ios_base::failure& e) {return;}
+ Coin coin;
+ DeserializeFromFuzzingInput(buffer, coin);
#elif NETADDR_DESERIALIZE
- try
- {
- CNetAddr na;
- ds >> na;
- } catch (const std::ios_base::failure& e) {return;}
+ CNetAddr na;
+ DeserializeFromFuzzingInput(buffer, na);
+ AssertEqualAfterSerializeDeserialize(na);
#elif SERVICE_DESERIALIZE
- try
- {
- CService s;
- ds >> s;
- } catch (const std::ios_base::failure& e) {return;}
+ CService s;
+ DeserializeFromFuzzingInput(buffer, s);
+ AssertEqualAfterSerializeDeserialize(s);
#elif MESSAGEHEADER_DESERIALIZE
- CMessageHeader::MessageStartChars pchMessageStart = {0x00, 0x00, 0x00, 0x00};
- try
- {
- CMessageHeader mh(pchMessageStart);
- ds >> mh;
- if (!mh.IsValid(pchMessageStart)) {return;}
- } catch (const std::ios_base::failure& e) {return;}
+ const CMessageHeader::MessageStartChars pchMessageStart = {0x00, 0x00, 0x00, 0x00};
+ CMessageHeader mh(pchMessageStart);
+ DeserializeFromFuzzingInput(buffer, mh);
+ (void)mh.IsValid(pchMessageStart);
#elif ADDRESS_DESERIALIZE
- try
- {
- CAddress a;
- ds >> a;
- } catch (const std::ios_base::failure& e) {return;}
+ CAddress a;
+ DeserializeFromFuzzingInput(buffer, a);
#elif INV_DESERIALIZE
- try
- {
- CInv i;
- ds >> i;
- } catch (const std::ios_base::failure& e) {return;}
+ CInv i;
+ DeserializeFromFuzzingInput(buffer, i);
#elif BLOOMFILTER_DESERIALIZE
- try
- {
- CBloomFilter bf;
- ds >> bf;
- } catch (const std::ios_base::failure& e) {return;}
+ CBloomFilter bf;
+ DeserializeFromFuzzingInput(buffer, bf);
#elif DISKBLOCKINDEX_DESERIALIZE
- try
- {
- CDiskBlockIndex dbi;
- ds >> dbi;
- } catch (const std::ios_base::failure& e) {return;}
+ CDiskBlockIndex dbi;
+ DeserializeFromFuzzingInput(buffer, dbi);
#elif TXOUTCOMPRESSOR_DESERIALIZE
- CTxOut to;
- CTxOutCompressor toc(to);
- try
- {
- ds >> toc;
- } catch (const std::ios_base::failure& e) {return;}
+ CTxOut to;
+ CTxOutCompressor toc(to);
+ DeserializeFromFuzzingInput(buffer, toc);
#elif BLOCKTRANSACTIONS_DESERIALIZE
- try
- {
- BlockTransactions bt;
- ds >> bt;
- } catch (const std::ios_base::failure& e) {return;}
+ BlockTransactions bt;
+ DeserializeFromFuzzingInput(buffer, bt);
#elif BLOCKTRANSACTIONSREQUEST_DESERIALIZE
- try
- {
- BlockTransactionsRequest btr;
- ds >> btr;
- } catch (const std::ios_base::failure& e) {return;}
+ BlockTransactionsRequest btr;
+ DeserializeFromFuzzingInput(buffer, btr);
#else
#error Need at least one fuzz target to compile
#endif
+ } catch (const invalid_fuzzing_input_exception&) {
+ }
}
diff --git a/src/test/fuzz/integer.cpp b/src/test/fuzz/integer.cpp
new file mode 100644
index 0000000000..723938bcdb
--- /dev/null
+++ b/src/test/fuzz/integer.cpp
@@ -0,0 +1,127 @@
+// 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 <arith_uint256.h>
+#include <compressor.h>
+#include <consensus/merkle.h>
+#include <core_io.h>
+#include <crypto/common.h>
+#include <crypto/siphash.h>
+#include <key_io.h>
+#include <memusage.h>
+#include <netbase.h>
+#include <policy/settings.h>
+#include <pow.h>
+#include <pubkey.h>
+#include <rpc/util.h>
+#include <script/signingprovider.h>
+#include <script/standard.h>
+#include <serialize.h>
+#include <test/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+#include <uint256.h>
+#include <util/strencodings.h>
+#include <util/system.h>
+#include <util/time.h>
+
+#include <cassert>
+#include <limits>
+#include <vector>
+
+void initialize()
+{
+ SelectParams(CBaseChainParams::REGTEST);
+}
+
+void test_one_input(const std::vector<uint8_t>& buffer)
+{
+ if (buffer.size() < sizeof(uint256) + sizeof(uint160)) {
+ return;
+ }
+ FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
+ const uint256 u256(fuzzed_data_provider.ConsumeBytes<unsigned char>(sizeof(uint256)));
+ const uint160 u160(fuzzed_data_provider.ConsumeBytes<unsigned char>(sizeof(uint160)));
+ const uint64_t u64 = fuzzed_data_provider.ConsumeIntegral<uint64_t>();
+ const int64_t i64 = fuzzed_data_provider.ConsumeIntegral<int64_t>();
+ const uint32_t u32 = fuzzed_data_provider.ConsumeIntegral<uint32_t>();
+ const int32_t i32 = fuzzed_data_provider.ConsumeIntegral<int32_t>();
+ const uint16_t u16 = fuzzed_data_provider.ConsumeIntegral<uint16_t>();
+ const int16_t i16 = fuzzed_data_provider.ConsumeIntegral<int16_t>();
+ const uint8_t u8 = fuzzed_data_provider.ConsumeIntegral<uint8_t>();
+ const int8_t i8 = fuzzed_data_provider.ConsumeIntegral<int8_t>();
+ // We cannot assume a specific value of std::is_signed<char>::value:
+ // ConsumeIntegral<char>() instead of casting from {u,}int8_t.
+ const char ch = fuzzed_data_provider.ConsumeIntegral<char>();
+
+ const Consensus::Params& consensus_params = Params().GetConsensus();
+ (void)CheckProofOfWork(u256, u32, consensus_params);
+ (void)CompressAmount(u64);
+ static const uint256 u256_min(uint256S("0000000000000000000000000000000000000000000000000000000000000000"));
+ static const uint256 u256_max(uint256S("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"));
+ const std::vector<uint256> v256{u256, u256_min, u256_max};
+ (void)ComputeMerkleRoot(v256);
+ (void)CountBits(u64);
+ (void)DecompressAmount(u64);
+ (void)FormatISO8601Date(i64);
+ (void)FormatISO8601DateTime(i64);
+ (void)GetSizeOfCompactSize(u64);
+ (void)GetSpecialScriptSize(u32);
+ // (void)GetVirtualTransactionSize(i64, i64); // function defined only for a subset of int64_t inputs
+ // (void)GetVirtualTransactionSize(i64, i64, u32); // function defined only for a subset of int64_t/uint32_t inputs
+ (void)HexDigit(ch);
+ (void)i64tostr(i64);
+ (void)IsDigit(ch);
+ (void)IsSpace(ch);
+ (void)IsSwitchChar(ch);
+ (void)itostr(i32);
+ (void)memusage::DynamicUsage(ch);
+ (void)memusage::DynamicUsage(i16);
+ (void)memusage::DynamicUsage(i32);
+ (void)memusage::DynamicUsage(i64);
+ (void)memusage::DynamicUsage(i8);
+ (void)memusage::DynamicUsage(u16);
+ (void)memusage::DynamicUsage(u32);
+ (void)memusage::DynamicUsage(u64);
+ (void)memusage::DynamicUsage(u8);
+ const unsigned char uch = static_cast<unsigned char>(u8);
+ (void)memusage::DynamicUsage(uch);
+ (void)MillisToTimeval(i64);
+ const double d = ser_uint64_to_double(u64);
+ assert(ser_double_to_uint64(d) == u64);
+ const float f = ser_uint32_to_float(u32);
+ assert(ser_float_to_uint32(f) == u32);
+ (void)SighashToStr(uch);
+ (void)SipHashUint256(u64, u64, u256);
+ (void)SipHashUint256Extra(u64, u64, u256, u32);
+ (void)ToLower(ch);
+
+ const arith_uint256 au256 = UintToArith256(u256);
+ assert(ArithToUint256(au256) == u256);
+ assert(uint256S(au256.GetHex()) == u256);
+ (void)au256.bits();
+ (void)au256.GetCompact(/* fNegative= */ false);
+ (void)au256.GetCompact(/* fNegative= */ true);
+ (void)au256.getdouble();
+ (void)au256.GetHex();
+ (void)au256.GetLow64();
+ (void)au256.size();
+ (void)au256.ToString();
+
+ const CKeyID key_id{u160};
+ const CScriptID script_id{u160};
+ // CTxDestination = CNoDestination ∪ PKHash ∪ ScriptHash ∪ WitnessV0ScriptHash ∪ WitnessV0KeyHash ∪ WitnessUnknown
+ const PKHash pk_hash{u160};
+ const ScriptHash script_hash{u160};
+ const WitnessV0KeyHash witness_v0_key_hash{u160};
+ const WitnessV0ScriptHash witness_v0_script_hash{u256};
+ const std::vector<CTxDestination> destinations{pk_hash, script_hash, witness_v0_key_hash, witness_v0_script_hash};
+ const SigningProvider store;
+ for (const CTxDestination& destination : destinations) {
+ (void)DescribeAddress(destination);
+ (void)EncodeDestination(destination);
+ (void)GetKeyForDestination(store, destination);
+ (void)GetScriptForDestination(destination);
+ (void)IsValidDestination(destination);
+ }
+}
diff --git a/src/test/fuzz/parse_hd_keypath.cpp b/src/test/fuzz/parse_hd_keypath.cpp
new file mode 100644
index 0000000000..9a23f4b2d4
--- /dev/null
+++ b/src/test/fuzz/parse_hd_keypath.cpp
@@ -0,0 +1,13 @@
+// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <test/fuzz/fuzz.h>
+#include <util/bip32.h>
+
+void test_one_input(const std::vector<uint8_t>& buffer)
+{
+ const std::string keypath_str(buffer.begin(), buffer.end());
+ std::vector<uint32_t> keypath;
+ (void)ParseHDKeypath(keypath_str, keypath);
+}
diff --git a/src/test/fuzz/parse_numbers.cpp b/src/test/fuzz/parse_numbers.cpp
new file mode 100644
index 0000000000..59f89dc9fb
--- /dev/null
+++ b/src/test/fuzz/parse_numbers.cpp
@@ -0,0 +1,35 @@
+// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <test/fuzz/fuzz.h>
+#include <util/moneystr.h>
+#include <util/strencodings.h>
+
+#include <string>
+
+void test_one_input(const std::vector<uint8_t>& buffer)
+{
+ const std::string random_string(buffer.begin(), buffer.end());
+
+ CAmount amount;
+ (void)ParseMoney(random_string, amount);
+
+ double d;
+ (void)ParseDouble(random_string, &d);
+
+ int32_t i32;
+ (void)ParseInt32(random_string, &i32);
+ (void)atoi(random_string);
+
+ uint32_t u32;
+ (void)ParseUInt32(random_string, &u32);
+
+ int64_t i64;
+ (void)atoi64(random_string);
+ (void)ParseFixedPoint(random_string, 3, &i64);
+ (void)ParseInt64(random_string, &i64);
+
+ uint64_t u64;
+ (void)ParseUInt64(random_string, &u64);
+}
diff --git a/src/test/fuzz/parse_script.cpp b/src/test/fuzz/parse_script.cpp
new file mode 100644
index 0000000000..21ac1aecf3
--- /dev/null
+++ b/src/test/fuzz/parse_script.cpp
@@ -0,0 +1,16 @@
+// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <core_io.h>
+#include <script/script.h>
+#include <test/fuzz/fuzz.h>
+
+void test_one_input(const std::vector<uint8_t>& buffer)
+{
+ const std::string script_string(buffer.begin(), buffer.end());
+ try {
+ (void)ParseScript(script_string);
+ } catch (const std::runtime_error&) {
+ }
+}
diff --git a/src/test/fuzz/parse_univalue.cpp b/src/test/fuzz/parse_univalue.cpp
new file mode 100644
index 0000000000..3ad112dbad
--- /dev/null
+++ b/src/test/fuzz/parse_univalue.cpp
@@ -0,0 +1,91 @@
+// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <chainparams.h>
+#include <core_io.h>
+#include <rpc/client.h>
+#include <rpc/util.h>
+#include <test/fuzz/fuzz.h>
+#include <util/memory.h>
+
+#include <limits>
+#include <string>
+
+void initialize()
+{
+ static const auto verify_handle = MakeUnique<ECCVerifyHandle>();
+ SelectParams(CBaseChainParams::REGTEST);
+}
+
+void test_one_input(const std::vector<uint8_t>& buffer)
+{
+ const std::string random_string(buffer.begin(), buffer.end());
+ bool valid = true;
+ const UniValue univalue = [&] {
+ try {
+ return ParseNonRFCJSONValue(random_string);
+ } catch (const std::runtime_error&) {
+ valid = false;
+ return NullUniValue;
+ }
+ }();
+ if (!valid) {
+ return;
+ }
+ try {
+ (void)ParseHashO(univalue, "A");
+ (void)ParseHashO(univalue, random_string);
+ } catch (const UniValue&) {
+ } catch (const std::runtime_error&) {
+ }
+ try {
+ (void)ParseHashV(univalue, "A");
+ (void)ParseHashV(univalue, random_string);
+ } catch (const UniValue&) {
+ } catch (const std::runtime_error&) {
+ }
+ try {
+ (void)ParseHexO(univalue, "A");
+ (void)ParseHexO(univalue, random_string);
+ } catch (const UniValue&) {
+ } catch (const std::runtime_error&) {
+ }
+ try {
+ (void)ParseHexUV(univalue, "A");
+ (void)ParseHexUV(univalue, random_string);
+ } catch (const UniValue&) {
+ } catch (const std::runtime_error&) {
+ }
+ try {
+ (void)ParseHexV(univalue, "A");
+ (void)ParseHexV(univalue, random_string);
+ } catch (const UniValue&) {
+ } catch (const std::runtime_error&) {
+ }
+ try {
+ (void)ParseSighashString(univalue);
+ } catch (const std::runtime_error&) {
+ }
+ try {
+ (void)AmountFromValue(univalue);
+ } catch (const UniValue&) {
+ } catch (const std::runtime_error&) {
+ }
+ try {
+ FlatSigningProvider provider;
+ (void)EvalDescriptorStringOrObject(univalue, provider);
+ } catch (const UniValue&) {
+ } catch (const std::runtime_error&) {
+ }
+ try {
+ (void)ParseConfirmTarget(univalue, std::numeric_limits<unsigned int>::max());
+ } catch (const UniValue&) {
+ } catch (const std::runtime_error&) {
+ }
+ try {
+ (void)ParseDescriptorRange(univalue);
+ } catch (const UniValue&) {
+ } catch (const std::runtime_error&) {
+ }
+}
diff --git a/src/test/fuzz/transaction.cpp b/src/test/fuzz/transaction.cpp
index 76b230ef3c..fefafda36b 100644
--- a/src/test/fuzz/transaction.cpp
+++ b/src/test/fuzz/transaction.cpp
@@ -26,19 +26,31 @@ void test_one_input(const std::vector<uint8_t>& buffer)
int nVersion;
ds >> nVersion;
ds.SetVersion(nVersion);
- } catch (const std::ios_base::failure& e) {
+ } catch (const std::ios_base::failure&) {
return;
}
- bool valid = true;
+ bool valid_tx = true;
const CTransaction tx = [&] {
try {
return CTransaction(deserialize, ds);
- } catch (const std::ios_base::failure& e) {
- valid = false;
+ } catch (const std::ios_base::failure&) {
+ valid_tx = false;
return CTransaction();
}
}();
- if (!valid) {
+ bool valid_mutable_tx = true;
+ CDataStream ds_mtx(buffer, SER_NETWORK, INIT_PROTO_VERSION);
+ CMutableTransaction mutable_tx;
+ try {
+ int nVersion;
+ ds_mtx >> nVersion;
+ ds_mtx.SetVersion(nVersion);
+ ds_mtx >> mutable_tx;
+ } catch (const std::ios_base::failure&) {
+ valid_mutable_tx = false;
+ }
+ assert(valid_tx == valid_mutable_tx);
+ if (!valid_tx) {
return;
}
diff --git a/src/test/fuzz/tx_in.cpp b/src/test/fuzz/tx_in.cpp
new file mode 100644
index 0000000000..8e116537d1
--- /dev/null
+++ b/src/test/fuzz/tx_in.cpp
@@ -0,0 +1,33 @@
+// 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 <consensus/validation.h>
+#include <core_memusage.h>
+#include <policy/policy.h>
+#include <primitives/transaction.h>
+#include <streams.h>
+#include <test/fuzz/fuzz.h>
+#include <version.h>
+
+#include <cassert>
+
+void test_one_input(const std::vector<uint8_t>& buffer)
+{
+ CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION);
+ CTxIn tx_in;
+ try {
+ int version;
+ ds >> version;
+ ds.SetVersion(version);
+ ds >> tx_in;
+ } catch (const std::ios_base::failure&) {
+ return;
+ }
+
+ (void)GetTransactionInputWeight(tx_in);
+ (void)GetVirtualTransactionInputSize(tx_in);
+ (void)RecursiveDynamicUsage(tx_in);
+
+ (void)tx_in.ToString();
+}
diff --git a/src/test/fuzz/tx_out.cpp b/src/test/fuzz/tx_out.cpp
new file mode 100644
index 0000000000..aa1338d5ba
--- /dev/null
+++ b/src/test/fuzz/tx_out.cpp
@@ -0,0 +1,35 @@
+// 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 <consensus/validation.h>
+#include <core_memusage.h>
+#include <policy/policy.h>
+#include <primitives/transaction.h>
+#include <streams.h>
+#include <test/fuzz/fuzz.h>
+#include <version.h>
+
+void test_one_input(const std::vector<uint8_t>& buffer)
+{
+ CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION);
+ CTxOut tx_out;
+ try {
+ int version;
+ ds >> version;
+ ds.SetVersion(version);
+ ds >> tx_out;
+ } catch (const std::ios_base::failure&) {
+ return;
+ }
+
+ const CFeeRate dust_relay_fee{DUST_RELAY_TX_FEE};
+ (void)GetDustThreshold(tx_out, dust_relay_fee);
+ (void)IsDust(tx_out, dust_relay_fee);
+ (void)RecursiveDynamicUsage(tx_out);
+
+ (void)tx_out.ToString();
+ (void)tx_out.IsNull();
+ tx_out.SetNull();
+ assert(tx_out.IsNull());
+}
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..0939803953 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);
@@ -797,6 +820,17 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
reason.clear();
BOOST_CHECK(!IsStandardTx(CTransaction(t), reason));
BOOST_CHECK_EQUAL(reason, "scriptsig-size");
+
+ // Check bare multisig (standard if policy flag fIsBareMultisigStd is set)
+ fIsBareMultisigStd = true;
+ t.vout[0].scriptPubKey = GetScriptForMultisig(1, {key.GetPubKey()}); // simple 1-of-1
+ t.vin[0].scriptSig = CScript() << std::vector<unsigned char>(65, 0);
+ BOOST_CHECK(IsStandardTx(CTransaction(t), reason));
+
+ fIsBareMultisigStd = false;
+ reason.clear();
+ BOOST_CHECK(!IsStandardTx(CTransaction(t), reason));
+ BOOST_CHECK_EQUAL(reason, "bare-multisig");
}
BOOST_AUTO_TEST_SUITE_END()
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/tinyformat.h b/src/tinyformat.h
index 182f518a0b..be63f2d5d8 100644
--- a/src/tinyformat.h
+++ b/src/tinyformat.h
@@ -33,6 +33,7 @@
//
// * Type safety and extensibility for user defined types.
// * C99 printf() compatibility, to the extent possible using std::ostream
+// * POSIX extension for positional arguments
// * Simplicity and minimalism. A single header file to include and distribute
// with your projects.
// * Augment rather than replace the standard stream formatting mechanism
@@ -42,7 +43,7 @@
// Main interface example usage
// ----------------------------
//
-// To print a date to std::cout:
+// To print a date to std::cout for American usage:
//
// std::string weekday = "Wednesday";
// const char* month = "July";
@@ -52,6 +53,14 @@
//
// tfm::printf("%s, %s %d, %.2d:%.2d\n", weekday, month, day, hour, min);
//
+// POSIX extension for positional arguments is available.
+// The ability to rearrange formatting arguments is an important feature
+// for localization because the word order may vary in different languages.
+//
+// Previous example for German usage. Arguments are reordered:
+//
+// tfm::printf("%1$s, %3$d. %2$s, %4$d:%5$.2d\n", weekday, month, day, hour, min);
+//
// The strange types here emphasize the type safety of the interface; it is
// possible to print a std::string using the "%s" conversion, and a
// size_t using the "%d" conversion. A similar result could be achieved
@@ -133,12 +142,17 @@ namespace tfm = tinyformat;
//------------------------------------------------------------------------------
// Implementation details.
#include <algorithm>
-#include <cassert>
#include <iostream>
#include <sstream>
-#include <stdexcept>
+#include <stdexcept> // Added for Bitcoin Core
+
+#ifndef TINYFORMAT_ASSERT
+# include <cassert>
+# define TINYFORMAT_ASSERT(cond) assert(cond)
+#endif
#ifndef TINYFORMAT_ERROR
+# include <cassert>
# define TINYFORMAT_ERROR(reason) assert(0 && reason)
#endif
@@ -149,13 +163,13 @@ namespace tfm = tinyformat;
#endif
#if defined(__GLIBCXX__) && __GLIBCXX__ < 20080201
-// std::showpos is broken on old libstdc++ as provided with OSX. See
+// std::showpos is broken on old libstdc++ as provided with macOS. See
// http://gcc.gnu.org/ml/libstdc++/2007-11/msg00075.html
# define TINYFORMAT_OLD_LIBSTDCPLUSPLUS_WORKAROUND
#endif
#ifdef __APPLE__
-// Workaround OSX linker warning: Xcode uses different default symbol
+// Workaround macOS linker warning: Xcode uses different default symbol
// visibilities for static libs vs executables (see issue #25)
# define TINYFORMAT_HIDDEN __attribute__((visibility("hidden")))
#else
@@ -164,6 +178,7 @@ namespace tfm = tinyformat;
namespace tinyformat {
+// Added for Bitcoin Core
class format_error: public std::runtime_error
{
public:
@@ -218,7 +233,7 @@ template<int n> struct is_wchar<wchar_t[n]> {};
template<typename T, typename fmtT, bool convertible = is_convertible<T, fmtT>::value>
struct formatValueAsType
{
- static void invoke(std::ostream& /*out*/, const T& /*value*/) { assert(0); }
+ static void invoke(std::ostream& /*out*/, const T& /*value*/) { TINYFORMAT_ASSERT(0); }
};
// Specialized version for types that can actually be converted to fmtT, as
// indicated by the "convertible" template parameter.
@@ -240,8 +255,7 @@ struct formatZeroIntegerWorkaround<T,true>
{
static bool invoke(std::ostream& out, const T& value)
{
- if (static_cast<int>(value) == 0 && out.flags() & std::ios::showpos)
- {
+ if (static_cast<int>(value) == 0 && out.flags() & std::ios::showpos) {
out << "+0";
return true;
}
@@ -282,7 +296,7 @@ inline void formatTruncated(std::ostream& out, const T& value, int ntrunc)
inline void formatTruncated(std::ostream& out, type* value, int ntrunc) \
{ \
std::streamsize len = 0; \
- while(len < ntrunc && value[len] != 0) \
+ while (len < ntrunc && value[len] != 0) \
++len; \
out.write(value, len); \
}
@@ -328,15 +342,14 @@ inline void formatValue(std::ostream& out, const char* /*fmtBegin*/,
// could otherwise lead to a crash when printing a dangling (const char*).
const bool canConvertToChar = detail::is_convertible<T,char>::value;
const bool canConvertToVoidPtr = detail::is_convertible<T, const void*>::value;
- if(canConvertToChar && *(fmtEnd-1) == 'c')
+ if (canConvertToChar && *(fmtEnd-1) == 'c')
detail::formatValueAsType<T, char>::invoke(out, value);
- else if(canConvertToVoidPtr && *(fmtEnd-1) == 'p')
+ else if (canConvertToVoidPtr && *(fmtEnd-1) == 'p')
detail::formatValueAsType<T, const void*>::invoke(out, value);
#ifdef TINYFORMAT_OLD_LIBSTDCPLUSPLUS_WORKAROUND
- else if(detail::formatZeroIntegerWorkaround<T>::invoke(out, value)) /**/;
+ else if (detail::formatZeroIntegerWorkaround<T>::invoke(out, value)) /**/;
#endif
- else if(ntrunc >= 0)
- {
+ else if (ntrunc >= 0) {
// Take care not to overread C strings in truncating conversions like
// "%.4s" where at most 4 characters may be read.
detail::formatTruncated(out, value, ntrunc);
@@ -351,8 +364,7 @@ inline void formatValue(std::ostream& out, const char* /*fmtBegin*/,
inline void formatValue(std::ostream& out, const char* /*fmtBegin*/, \
const char* fmtEnd, int /**/, charType value) \
{ \
- switch(*(fmtEnd-1)) \
- { \
+ switch (*(fmtEnd-1)) { \
case 'u': case 'd': case 'i': case 'o': case 'X': case 'x': \
out << static_cast<int>(value); break; \
default: \
@@ -490,19 +502,19 @@ namespace detail {
// Type-opaque holder for an argument to format(), with associated actions on
// the type held as explicit function pointers. This allows FormatArg's for
-// each argument to be allocated as a homogenous array inside FormatList
+// each argument to be allocated as a homogeneous array inside FormatList
// whereas a naive implementation based on inheritance does not.
class FormatArg
{
public:
FormatArg()
- : m_value(nullptr),
- m_formatImpl(nullptr),
- m_toIntImpl(nullptr)
- { }
+ : m_value(NULL),
+ m_formatImpl(NULL),
+ m_toIntImpl(NULL)
+ { }
template<typename T>
- explicit FormatArg(const T& value)
+ FormatArg(const T& value)
: m_value(static_cast<const void*>(&value)),
m_formatImpl(&formatImpl<T>),
m_toIntImpl(&toIntImpl<T>)
@@ -511,15 +523,15 @@ class FormatArg
void format(std::ostream& out, const char* fmtBegin,
const char* fmtEnd, int ntrunc) const
{
- assert(m_value);
- assert(m_formatImpl);
+ TINYFORMAT_ASSERT(m_value);
+ TINYFORMAT_ASSERT(m_formatImpl);
m_formatImpl(out, fmtBegin, fmtEnd, ntrunc, m_value);
}
int toInt() const
{
- assert(m_value);
- assert(m_toIntImpl);
+ TINYFORMAT_ASSERT(m_value);
+ TINYFORMAT_ASSERT(m_toIntImpl);
return m_toIntImpl(m_value);
}
@@ -549,36 +561,68 @@ class FormatArg
inline int parseIntAndAdvance(const char*& c)
{
int i = 0;
- for(;*c >= '0' && *c <= '9'; ++c)
+ for (;*c >= '0' && *c <= '9'; ++c)
i = 10*i + (*c - '0');
return i;
}
-// Print literal part of format string and return next format spec
-// position.
+// Parse width or precision `n` from format string pointer `c`, and advance it
+// to the next character. If an indirection is requested with `*`, the argument
+// is read from `args[argIndex]` and `argIndex` is incremented (or read
+// from `args[n]` in positional mode). Returns true if one or more
+// characters were read.
+inline bool parseWidthOrPrecision(int& n, const char*& c, bool positionalMode,
+ const detail::FormatArg* args,
+ int& argIndex, int numArgs)
+{
+ if (*c >= '0' && *c <= '9') {
+ n = parseIntAndAdvance(c);
+ }
+ else if (*c == '*') {
+ ++c;
+ n = 0;
+ if (positionalMode) {
+ int pos = parseIntAndAdvance(c) - 1;
+ if (*c != '$')
+ TINYFORMAT_ERROR("tinyformat: Non-positional argument used after a positional one");
+ if (pos >= 0 && pos < numArgs)
+ n = args[pos].toInt();
+ else
+ TINYFORMAT_ERROR("tinyformat: Positional argument out of range");
+ ++c;
+ }
+ else {
+ if (argIndex < numArgs)
+ n = args[argIndex++].toInt();
+ else
+ TINYFORMAT_ERROR("tinyformat: Not enough arguments to read variable width or precision");
+ }
+ }
+ else {
+ return false;
+ }
+ return true;
+}
+
+// Print literal part of format string and return next format spec position.
//
-// Skips over any occurrences of '%%', printing a literal '%' to the
-// output. The position of the first % character of the next
-// nontrivial format spec is returned, or the end of string.
+// Skips over any occurrences of '%%', printing a literal '%' to the output.
+// The position of the first % character of the next nontrivial format spec is
+// returned, or the end of string.
inline const char* printFormatStringLiteral(std::ostream& out, const char* fmt)
{
const char* c = fmt;
- for(;; ++c)
- {
- switch(*c)
- {
- case '\0':
- out.write(fmt, c - fmt);
+ for (;; ++c) {
+ if (*c == '\0') {
+ out.write(fmt, c - fmt);
+ return c;
+ }
+ else if (*c == '%') {
+ out.write(fmt, c - fmt);
+ if (*(c+1) != '%')
return c;
- case '%':
- out.write(fmt, c - fmt);
- if(*(c+1) != '%')
- return c;
- // for "%%", tack trailing % onto next literal section.
- fmt = ++c;
- break;
- default:
- break;
+ // for "%%", tack trailing % onto next literal section.
+ fmt = ++c;
}
}
}
@@ -587,23 +631,43 @@ inline const char* printFormatStringLiteral(std::ostream& out, const char* fmt)
// Parse a format string and set the stream state accordingly.
//
// The format mini-language recognized here is meant to be the one from C99,
-// with the form "%[flags][width][.precision][length]type".
+// with the form "%[flags][width][.precision][length]type" with POSIX
+// positional arguments extension.
+//
+// POSIX positional arguments extension:
+// Conversions can be applied to the nth argument after the format in
+// the argument list, rather than to the next unused argument. In this case,
+// the conversion specifier character % (see below) is replaced by the sequence
+// "%n$", where n is a decimal integer in the range [1,{NL_ARGMAX}],
+// giving the position of the argument in the argument list. This feature
+// provides for the definition of format strings that select arguments
+// in an order appropriate to specific languages.
+//
+// The format can contain either numbered argument conversion specifications
+// (that is, "%n$" and "*m$"), or unnumbered argument conversion specifications
+// (that is, % and * ), but not both. The only exception to this is that %%
+// can be mixed with the "%n$" form. The results of mixing numbered and
+// unnumbered argument specifications in a format string are undefined.
+// When numbered argument specifications are used, specifying the Nth argument
+// requires that all the leading arguments, from the first to the (N-1)th,
+// are specified in the format string.
+//
+// In format strings containing the "%n$" form of conversion specification,
+// numbered arguments in the argument list can be referenced from the format
+// string as many times as required.
//
// Formatting options which can't be natively represented using the ostream
// state are returned in spacePadPositive (for space padded positive numbers)
// and ntrunc (for truncating conversions). argIndex is incremented if
// necessary to pull out variable width and precision. The function returns a
// pointer to the character after the end of the current format spec.
-inline const char* streamStateFromFormat(std::ostream& out, bool& spacePadPositive,
+inline const char* streamStateFromFormat(std::ostream& out, bool& positionalMode,
+ bool& spacePadPositive,
int& ntrunc, const char* fmtStart,
- const detail::FormatArg* formatters,
- int& argIndex, int numFormatters)
+ const detail::FormatArg* args,
+ int& argIndex, int numArgs)
{
- if(*fmtStart != '%')
- {
- TINYFORMAT_ERROR("tinyformat: Not enough conversion specifiers in format string");
- return fmtStart;
- }
+ TINYFORMAT_ASSERT(*fmtStart == '%');
// Reset stream state to defaults.
out.width(0);
out.precision(6);
@@ -616,100 +680,113 @@ inline const char* streamStateFromFormat(std::ostream& out, bool& spacePadPositi
bool widthSet = false;
int widthExtra = 0;
const char* c = fmtStart + 1;
- // 1) Parse flags
- for(;; ++c)
- {
- switch(*c)
- {
- case '#':
- out.setf(std::ios::showpoint | std::ios::showbase);
- continue;
- case '0':
- // overridden by left alignment ('-' flag)
- if(!(out.flags() & std::ios::left))
- {
- // Use internal padding so that numeric values are
- // formatted correctly, eg -00010 rather than 000-10
- out.fill('0');
- out.setf(std::ios::internal, std::ios::adjustfield);
- }
- continue;
- case '-':
- out.fill(' ');
- out.setf(std::ios::left, std::ios::adjustfield);
- continue;
- case ' ':
- // overridden by show positive sign, '+' flag.
- if(!(out.flags() & std::ios::showpos))
- spacePadPositive = true;
- continue;
- case '+':
- out.setf(std::ios::showpos);
- spacePadPositive = false;
- widthExtra = 1;
- continue;
- default:
- break;
+
+ // 1) Parse an argument index (if followed by '$') or a width possibly
+ // preceded with '0' flag.
+ if (*c >= '0' && *c <= '9') {
+ const char tmpc = *c;
+ int value = parseIntAndAdvance(c);
+ if (*c == '$') {
+ // value is an argument index
+ if (value > 0 && value <= numArgs)
+ argIndex = value - 1;
+ else
+ TINYFORMAT_ERROR("tinyformat: Positional argument out of range");
+ ++c;
+ positionalMode = true;
+ }
+ else if (positionalMode) {
+ TINYFORMAT_ERROR("tinyformat: Non-positional argument used after a positional one");
+ }
+ else {
+ if (tmpc == '0') {
+ // Use internal padding so that numeric values are
+ // formatted correctly, eg -00010 rather than 000-10
+ out.fill('0');
+ out.setf(std::ios::internal, std::ios::adjustfield);
+ }
+ if (value != 0) {
+ // Nonzero value means that we parsed width.
+ widthSet = true;
+ out.width(value);
+ }
}
- break;
}
- // 2) Parse width
- if(*c >= '0' && *c <= '9')
- {
- widthSet = true;
- out.width(parseIntAndAdvance(c));
+ else if (positionalMode) {
+ TINYFORMAT_ERROR("tinyformat: Non-positional argument used after a positional one");
}
- if(*c == '*')
- {
- widthSet = true;
+ // 2) Parse flags and width if we did not do it in previous step.
+ if (!widthSet) {
+ // Parse flags
+ for (;; ++c) {
+ switch (*c) {
+ case '#':
+ out.setf(std::ios::showpoint | std::ios::showbase);
+ continue;
+ case '0':
+ // overridden by left alignment ('-' flag)
+ if (!(out.flags() & std::ios::left)) {
+ // Use internal padding so that numeric values are
+ // formatted correctly, eg -00010 rather than 000-10
+ out.fill('0');
+ out.setf(std::ios::internal, std::ios::adjustfield);
+ }
+ continue;
+ case '-':
+ out.fill(' ');
+ out.setf(std::ios::left, std::ios::adjustfield);
+ continue;
+ case ' ':
+ // overridden by show positive sign, '+' flag.
+ if (!(out.flags() & std::ios::showpos))
+ spacePadPositive = true;
+ continue;
+ case '+':
+ out.setf(std::ios::showpos);
+ spacePadPositive = false;
+ widthExtra = 1;
+ continue;
+ default:
+ break;
+ }
+ break;
+ }
+ // Parse width
int width = 0;
- if(argIndex < numFormatters)
- width = formatters[argIndex++].toInt();
- else
- TINYFORMAT_ERROR("tinyformat: Not enough arguments to read variable width");
- if(width < 0)
- {
- // negative widths correspond to '-' flag set
- out.fill(' ');
- out.setf(std::ios::left, std::ios::adjustfield);
- width = -width;
+ widthSet = parseWidthOrPrecision(width, c, positionalMode,
+ args, argIndex, numArgs);
+ if (widthSet) {
+ if (width < 0) {
+ // negative widths correspond to '-' flag set
+ out.fill(' ');
+ out.setf(std::ios::left, std::ios::adjustfield);
+ width = -width;
+ }
+ out.width(width);
}
- out.width(width);
- ++c;
}
// 3) Parse precision
- if(*c == '.')
- {
+ if (*c == '.') {
++c;
int precision = 0;
- if(*c == '*')
- {
- ++c;
- if(argIndex < numFormatters)
- precision = formatters[argIndex++].toInt();
- else
- TINYFORMAT_ERROR("tinyformat: Not enough arguments to read variable precision");
- }
- else
- {
- if(*c >= '0' && *c <= '9')
- precision = parseIntAndAdvance(c);
- else if(*c == '-') // negative precisions ignored, treated as zero.
- parseIntAndAdvance(++c);
- }
- out.precision(precision);
- precisionSet = true;
+ parseWidthOrPrecision(precision, c, positionalMode,
+ args, argIndex, numArgs);
+ // Presence of `.` indicates precision set, unless the inferred value
+ // was negative in which case the default is used.
+ precisionSet = precision >= 0;
+ if (precisionSet)
+ out.precision(precision);
}
// 4) Ignore any C99 length modifier
- while(*c == 'l' || *c == 'h' || *c == 'L' ||
- *c == 'j' || *c == 'z' || *c == 't')
+ while (*c == 'l' || *c == 'h' || *c == 'L' ||
+ *c == 'j' || *c == 'z' || *c == 't') {
++c;
+ }
// 5) We're up to the conversion specifier character.
// Set stream flags based on conversion specifier (thanks to the
// boost::format class for forging the way here).
bool intConversion = false;
- switch(*c)
- {
+ switch (*c) {
case 'u': case 'd': case 'i':
out.setf(std::ios::dec, std::ios::basefield);
intConversion = true;
@@ -738,6 +815,18 @@ inline const char* streamStateFromFormat(std::ostream& out, bool& spacePadPositi
case 'f':
out.setf(std::ios::fixed, std::ios::floatfield);
break;
+ case 'A':
+ out.setf(std::ios::uppercase);
+ // Falls through
+ case 'a':
+# ifdef _MSC_VER
+ // Workaround https://developercommunity.visualstudio.com/content/problem/520472/hexfloat-stream-output-does-not-ignore-precision-a.html
+ // by always setting maximum precision on MSVC to avoid precision
+ // loss for doubles.
+ out.precision(13);
+# endif
+ out.setf(std::ios::fixed | std::ios::scientific, std::ios::floatfield);
+ break;
case 'G':
out.setf(std::ios::uppercase);
// Falls through
@@ -746,17 +835,13 @@ inline const char* streamStateFromFormat(std::ostream& out, bool& spacePadPositi
// As in boost::format, let stream decide float format.
out.flags(out.flags() & ~std::ios::floatfield);
break;
- case 'a': case 'A':
- TINYFORMAT_ERROR("tinyformat: the %a and %A conversion specs "
- "are not supported");
- break;
case 'c':
// Handled as special case inside formatValue()
break;
case 's':
- if(precisionSet)
+ if (precisionSet)
ntrunc = static_cast<int>(out.precision());
- // Make %s print booleans as "true" and "false"
+ // Make %s print Booleans as "true" and "false"
out.setf(std::ios::boolalpha);
break;
case 'n':
@@ -770,8 +855,7 @@ inline const char* streamStateFromFormat(std::ostream& out, bool& spacePadPositi
default:
break;
}
- if(intConversion && precisionSet && !widthSet)
- {
+ if (intConversion && precisionSet && !widthSet) {
// "precision" for integers gives the minimum number of digits (to be
// padded with zeros on the left). This isn't really supported by the
// iostreams, but we can approximately simulate it with the width if
@@ -786,8 +870,8 @@ inline const char* streamStateFromFormat(std::ostream& out, bool& spacePadPositi
//------------------------------------------------------------------------------
inline void formatImpl(std::ostream& out, const char* fmt,
- const detail::FormatArg* formatters,
- int numFormatters)
+ const detail::FormatArg* args,
+ int numArgs)
{
// Saved stream state
std::streamsize origWidth = out.width();
@@ -795,26 +879,34 @@ inline void formatImpl(std::ostream& out, const char* fmt,
std::ios::fmtflags origFlags = out.flags();
char origFill = out.fill();
- for (int argIndex = 0; argIndex < numFormatters; ++argIndex)
- {
- // Parse the format string
+ // "Positional mode" means all format specs should be of the form "%n$..."
+ // with `n` an integer. We detect this in `streamStateFromFormat`.
+ bool positionalMode = false;
+ int argIndex = 0;
+ while (true) {
fmt = printFormatStringLiteral(out, fmt);
+ if (*fmt == '\0') {
+ if (!positionalMode && argIndex < numArgs) {
+ TINYFORMAT_ERROR("tinyformat: Not enough conversion specifiers in format string");
+ }
+ break;
+ }
bool spacePadPositive = false;
int ntrunc = -1;
- const char* fmtEnd = streamStateFromFormat(out, spacePadPositive, ntrunc, fmt,
- formatters, argIndex, numFormatters);
- if (argIndex >= numFormatters)
- {
- // Check args remain after reading any variable width/precision
- TINYFORMAT_ERROR("tinyformat: Not enough format arguments");
+ const char* fmtEnd = streamStateFromFormat(out, positionalMode, spacePadPositive, ntrunc, fmt,
+ args, argIndex, numArgs);
+ // NB: argIndex may be incremented by reading variable width/precision
+ // in `streamStateFromFormat`, so do the bounds check here.
+ if (argIndex >= numArgs) {
+ TINYFORMAT_ERROR("tinyformat: Too many conversion specifiers in format string");
return;
}
- const FormatArg& arg = formatters[argIndex];
+ const FormatArg& arg = args[argIndex];
// Format the arg into the stream.
- if(!spacePadPositive)
+ if (!spacePadPositive) {
arg.format(out, fmt, fmtEnd, ntrunc);
- else
- {
+ }
+ else {
// The following is a special case with no direct correspondence
// between stream formatting and the printf() behaviour. Simulate
// it crudely by formatting into a temporary string stream and
@@ -824,18 +916,17 @@ inline void formatImpl(std::ostream& out, const char* fmt,
tmpStream.setf(std::ios::showpos);
arg.format(tmpStream, fmt, fmtEnd, ntrunc);
std::string result = tmpStream.str(); // allocates... yuck.
- for(size_t i = 0, iend = result.size(); i < iend; ++i)
- if(result[i] == '+') result[i] = ' ';
+ for (size_t i = 0, iend = result.size(); i < iend; ++i) {
+ if (result[i] == '+')
+ result[i] = ' ';
+ }
out << result;
}
+ if (!positionalMode)
+ ++argIndex;
fmt = fmtEnd;
}
- // Print remaining part of format string.
- fmt = printFormatStringLiteral(out, fmt);
- if(*fmt != '\0')
- TINYFORMAT_ERROR("tinyformat: Too many conversion specifiers in format string");
-
// Restore stream state
out.width(origWidth);
out.precision(origPrecision);
@@ -855,14 +946,14 @@ inline void formatImpl(std::ostream& out, const char* fmt,
class FormatList
{
public:
- FormatList(detail::FormatArg* formatters, int N)
- : m_formatters(formatters), m_N(N) { }
+ FormatList(detail::FormatArg* args, int N)
+ : m_args(args), m_N(N) { }
friend void vformat(std::ostream& out, const char* fmt,
const FormatList& list);
private:
- const detail::FormatArg* m_formatters;
+ const detail::FormatArg* m_args;
int m_N;
};
@@ -879,29 +970,33 @@ class FormatListN : public FormatList
public:
#ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES
template<typename... Args>
- explicit FormatListN(const Args&... args)
+ FormatListN(const Args&... args)
: FormatList(&m_formatterStore[0], N),
m_formatterStore { FormatArg(args)... }
{ static_assert(sizeof...(args) == N, "Number of args must be N"); }
#else // C++98 version
void init(int) {}
-# define TINYFORMAT_MAKE_FORMATLIST_CONSTRUCTOR(n) \
- \
- template<TINYFORMAT_ARGTYPES(n)> \
- explicit FormatListN(TINYFORMAT_VARARGS(n)) \
- : FormatList(&m_formatterStore[0], n) \
- { assert(n == N); init(0, TINYFORMAT_PASSARGS(n)); } \
- \
- template<TINYFORMAT_ARGTYPES(n)> \
- void init(int i, TINYFORMAT_VARARGS(n)) \
- { \
- m_formatterStore[i] = FormatArg(v1); \
- init(i+1 TINYFORMAT_PASSARGS_TAIL(n)); \
+# define TINYFORMAT_MAKE_FORMATLIST_CONSTRUCTOR(n) \
+ \
+ template<TINYFORMAT_ARGTYPES(n)> \
+ FormatListN(TINYFORMAT_VARARGS(n)) \
+ : FormatList(&m_formatterStore[0], n) \
+ { TINYFORMAT_ASSERT(n == N); init(0, TINYFORMAT_PASSARGS(n)); } \
+ \
+ template<TINYFORMAT_ARGTYPES(n)> \
+ void init(int i, TINYFORMAT_VARARGS(n)) \
+ { \
+ m_formatterStore[i] = FormatArg(v1); \
+ init(i+1 TINYFORMAT_PASSARGS_TAIL(n)); \
}
TINYFORMAT_FOREACH_ARGNUM(TINYFORMAT_MAKE_FORMATLIST_CONSTRUCTOR)
# undef TINYFORMAT_MAKE_FORMATLIST_CONSTRUCTOR
#endif
+ FormatListN(const FormatListN& other)
+ : FormatList(&m_formatterStore[0], N)
+ { std::copy(&other.m_formatterStore[0], &other.m_formatterStore[N],
+ &m_formatterStore[0]); }
private:
FormatArg m_formatterStore[N];
@@ -956,7 +1051,7 @@ TINYFORMAT_FOREACH_ARGNUM(TINYFORMAT_MAKE_MAKEFORMATLIST)
/// list of format arguments is held in a single function argument.
inline void vformat(std::ostream& out, const char* fmt, FormatListRef list)
{
- detail::formatImpl(out, fmt, list.m_formatters, list.m_N);
+ detail::formatImpl(out, fmt, list.m_args, list.m_N);
}
@@ -993,6 +1088,7 @@ void printfln(const char* fmt, const Args&... args)
std::cout << '\n';
}
+
#else // C++98 version
inline void format(std::ostream& out, const char* fmt)
@@ -1063,6 +1159,7 @@ std::string format(const std::string &fmt, const Args&... args)
} // namespace tinyformat
+// Added for Bitcoin Core:
/** Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for details) */
#define strprintf tfm::format
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, &param)) {
+ if (pthread_setschedparam(pthread_self(), SCHED_BATCH, &param) != 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 e744110371..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;
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/scriptpubkeyman.cpp b/src/wallet/scriptpubkeyman.cpp
index 3eaaf3786c..2b9e8fbf2a 100644
--- a/src/wallet/scriptpubkeyman.cpp
+++ b/src/wallet/scriptpubkeyman.cpp
@@ -18,7 +18,7 @@ bool LegacyScriptPubKeyMan::GetNewDestination(const OutputType type, CTxDestinat
// Generate a new key that is added to wallet
CPubKey new_key;
- if (!GetKeyFromPool(new_key)) {
+ if (!GetKeyFromPool(new_key, type)) {
error = "Error: Keypool ran out, please call keypoolrefill first";
return false;
}
@@ -262,24 +262,19 @@ bool LegacyScriptPubKeyMan::EncryptKeys(CKeyingMaterial& vMasterKeyIn)
return true;
}
-bool LegacyScriptPubKeyMan::GetReservedDestination(const OutputType type, bool internal, int64_t& index, CKeyPool& keypool)
+bool LegacyScriptPubKeyMan::GetReservedDestination(const OutputType type, bool internal, CTxDestination& address, int64_t& index, CKeyPool& keypool)
{
+ if (!CanGetAddresses(internal)) {
+ return false;
+ }
+
if (!ReserveKeyFromKeyPool(index, keypool, internal)) {
return false;
}
+ address = GetDestinationForKey(keypool.vchPubKey, type);
return true;
}
-void LegacyScriptPubKeyMan::KeepDestination(int64_t index)
-{
- KeepKey(index);
-}
-
-void LegacyScriptPubKeyMan::ReturnDestination(int64_t index, bool internal, const CPubKey& pubkey)
-{
- ReturnKey(index, internal, pubkey);
-}
-
void LegacyScriptPubKeyMan::MarkUnusedAddresses(const CScript& script)
{
AssertLockHeld(cs_wallet);
@@ -460,7 +455,7 @@ size_t LegacyScriptPubKeyMan::KeypoolCountExternalKeys()
unsigned int LegacyScriptPubKeyMan::GetKeyPoolSize() const
{
AssertLockHeld(cs_wallet);
- return setInternalKeyPool.size() + setExternalKeyPool.size();
+ return setInternalKeyPool.size() + setExternalKeyPool.size() + set_pre_split_keypool.size();
}
int64_t LegacyScriptPubKeyMan::GetTimeFirstKey() const
@@ -1092,15 +1087,20 @@ void LegacyScriptPubKeyMan::AddKeypoolPubkeyWithDB(const CPubKey& pubkey, const
m_pool_key_to_index[pubkey.GetID()] = index;
}
-void LegacyScriptPubKeyMan::KeepKey(int64_t nIndex)
+void LegacyScriptPubKeyMan::KeepDestination(int64_t nIndex, const OutputType& type)
{
// Remove from key pool
WalletBatch batch(m_storage.GetDatabase());
batch.ErasePool(nIndex);
+ CPubKey pubkey;
+ bool have_pk = GetPubKey(m_index_to_reserved_key.at(nIndex), pubkey);
+ assert(have_pk);
+ LearnRelatedScripts(pubkey, type);
+ m_index_to_reserved_key.erase(nIndex);
WalletLogPrintf("keypool keep %d\n", nIndex);
}
-void LegacyScriptPubKeyMan::ReturnKey(int64_t nIndex, bool fInternal, const CPubKey& pubkey)
+void LegacyScriptPubKeyMan::ReturnDestination(int64_t nIndex, bool fInternal, const CTxDestination&)
{
// Return to key pool
{
@@ -1112,13 +1112,15 @@ void LegacyScriptPubKeyMan::ReturnKey(int64_t nIndex, bool fInternal, const CPub
} else {
setExternalKeyPool.insert(nIndex);
}
- m_pool_key_to_index[pubkey.GetID()] = nIndex;
+ CKeyID& pubkey_id = m_index_to_reserved_key.at(nIndex);
+ m_pool_key_to_index[pubkey_id] = nIndex;
+ m_index_to_reserved_key.erase(nIndex);
NotifyCanGetAddressesChanged();
}
WalletLogPrintf("keypool return %d\n", nIndex);
}
-bool LegacyScriptPubKeyMan::GetKeyFromPool(CPubKey& result, bool internal)
+bool LegacyScriptPubKeyMan::GetKeyFromPool(CPubKey& result, const OutputType type, bool internal)
{
if (!CanGetAddresses(internal)) {
return false;
@@ -1134,7 +1136,7 @@ bool LegacyScriptPubKeyMan::GetKeyFromPool(CPubKey& result, bool internal)
result = GenerateNewKey(batch, internal);
return true;
}
- KeepKey(nIndex);
+ KeepDestination(nIndex, type);
result = keypool.vchPubKey;
}
return true;
@@ -1179,6 +1181,8 @@ bool LegacyScriptPubKeyMan::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& key
throw std::runtime_error(std::string(__func__) + ": keypool entry invalid");
}
+ assert(m_index_to_reserved_key.count(nIndex) == 0);
+ m_index_to_reserved_key[nIndex] = keypool.vchPubKey.GetID();
m_pool_key_to_index.erase(keypool.vchPubKey.GetID());
WalletLogPrintf("keypool reserve %d\n", nIndex);
}
diff --git a/src/wallet/scriptpubkeyman.h b/src/wallet/scriptpubkeyman.h
index 4f17156792..6ed9a4787a 100644
--- a/src/wallet/scriptpubkeyman.h
+++ b/src/wallet/scriptpubkeyman.h
@@ -150,9 +150,9 @@ public:
virtual bool GetNewDestination(const OutputType type, CTxDestination& dest, std::string& error) { return false; }
virtual isminetype IsMine(const CScript& script) const { return ISMINE_NO; }
- virtual bool GetReservedDestination(const OutputType type, bool internal, int64_t& index, CKeyPool& keypool) { return false; }
- virtual void KeepDestination(int64_t index) {}
- virtual void ReturnDestination(int64_t index, bool internal, const CPubKey& pubkey) {}
+ virtual bool GetReservedDestination(const OutputType type, bool internal, CTxDestination& address, int64_t& index, CKeyPool& keypool) { return false; }
+ virtual void KeepDestination(int64_t index, const OutputType& type) {}
+ virtual void ReturnDestination(int64_t index, bool internal, const CTxDestination& addr) {}
virtual bool TopUp(unsigned int size = 0) { return false; }
@@ -246,9 +246,11 @@ private:
std::set<int64_t> set_pre_split_keypool GUARDED_BY(cs_wallet);
int64_t m_max_keypool_index GUARDED_BY(cs_wallet) = 0;
std::map<CKeyID, int64_t> m_pool_key_to_index;
+ // Tracks keypool indexes to CKeyIDs of keys that have been taken out of the keypool but may be returned to it
+ std::map<int64_t, CKeyID> m_index_to_reserved_key;
//! Fetches a key from the keypool
- bool GetKeyFromPool(CPubKey &key, bool internal = false);
+ bool GetKeyFromPool(CPubKey &key, const OutputType type, bool internal = false);
/**
* Reserves a key from the keypool and sets nIndex to its index
@@ -266,9 +268,6 @@ private:
*/
bool ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool, bool fRequestedInternal);
- void KeepKey(int64_t nIndex);
- void ReturnKey(int64_t nIndex, bool fInternal, const CPubKey& pubkey);
-
public:
bool GetNewDestination(const OutputType type, CTxDestination& dest, std::string& error) override;
isminetype IsMine(const CScript& script) const override;
@@ -276,9 +275,9 @@ public:
//! will encrypt previously unencrypted keys
bool EncryptKeys(CKeyingMaterial& vMasterKeyIn);
- bool GetReservedDestination(const OutputType type, bool internal, int64_t& index, CKeyPool& keypool) override;
- void KeepDestination(int64_t index) override;
- void ReturnDestination(int64_t index, bool internal, const CPubKey& pubkey) override;
+ bool GetReservedDestination(const OutputType type, bool internal, CTxDestination& address, int64_t& index, CKeyPool& keypool) override;
+ void KeepDestination(int64_t index, const OutputType& type) override;
+ void ReturnDestination(int64_t index, bool internal, const CTxDestination&) override;
bool TopUp(unsigned int size = 0) override;
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..abee497c1d 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,49 +3288,41 @@ 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) {
return false;
}
- if (!pwallet->CanGetAddresses(internal)) {
- return false;
- }
if (nIndex == -1)
{
CKeyPool keypool;
- if (!m_spk_man->GetReservedDestination(type, internal, nIndex, keypool)) {
+ if (!m_spk_man->GetReservedDestination(type, internal, address, nIndex, keypool)) {
return false;
}
- vchPubKey = keypool.vchPubKey;
fInternal = keypool.fInternal;
}
- assert(vchPubKey.IsValid());
- m_spk_man->LearnRelatedScripts(vchPubKey, type);
- address = GetDestinationForKey(vchPubKey, type);
dest = address;
return true;
}
void ReserveDestination::KeepDestination()
{
- if (nIndex != -1)
- m_spk_man->KeepDestination(nIndex);
+ if (nIndex != -1) {
+ m_spk_man->KeepDestination(nIndex, type);
+ }
nIndex = -1;
- vchPubKey = CPubKey();
address = CNoDestination();
}
void ReserveDestination::ReturnDestination()
{
if (nIndex != -1) {
- m_spk_man->ReturnDestination(nIndex, fInternal, vchPubKey);
+ m_spk_man->ReturnDestination(nIndex, fInternal, address);
}
nIndex = -1;
- vchPubKey = CPubKey();
address = CNoDestination();
}
@@ -3651,9 +3666,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 +4037,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..b02e092f0a 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,12 +138,12 @@ class ReserveDestination
{
protected:
//! The wallet to reserve from
- CWallet* pwallet;
- LegacyScriptPubKeyMan* m_spk_man{nullptr};
+ CWallet* const pwallet;
+ //! The ScriptPubKeyMan to reserve from. Based on type when GetReservedDestination is called
+ ScriptPubKeyMan* 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
- CPubKey vchPubKey;
//! The destination
CTxDestination address;
//! Whether this is from the internal (change output) keypool
@@ -153,10 +151,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 +165,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 +581,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 +1127,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/functional/create_cache.py b/test/functional/create_cache.py
index edf16fa47e..16a791177b 100755
--- a/test/functional/create_cache.py
+++ b/test/functional/create_cache.py
@@ -16,7 +16,6 @@ class CreateCache(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 0
- self.supports_cli = True
def setup_network(self):
pass
diff --git a/test/functional/feature_config_args.py b/test/functional/feature_config_args.py
index b997c76025..801209b1c0 100755
--- a/test/functional/feature_config_args.py
+++ b/test/functional/feature_config_args.py
@@ -13,6 +13,7 @@ class ConfArgsTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
self.num_nodes = 1
+ self.supports_cli = False
def test_config_file_parser(self):
# Assume node is stopped
diff --git a/test/functional/feature_csv_activation.py b/test/functional/feature_csv_activation.py
index 6bd321992a..c2b4de54f2 100755
--- a/test/functional/feature_csv_activation.py
+++ b/test/functional/feature_csv_activation.py
@@ -139,6 +139,7 @@ class BIP68_112_113Test(BitcoinTestFramework):
self.num_nodes = 1
self.setup_clean_chain = True
self.extra_args = [['-whitelist=127.0.0.1', '-blockversion=4', '-addresstype=legacy']]
+ self.supports_cli = False
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
diff --git a/test/functional/feature_dbcrash.py b/test/functional/feature_dbcrash.py
index 6bd6bb5b8c..5bbdb8cda1 100755
--- a/test/functional/feature_dbcrash.py
+++ b/test/functional/feature_dbcrash.py
@@ -51,6 +51,7 @@ class ChainstateWriteCrashTest(BitcoinTestFramework):
self.num_nodes = 4
self.setup_clean_chain = False
self.rpc_timeout = 480
+ self.supports_cli = False
# Set -maxmempool=0 to turn off mempool memory sharing with dbcache
# Set -rpcservertimeout=900 to reduce socket disconnects in this
diff --git a/test/functional/feature_loadblock.py b/test/functional/feature_loadblock.py
index bf2a4ff61f..bd4b271ca7 100755
--- a/test/functional/feature_loadblock.py
+++ b/test/functional/feature_loadblock.py
@@ -26,6 +26,7 @@ class LoadblockTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
self.num_nodes = 2
+ self.supports_cli = False
def run_test(self):
self.nodes[1].setnetworkactive(state=False)
diff --git a/test/functional/feature_maxuploadtarget.py b/test/functional/feature_maxuploadtarget.py
index 180ea0e51d..42e2b5bff2 100755
--- a/test/functional/feature_maxuploadtarget.py
+++ b/test/functional/feature_maxuploadtarget.py
@@ -36,6 +36,7 @@ class MaxUploadTest(BitcoinTestFramework):
self.setup_clean_chain = True
self.num_nodes = 1
self.extra_args = [["-maxuploadtarget=800", "-acceptnonstdtxn=1"]]
+ self.supports_cli = False
# Cache for utxos, as the listunspent may take a long time later in the test
self.utxo_cache = []
diff --git a/test/functional/feature_pruning.py b/test/functional/feature_pruning.py
index 51523f13e7..e1e0f00530 100755
--- a/test/functional/feature_pruning.py
+++ b/test/functional/feature_pruning.py
@@ -78,6 +78,7 @@ class PruneTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
self.num_nodes = 6
+ self.supports_cli = False
# Create nodes 0 and 1 to mine.
# Create node 2 to test pruning.
diff --git a/test/functional/feature_rbf.py b/test/functional/feature_rbf.py
index e7afbd0272..9e578f0026 100755
--- a/test/functional/feature_rbf.py
+++ b/test/functional/feature_rbf.py
@@ -76,6 +76,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
"-limitdescendantsize=101",
],
]
+ self.supports_cli = False
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
diff --git a/test/functional/feature_shutdown.py b/test/functional/feature_shutdown.py
index 5084cb1322..9485db9864 100755
--- a/test/functional/feature_shutdown.py
+++ b/test/functional/feature_shutdown.py
@@ -17,6 +17,7 @@ class ShutdownTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
self.num_nodes = 1
+ self.supports_cli = False
def run_test(self):
node = get_rpc_proxy(self.nodes[0].url, 1, timeout=600, coveragedir=self.nodes[0].coverage_dir)
diff --git a/test/functional/interface_bitcoin_cli.py b/test/functional/interface_bitcoin_cli.py
index ec1c88ed53..f04a58cd19 100755
--- a/test/functional/interface_bitcoin_cli.py
+++ b/test/functional/interface_bitcoin_cli.py
@@ -59,7 +59,6 @@ class TestBitcoinCli(BitcoinTestFramework):
blockchain_info = self.nodes[0].getblockchaininfo()
assert_equal(cli_get_info['version'], network_info['version'])
- assert_equal(cli_get_info['protocolversion'], network_info['protocolversion'])
assert_equal(cli_get_info['blocks'], blockchain_info['blocks'])
assert_equal(cli_get_info['timeoffset'], network_info['timeoffset'])
assert_equal(cli_get_info['connections'], network_info['connections'])
@@ -67,9 +66,7 @@ class TestBitcoinCli(BitcoinTestFramework):
assert_equal(cli_get_info['difficulty'], blockchain_info['difficulty'])
assert_equal(cli_get_info['chain'], blockchain_info['chain'])
if self.is_wallet_compiled():
- assert_equal(cli_get_info['walletversion'], wallet_info['walletversion'])
assert_equal(cli_get_info['balance'], wallet_info['balance'])
- assert_equal(cli_get_info['keypoololdest'], wallet_info['keypoololdest'])
assert_equal(cli_get_info['keypoolsize'], wallet_info['keypoolsize'])
assert_equal(cli_get_info['paytxfee'], wallet_info['paytxfee'])
assert_equal(cli_get_info['relayfee'], network_info['relayfee'])
diff --git a/test/functional/interface_http.py b/test/functional/interface_http.py
index bb868d7115..d007490f80 100755
--- a/test/functional/interface_http.py
+++ b/test/functional/interface_http.py
@@ -13,6 +13,7 @@ import urllib.parse
class HTTPBasicsTest (BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 3
+ self.supports_cli = False
def setup_network(self):
self.setup_nodes()
diff --git a/test/functional/interface_rest.py b/test/functional/interface_rest.py
index a036dfc790..e73ec90819 100755
--- a/test/functional/interface_rest.py
+++ b/test/functional/interface_rest.py
@@ -44,6 +44,7 @@ class RESTTest (BitcoinTestFramework):
self.setup_clean_chain = True
self.num_nodes = 2
self.extra_args = [["-rest"], []]
+ self.supports_cli = False
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
@@ -151,7 +152,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/interface_rpc.py b/test/functional/interface_rpc.py
index e99fa22646..e460db39f8 100755
--- a/test/functional/interface_rpc.py
+++ b/test/functional/interface_rpc.py
@@ -22,6 +22,7 @@ class RPCInterfaceTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 1
self.setup_clean_chain = True
+ self.supports_cli = False
def test_getrpcinfo(self):
self.log.info("Testing getrpcinfo...")
diff --git a/test/functional/mempool_accept.py b/test/functional/mempool_accept.py
index c466b120f2..9cb6b03ee0 100755
--- a/test/functional/mempool_accept.py
+++ b/test/functional/mempool_accept.py
@@ -37,6 +37,7 @@ class MempoolAcceptanceTest(BitcoinTestFramework):
self.extra_args = [[
'-txindex',
]] * self.num_nodes
+ self.supports_cli = False
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
@@ -267,6 +268,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/mempool_limit.py b/test/functional/mempool_limit.py
index edf2069933..39035f7cb1 100755
--- a/test/functional/mempool_limit.py
+++ b/test/functional/mempool_limit.py
@@ -18,6 +18,7 @@ class MempoolLimitTest(BitcoinTestFramework):
"-maxmempool=5",
"-spendzeroconfchange=0",
]]
+ self.supports_cli = False
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
diff --git a/test/functional/mining_basic.py b/test/functional/mining_basic.py
index f9231614ce..bfeaa76c74 100755
--- a/test/functional/mining_basic.py
+++ b/test/functional/mining_basic.py
@@ -43,6 +43,7 @@ class MiningTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 2
self.setup_clean_chain = True
+ self.supports_cli = False
def mine_chain(self):
self.log.info('Create some old blocks')
diff --git a/test/functional/mining_getblocktemplate_longpoll.py b/test/functional/mining_getblocktemplate_longpoll.py
index 445ec124ce..6d0b241e57 100755
--- a/test/functional/mining_getblocktemplate_longpoll.py
+++ b/test/functional/mining_getblocktemplate_longpoll.py
@@ -27,6 +27,7 @@ class LongpollThread(threading.Thread):
class GetBlockTemplateLPTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 2
+ self.supports_cli = False
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
diff --git a/test/functional/mining_prioritisetransaction.py b/test/functional/mining_prioritisetransaction.py
index 7e05a8e6c8..1426fdaacb 100755
--- a/test/functional/mining_prioritisetransaction.py
+++ b/test/functional/mining_prioritisetransaction.py
@@ -18,6 +18,7 @@ class PrioritiseTransactionTest(BitcoinTestFramework):
"-printpriority=1",
"-acceptnonstdtxn=1",
]] * self.num_nodes
+ self.supports_cli = False
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
diff --git a/test/functional/p2p_disconnect_ban.py b/test/functional/p2p_disconnect_ban.py
index 23dea4b729..1b64b65b82 100755
--- a/test/functional/p2p_disconnect_ban.py
+++ b/test/functional/p2p_disconnect_ban.py
@@ -16,6 +16,7 @@ from test_framework.util import (
class DisconnectBanTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 2
+ self.supports_cli = False
def run_test(self):
self.log.info("Connect nodes both way")
diff --git a/test/functional/p2p_segwit.py b/test/functional/p2p_segwit.py
index 0c7edbf434..297fa88fbe 100755
--- a/test/functional/p2p_segwit.py
+++ b/test/functional/p2p_segwit.py
@@ -191,6 +191,7 @@ class SegWitTest(BitcoinTestFramework):
["-whitelist=127.0.0.1", "-acceptnonstdtxn=0", "-segwitheight={}".format(SEGWIT_HEIGHT)],
["-whitelist=127.0.0.1", "-acceptnonstdtxn=1", "-segwitheight=-1"]
]
+ self.supports_cli = False
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
@@ -1116,7 +1117,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 +1141,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_bind.py b/test/functional/rpc_bind.py
index 8979251a26..664a15a5ec 100755
--- a/test/functional/rpc_bind.py
+++ b/test/functional/rpc_bind.py
@@ -15,6 +15,7 @@ class RPCBindTest(BitcoinTestFramework):
self.setup_clean_chain = True
self.bind_to_localhost_only = False
self.num_nodes = 1
+ self.supports_cli = False
def setup_network(self):
self.add_nodes(self.num_nodes, None)
diff --git a/test/functional/rpc_blockchain.py b/test/functional/rpc_blockchain.py
index 278ce6d911..adf6f1ca4f 100755
--- a/test/functional/rpc_blockchain.py
+++ b/test/functional/rpc_blockchain.py
@@ -49,6 +49,7 @@ class BlockchainTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
self.num_nodes = 1
+ self.supports_cli = False
def run_test(self):
self.mine_chain()
diff --git a/test/functional/rpc_createmultisig.py b/test/functional/rpc_createmultisig.py
index 2a64a29967..aa7f12848c 100755
--- a/test/functional/rpc_createmultisig.py
+++ b/test/functional/rpc_createmultisig.py
@@ -22,6 +22,7 @@ class RpcCreateMultiSigTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
self.num_nodes = 3
+ self.supports_cli = False
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
diff --git a/test/functional/rpc_deriveaddresses.py b/test/functional/rpc_deriveaddresses.py
index 42128d5767..42d7d59d56 100755
--- a/test/functional/rpc_deriveaddresses.py
+++ b/test/functional/rpc_deriveaddresses.py
@@ -10,7 +10,6 @@ from test_framework.util import assert_equal, assert_raises_rpc_error
class DeriveaddressesTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 1
- self.supports_cli = 1
def run_test(self):
assert_raises_rpc_error(-5, "Missing checksum", self.nodes[0].deriveaddresses, "a")
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/rpc_getblockstats.py b/test/functional/rpc_getblockstats.py
index efab69ac26..57794ae973 100755
--- a/test/functional/rpc_getblockstats.py
+++ b/test/functional/rpc_getblockstats.py
@@ -33,6 +33,7 @@ class GetblockstatsTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 1
self.setup_clean_chain = True
+ self.supports_cli = False
def get_stats(self):
return [self.nodes[0].getblockstats(hash_or_height=self.start_height + i) for i in range(self.max_stat_pos+1)]
diff --git a/test/functional/rpc_help.py b/test/functional/rpc_help.py
index 78d6e78aed..ec8ea5697a 100755
--- a/test/functional/rpc_help.py
+++ b/test/functional/rpc_help.py
@@ -13,6 +13,7 @@ import os
class HelpRpcTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 1
+ self.supports_cli = False
def run_test(self):
self.test_categories()
diff --git a/test/functional/rpc_misc.py b/test/functional/rpc_misc.py
index 3da9f05ca5..c8517d719e 100755
--- a/test/functional/rpc_misc.py
+++ b/test/functional/rpc_misc.py
@@ -19,6 +19,7 @@ from test_framework.authproxy import JSONRPCException
class RpcMiscTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 1
+ self.supports_cli = False
def run_test(self):
node = self.nodes[0]
diff --git a/test/functional/rpc_named_arguments.py b/test/functional/rpc_named_arguments.py
index ecac9c2f82..41b9312969 100755
--- a/test/functional/rpc_named_arguments.py
+++ b/test/functional/rpc_named_arguments.py
@@ -13,6 +13,7 @@ from test_framework.util import (
class NamedArgumentTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 1
+ self.supports_cli = False
def run_test(self):
node = self.nodes[0]
diff --git a/test/functional/rpc_net.py b/test/functional/rpc_net.py
index 615f9abbe0..368debf35c 100755
--- a/test/functional/rpc_net.py
+++ b/test/functional/rpc_net.py
@@ -45,6 +45,7 @@ class NetTest(BitcoinTestFramework):
self.setup_clean_chain = True
self.num_nodes = 2
self.extra_args = [["-minrelaytxfee=0.00001000"],["-minrelaytxfee=0.00000500"]]
+ self.supports_cli = False
def run_test(self):
self.log.info('Connect nodes both way')
diff --git a/test/functional/rpc_preciousblock.py b/test/functional/rpc_preciousblock.py
index 0663ffdf5b..8386e47411 100755
--- a/test/functional/rpc_preciousblock.py
+++ b/test/functional/rpc_preciousblock.py
@@ -36,6 +36,7 @@ class PreciousTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
self.num_nodes = 3
+ self.supports_cli = False
def setup_network(self):
self.setup_nodes()
diff --git a/test/functional/rpc_psbt.py b/test/functional/rpc_psbt.py
index 61572654e0..2cc9650cb2 100755
--- a/test/functional/rpc_psbt.py
+++ b/test/functional/rpc_psbt.py
@@ -32,6 +32,7 @@ class PSBTTest(BitcoinTestFramework):
["-walletrbf=0"],
[]
]
+ self.supports_cli = False
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
@@ -416,5 +417,10 @@ class PSBTTest(BitcoinTestFramework):
analyzed = self.nodes[0].analyzepsbt(signed)
assert analyzed['inputs'][0]['has_utxo'] and analyzed['inputs'][0]['is_final'] and analyzed['next'] == 'extractor'
+ self.log.info("PSBT spending unspendable outputs should have error message and Creator as next")
+ analysis = self.nodes[0].analyzepsbt('cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWAEHYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFv8/wADXYP/7//////8JxOh0LR2HAI8AAAAAAAEBIADC6wsAAAAAF2oUt/X69ELjeX2nTof+fZ10l+OyAokDAQcJAwEHEAABAACAAAEBIADC6wsAAAAAF2oUt/X69ELjeX2nTof+fZ10l+OyAokDAQcJAwEHENkMak8AAAAA')
+ assert_equal(analysis['next'], 'creator')
+ assert_equal(analysis['error'], 'PSBT is not valid. Input 0 spends unspendable output')
+
if __name__ == '__main__':
PSBTTest().main()
diff --git a/test/functional/rpc_rawtransaction.py b/test/functional/rpc_rawtransaction.py
index 4ee46d5f53..14cad3d1b8 100755
--- a/test/functional/rpc_rawtransaction.py
+++ b/test/functional/rpc_rawtransaction.py
@@ -53,6 +53,7 @@ class RawTransactionsTest(BitcoinTestFramework):
["-txindex"],
["-txindex"],
]
+ self.supports_cli = False
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
diff --git a/test/functional/rpc_users.py b/test/functional/rpc_users.py
index 8bbb3c04fa..3541f96ab7 100755
--- a/test/functional/rpc_users.py
+++ b/test/functional/rpc_users.py
@@ -35,6 +35,7 @@ def call_with_auth(node, user, password):
class HTTPBasicsTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 2
+ self.supports_cli = False
def setup_chain(self):
super().setup_chain()
diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py
index 6b6bbfd1f9..da92c6325a 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
@@ -96,7 +97,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
self.nodes = []
self.network_thread = None
self.rpc_timeout = 60 # Wait for up to 60 seconds for the RPC server to respond
- self.supports_cli = False
+ self.supports_cli = True
self.bind_to_localhost_only = True
self.set_test_params()
self.parse_args()
@@ -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
@@ -157,6 +161,8 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
help="use bitcoin-cli instead of RPC for all commands")
parser.add_argument("--perf", dest="perf", default=False, action="store_true",
help="profile running nodes with perf for the duration of the test")
+ parser.add_argument("--valgrind", dest="valgrind", default=False, action="store_true",
+ help="run nodes under the valgrind memory error detector: expect at least a ~10x slowdown, valgrind 3.14 or later required")
parser.add_argument("--randomseed", type=int,
help="set a random seed for deterministically reproducing a previous test run")
self.add_options(parser)
@@ -394,6 +400,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
extra_args=extra_args[i],
use_cli=self.options.usecli,
start_perf=self.options.perf,
+ use_valgrind=self.options.valgrind,
))
def start_node(self, i, *args, **kwargs):
diff --git a/test/functional/test_framework/test_node.py b/test/functional/test_framework/test_node.py
index 1c9628264f..e5c77ae5fa 100755
--- a/test/functional/test_framework/test_node.py
+++ b/test/functional/test_framework/test_node.py
@@ -30,6 +30,7 @@ from .util import (
rpc_url,
wait_until,
p2p_port,
+ EncodeDecimal,
)
BITCOIND_PROC_WAIT_TIMEOUT = 60
@@ -59,7 +60,7 @@ class TestNode():
To make things easier for the test writer, any unrecognised messages will
be dispatched to the RPC connection."""
- def __init__(self, i, datadir, *, chain, rpchost, timewait, bitcoind, bitcoin_cli, coverage_dir, cwd, extra_conf=None, extra_args=None, use_cli=False, start_perf=False):
+ def __init__(self, i, datadir, *, chain, rpchost, timewait, bitcoind, bitcoin_cli, coverage_dir, cwd, extra_conf=None, extra_args=None, use_cli=False, start_perf=False, use_valgrind=False):
"""
Kwargs:
start_perf (bool): If True, begin profiling the node with `perf` as soon as
@@ -96,6 +97,15 @@ class TestNode():
"-debugexclude=leveldb",
"-uacomment=testnode%d" % i,
]
+ if use_valgrind:
+ default_suppressions_file = os.path.join(
+ os.path.dirname(os.path.realpath(__file__)),
+ "..", "..", "..", "contrib", "valgrind.supp")
+ suppressions_file = os.getenv("VALGRIND_SUPPRESSIONS_FILE",
+ default_suppressions_file)
+ self.args = ["valgrind", "--suppressions={}".format(suppressions_file),
+ "--gen-suppressions=all", "--exit-on-first-error=yes",
+ "--error-exitcode=1", "--quiet"] + self.args
self.cli = TestNodeCLI(bitcoin_cli, self.datadir)
self.use_cli = use_cli
@@ -480,7 +490,7 @@ def arg_to_cli(arg):
if isinstance(arg, bool):
return str(arg).lower()
elif isinstance(arg, dict) or isinstance(arg, list):
- return json.dumps(arg)
+ return json.dumps(arg, default=EncodeDecimal)
else:
return str(arg)
diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py
index 4d7967273a..5bb73aee7e 100644
--- a/test/functional/test_framework/util.py
+++ b/test/functional/test_framework/util.py
@@ -190,6 +190,11 @@ def check_json_precision():
if satoshis != 2000000000000003:
raise RuntimeError("JSON encode/decode loses precision")
+def EncodeDecimal(o):
+ if isinstance(o, Decimal):
+ return str(o)
+ raise TypeError(repr(o) + " is not JSON serializable")
+
def count_bytes(hex_string):
return len(bytearray.fromhex(hex_string))
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/wallet_abandonconflict.py b/test/functional/wallet_abandonconflict.py
index e86679bc31..1122daaf83 100755
--- a/test/functional/wallet_abandonconflict.py
+++ b/test/functional/wallet_abandonconflict.py
@@ -18,6 +18,7 @@ from test_framework.util import (
assert_raises_rpc_error,
connect_nodes,
disconnect_nodes,
+ wait_until,
)
@@ -97,6 +98,7 @@ class AbandonConflictTest(BitcoinTestFramework):
# TODO: redo with eviction
self.stop_node(0)
self.start_node(0, extra_args=["-minrelaytxfee=0.0001"])
+ wait_until(lambda: self.nodes[0].getmempoolinfo()['loaded'])
# Verify txs no longer in either node's mempool
assert_equal(len(self.nodes[0].getrawmempool()), 0)
@@ -124,6 +126,8 @@ class AbandonConflictTest(BitcoinTestFramework):
# Verify that even with a low min relay fee, the tx is not reaccepted from wallet on startup once abandoned
self.stop_node(0)
self.start_node(0, extra_args=["-minrelaytxfee=0.00001"])
+ wait_until(lambda: self.nodes[0].getmempoolinfo()['loaded'])
+
assert_equal(len(self.nodes[0].getrawmempool()), 0)
assert_equal(self.nodes[0].getbalance(), balance)
@@ -144,6 +148,7 @@ class AbandonConflictTest(BitcoinTestFramework):
# Remove using high relay fee again
self.stop_node(0)
self.start_node(0, extra_args=["-minrelaytxfee=0.0001"])
+ wait_until(lambda: self.nodes[0].getmempoolinfo()['loaded'])
assert_equal(len(self.nodes[0].getrawmempool()), 0)
newbalance = self.nodes[0].getbalance()
assert_equal(newbalance, balance - Decimal("24.9996"))
diff --git a/test/functional/wallet_address_types.py b/test/functional/wallet_address_types.py
index 479d67fb66..f08606e622 100755
--- a/test/functional/wallet_address_types.py
+++ b/test/functional/wallet_address_types.py
@@ -83,6 +83,7 @@ class AddressTypeTest(BitcoinTestFramework):
# whitelist all peers to speed up tx relay / mempool sync
for args in self.extra_args:
args.append("-whitelist=127.0.0.1")
+ self.supports_cli = False
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
diff --git a/test/functional/wallet_basic.py b/test/functional/wallet_basic.py
index 550037923e..2606afa0e4 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):
@@ -24,6 +28,7 @@ class WalletTest(BitcoinTestFramework):
"-acceptnonstdtxn=1",
]] * self.num_nodes
self.setup_clean_chain = True
+ self.supports_cli = False
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
@@ -390,7 +395,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_createwallet.py b/test/functional/wallet_createwallet.py
index e302e499f4..048b3127ff 100755
--- a/test/functional/wallet_createwallet.py
+++ b/test/functional/wallet_createwallet.py
@@ -15,7 +15,6 @@ class CreateWalletTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = False
self.num_nodes = 1
- self.supports_cli = True
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
diff --git a/test/functional/wallet_hd.py b/test/functional/wallet_hd.py
index fa5d5a8878..575b501f50 100755
--- a/test/functional/wallet_hd.py
+++ b/test/functional/wallet_hd.py
@@ -20,6 +20,7 @@ class WalletHDTest(BitcoinTestFramework):
self.setup_clean_chain = True
self.num_nodes = 2
self.extra_args = [[], ['-keypool=0']]
+ self.supports_cli = False
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
diff --git a/test/functional/wallet_implicitsegwit.py b/test/functional/wallet_implicitsegwit.py
index 379fa6a12f..a8583e2879 100755
--- a/test/functional/wallet_implicitsegwit.py
+++ b/test/functional/wallet_implicitsegwit.py
@@ -41,6 +41,7 @@ def check_implicit_transactions(implicit_keys, implicit_node):
class ImplicitSegwitTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 2
+ self.supports_cli = False
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
diff --git a/test/functional/wallet_import_rescan.py b/test/functional/wallet_import_rescan.py
index 79062a4a29..b8b85b7a19 100755
--- a/test/functional/wallet_import_rescan.py
+++ b/test/functional/wallet_import_rescan.py
@@ -145,6 +145,7 @@ def get_rand_amount():
class ImportRescanTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 2 + len(IMPORT_NODES)
+ self.supports_cli = False
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
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 efa6a199ad..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):
@@ -127,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/functional/wallet_multiwallet.py b/test/functional/wallet_multiwallet.py
index ce0b7e8782..85d900f6cc 100755
--- a/test/functional/wallet_multiwallet.py
+++ b/test/functional/wallet_multiwallet.py
@@ -24,7 +24,6 @@ class MultiWalletTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
self.num_nodes = 2
- self.supports_cli = True
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
diff --git a/test/functional/wallet_txn_clone.py b/test/functional/wallet_txn_clone.py
index 60d7205887..99559090ee 100755
--- a/test/functional/wallet_txn_clone.py
+++ b/test/functional/wallet_txn_clone.py
@@ -16,6 +16,7 @@ from test_framework.messages import CTransaction, COIN
class TxnMallTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 4
+ self.supports_cli = False
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
diff --git a/test/functional/wallet_txn_doublespend.py b/test/functional/wallet_txn_doublespend.py
index 40eeb4048c..1891cd9190 100755
--- a/test/functional/wallet_txn_doublespend.py
+++ b/test/functional/wallet_txn_doublespend.py
@@ -16,6 +16,7 @@ from test_framework.util import (
class TxnMallTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 4
+ self.supports_cli = False
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
diff --git a/test/functional/wallet_watchonly.py b/test/functional/wallet_watchonly.py
index be8d7714fb..b0c41b2738 100755
--- a/test/functional/wallet_watchonly.py
+++ b/test/functional/wallet_watchonly.py
@@ -16,7 +16,6 @@ class CreateWalletWatchonlyTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = False
self.num_nodes = 1
- self.supports_cli = True
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
diff --git a/test/fuzz/test_runner.py b/test/fuzz/test_runner.py
index fde99fe496..2d255c0bb4 100755
--- a/test/fuzz/test_runner.py
+++ b/test/fuzz/test_runner.py
@@ -12,6 +12,34 @@ import sys
import subprocess
import logging
+# Fuzzers known to lack a seed corpus in https://github.com/bitcoin-core/qa-assets/tree/master/fuzz_seed_corpus
+FUZZERS_MISSING_CORPORA = [
+ "addr_info_deserialize",
+ "block_file_info_deserialize",
+ "block_filter_deserialize",
+ "block_header_and_short_txids_deserialize",
+ "fee_rate_deserialize",
+ "flat_file_pos_deserialize",
+ "integer",
+ "key_origin_info_deserialize",
+ "merkle_block_deserialize",
+ "out_point_deserialize",
+ "parse_hd_keypath",
+ "parse_numbers",
+ "parse_script",
+ "parse_univalue",
+ "partial_merkle_tree_deserialize",
+ "partially_signed_transaction_deserialize",
+ "prefilled_transaction_deserialize",
+ "psbt_input_deserialize",
+ "psbt_output_deserialize",
+ "pub_key_deserialize",
+ "script_deserialize",
+ "sub_net_deserialize",
+ "tx_in",
+ "tx_in_deserialize",
+ "tx_out",
+]
def main():
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
@@ -100,10 +128,14 @@ def main():
def run_once(*, corpus, test_list, build_dir, export_coverage):
for t in test_list:
+ corpus_path = os.path.join(corpus, t)
+ if t in FUZZERS_MISSING_CORPORA:
+ os.makedirs(corpus_path, exist_ok=True)
args = [
os.path.join(build_dir, 'src', 'test', 'fuzz', t),
'-runs=1',
- os.path.join(corpus, t),
+ '-detect_leaks=0',
+ corpus_path,
]
logging.debug('Run {} with args {}'.format(t, args))
result = subprocess.run(args, 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-locale-dependence.sh b/test/lint/lint-locale-dependence.sh
index 9a1aa766f7..ea9ea7a58d 100755
--- a/test/lint/lint-locale-dependence.sh
+++ b/test/lint/lint-locale-dependence.sh
@@ -11,6 +11,7 @@ KNOWN_VIOLATIONS=(
"src/qt/rpcconsole.cpp:.*atoi"
"src/rest.cpp:.*strtol"
"src/test/dbwrapper_tests.cpp:.*snprintf"
+ "src/test/fuzz/parse_numbers.cpp:.*atoi"
"src/torcontrol.cpp:.*atoi"
"src/torcontrol.cpp:.*strtol"
"src/util/strencodings.cpp:.*atoi"
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/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/*