aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.appveyor.yml65
-rw-r--r--.github/PULL_REQUEST_TEMPLATE.md31
-rw-r--r--.travis.yml2
-rwxr-xr-x.travis/lint_04_install.sh4
-rw-r--r--Makefile.am4
-rw-r--r--appveyor.yml45
-rw-r--r--build_msvc/common.vcxproj5
-rw-r--r--build_msvc/test_bitcoin/test_bitcoin.vcxproj2
-rw-r--r--configure.ac32
-rwxr-xr-xcontrib/gitian-build.py6
-rw-r--r--depends/README.md27
-rw-r--r--depends/packages/freetype.mk2
-rw-r--r--depends/packages/qt.mk2
-rw-r--r--doc/build-unix.md8
-rw-r--r--doc/build-windows.md2
-rw-r--r--doc/developer-notes.md4
-rw-r--r--doc/init.md2
-rw-r--r--doc/man/Makefile.am8
-rw-r--r--doc/release-notes-14282.md6
-rw-r--r--doc/release-notes/release-notes-0.14.3.md118
-rw-r--r--doc/release-notes/release-notes-0.15.2.md118
-rw-r--r--doc/release-notes/release-notes-0.17.0.md1105
-rw-r--r--doc/release-process.md2
-rw-r--r--src/Makefile.am9
-rw-r--r--src/Makefile.test.include12
-rw-r--r--src/addrman.h53
-rw-r--r--src/amount.h1
-rw-r--r--src/arith_uint256.cpp2
-rw-r--r--src/bench/ccoins_caching.cpp16
-rw-r--r--src/bench/checkblock.cpp4
-rw-r--r--src/bitcoin-cli.cpp5
-rw-r--r--src/bitcoin-tx.cpp11
-rw-r--r--src/bitcoind.cpp4
-rw-r--r--src/chainparams.cpp67
-rw-r--r--src/chainparams.h8
-rw-r--r--src/chainparamsbase.cpp1
-rw-r--r--src/core_io.h11
-rw-r--r--src/core_read.cpp9
-rw-r--r--src/fs.cpp102
-rw-r--r--src/fs.h52
-rw-r--r--src/init.cpp36
-rw-r--r--src/net.cpp491
-rw-r--r--src/net.h8
-rw-r--r--src/net_processing.cpp7
-rw-r--r--src/net_processing.h7
-rw-r--r--src/netbase.cpp26
-rw-r--r--src/policy/fees.h6
-rw-r--r--src/primitives/transaction.h2
-rw-r--r--src/qt/README.md4
-rw-r--r--src/qt/bitcoin.cpp12
-rw-r--r--src/qt/bitcoingui.cpp16
-rw-r--r--src/qt/clientmodel.cpp5
-rw-r--r--src/qt/clientmodel.h1
-rw-r--r--src/qt/forms/debugwindow.ui68
-rw-r--r--src/qt/guiutil.cpp12
-rw-r--r--src/qt/rpcconsole.cpp5
-rw-r--r--src/qt/transactionview.cpp6
-rw-r--r--src/rest.cpp40
-rw-r--r--src/rpc/blockchain.cpp46
-rw-r--r--src/rpc/mining.cpp18
-rw-r--r--src/rpc/misc.cpp8
-rw-r--r--src/rpc/protocol.cpp10
-rw-r--r--src/rpc/rawtransaction.cpp22
-rw-r--r--src/rpc/server.cpp12
-rw-r--r--src/script/ismine.cpp14
-rw-r--r--src/script/sign.cpp17
-rw-r--r--src/test/addrman_tests.cpp4
-rw-r--r--src/test/blockfilter_tests.cpp9
-rw-r--r--src/test/fs_tests.cpp56
-rw-r--r--src/test/script_tests.cpp8
-rw-r--r--src/test/test_bitcoin.cpp7
-rw-r--r--src/test/test_bitcoin.h2
-rw-r--r--src/txmempool.h14
-rw-r--r--src/util.cpp40
-rw-r--r--src/util.h16
-rw-r--r--src/utilmoneystr.cpp2
-rw-r--r--src/versionbits.cpp15
-rw-r--r--src/versionbits.h9
-rw-r--r--src/versionbitsinfo.cpp22
-rw-r--r--src/versionbitsinfo.h17
-rw-r--r--src/wallet/coinselection.h2
-rw-r--r--src/wallet/init.cpp7
-rw-r--r--src/wallet/rpcdump.cpp12
-rw-r--r--src/wallet/rpcwallet.cpp52
-rw-r--r--src/wallet/test/init_test_fixture.cpp42
-rw-r--r--src/wallet/test/init_test_fixture.h21
-rw-r--r--src/wallet/test/init_tests.cpp78
-rw-r--r--src/wallet/wallet.cpp16
-rw-r--r--test/config.ini.in2
-rw-r--r--test/functional/README.md7
-rwxr-xr-xtest/functional/combine_logs.py4
-rwxr-xr-xtest/functional/feature_block.py2
-rwxr-xr-xtest/functional/feature_config_args.py10
-rwxr-xr-xtest/functional/feature_notifications.py82
-rwxr-xr-xtest/functional/feature_uacomment.py2
-rwxr-xr-xtest/functional/interface_bitcoin_cli.py32
-rwxr-xr-xtest/functional/interface_zmq.py40
-rwxr-xr-xtest/functional/mining_prioritisetransaction.py3
-rwxr-xr-xtest/functional/p2p_compactblocks.py2
-rwxr-xr-xtest/functional/p2p_segwit.py14
-rwxr-xr-xtest/functional/p2p_sendheaders.py2
-rwxr-xr-xtest/functional/rpc_blockchain.py8
-rwxr-xr-xtest/functional/rpc_rawtransaction.py12
-rwxr-xr-xtest/functional/rpc_signrawtransaction.py9
-rwxr-xr-xtest/functional/rpc_txoutproof.py8
-rwxr-xr-xtest/functional/rpc_zmq.py37
-rw-r--r--test/functional/test_framework/address.py3
-rw-r--r--test/functional/test_framework/authproxy.py26
-rwxr-xr-xtest/functional/test_framework/messages.py173
-rw-r--r--test/functional/test_framework/script.py9
-rwxr-xr-xtest/functional/test_framework/test_framework.py8
-rwxr-xr-xtest/functional/test_framework/test_node.py4
-rwxr-xr-xtest/functional/test_runner.py45
-rwxr-xr-xtest/functional/wallet_basic.py8
-rwxr-xr-xtest/functional/wallet_hd.py6
-rwxr-xr-xtest/functional/wallet_listsinceblock.py4
-rwxr-xr-xtest/functional/wallet_multiwallet.py17
-rwxr-xr-xtest/lint/check-doc.py2
-rwxr-xr-xtest/lint/lint-includes.sh1
-rwxr-xr-xtest/lint/lint-python.sh2
-rw-r--r--test/lint/lint-spelling.ignore-words.txt1
-rwxr-xr-xtest/lint/lint-spelling.sh3
-rw-r--r--test/util/data/bitcoin-util-test.json60
123 files changed, 3049 insertions, 916 deletions
diff --git a/.appveyor.yml b/.appveyor.yml
new file mode 100644
index 0000000000..ff84c01a39
--- /dev/null
+++ b/.appveyor.yml
@@ -0,0 +1,65 @@
+version: '{branch}.{build}'
+skip_tags: true
+image: Visual Studio 2017
+configuration: Release
+platform: x64
+environment:
+ APPVEYOR_SAVE_CACHE_ON_ERROR: true
+ CLCACHE_SERVER: 1
+ PACKAGES: boost-filesystem boost-signals2 boost-test libevent openssl zeromq berkeleydb secp256k1 leveldb
+ PYTHONIOENCODING: utf-8
+cache:
+- C:\tools\vcpkg\installed
+- C:\Users\appveyor\clcache
+init:
+- cmd: set PATH=C:\Python36-x64;C:\Python36-x64\Scripts;%PATH%
+install:
+- cmd: pip install git+https://github.com/frerich/clcache.git
+# Disable zmq test for now since python zmq library on Windows would cause Access violation sometimes.
+# - cmd: pip install zmq
+- ps: $packages = $env:PACKAGES -Split ' '
+- ps: for ($i=0; $i -lt $packages.length; $i++) {
+ $env:ALL_PACKAGES += $packages[$i] + ":" + $env:PLATFORM + "-windows-static "
+ }
+- cmd: git -C C:\Tools\vcpkg pull # This is a temporary fix, can be removed after appveyor update its image to include Microsoft/vcpkg#4046
+- cmd: C:\Tools\vcpkg\bootstrap-vcpkg.bat
+- cmd: vcpkg remove --recurse --outdated
+- cmd: vcpkg install %ALL_PACKAGES%
+- cmd: del /s /q C:\Tools\vcpkg\installed\%PLATFORM%-windows-static\debug # Remove unused debug library
+before_build:
+- ps: clcache -M 536870912
+- cmd: python build_msvc\msvc-autogen.py
+- ps: $files = (Get-ChildItem -Recurse | where {$_.extension -eq ".vcxproj"}).FullName
+- ps: for (${i} = 0; ${i} -lt ${files}.length; ${i}++) {
+ ${content} = (Get-Content ${files}[${i}]);
+ ${content} = ${content}.Replace("</RuntimeLibrary>", "</RuntimeLibrary><DebugInformationFormat>None</DebugInformationFormat>");
+ ${content} = ${content}.Replace("<WholeProgramOptimization>true", "<WholeProgramOptimization>false");
+ ${content} = ${content}.Replace("NDEBUG;", "");
+ Set-Content ${files}[${i}] ${content};
+ }
+- ps: Start-Process clcache-server
+- ps: fsutil behavior set disablelastaccess 0 # Enable Access time feature on Windows (for clcache)
+build_script:
+- cmd: msbuild /p:TrackFileAccess=false /p:CLToolExe=clcache.exe build_msvc\bitcoin.sln /m /v:q /nowarn:C4244;C4267;C4715 /nologo
+after_build:
+- ps: fsutil behavior set disablelastaccess 0 # Disable Access time feature on Windows (better performance)
+- ps: clcache -z
+before_test:
+- ps: ${conf_ini} = (Get-Content([IO.Path]::Combine(${env:APPVEYOR_BUILD_FOLDER}, "test", "config.ini.in")))
+- ps: ${conf_ini} = ${conf_ini}.Replace("@abs_top_srcdir@", ${env:APPVEYOR_BUILD_FOLDER})
+- ps: ${conf_ini} = ${conf_ini}.Replace("@abs_top_builddir@", ${env:APPVEYOR_BUILD_FOLDER})
+- ps: ${conf_ini} = ${conf_ini}.Replace("@EXEEXT@", ".exe")
+- ps: ${conf_ini} = ${conf_ini}.Replace("@ENABLE_WALLET_TRUE@", "")
+- ps: ${conf_ini} = ${conf_ini}.Replace("@BUILD_BITCOIN_CLI_TRUE@", "")
+- ps: ${conf_ini} = ${conf_ini}.Replace("@BUILD_BITCOIND_TRUE@", "")
+- ps: ${conf_ini} = ${conf_ini}.Replace("@ENABLE_ZMQ_TRUE@", "")
+- ps: ${utf8} = New-Object System.Text.UTF8Encoding ${false}
+- ps: '[IO.File]::WriteAllLines([IO.Path]::Combine(${env:APPVEYOR_BUILD_FOLDER}, "test", "config.ini"), ${conf_ini}, ${utf8})'
+- ps: move "build_msvc\${env:PLATFORM}\${env:CONFIGURATION}\*.exe" src
+test_script:
+- cmd: src\test_bitcoin.exe
+- ps: src\bench_bitcoin.exe -evals=1 -scaling=0
+- ps: python test\util\bitcoin-util-test.py
+- cmd: python test\util\rpcauth-test.py
+- cmd: python test\functional\test_runner.py --force --quiet --combinedlogslen=4000 --exclude wallet_multiwallet
+deploy: off
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
new file mode 100644
index 0000000000..00d5478c4e
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -0,0 +1,31 @@
+Pull requests without a rationale and clear improvement may be closed
+immediately.
+
+Please provide clear motivation for your patch and explain how it improves
+Bitcoin Core user experience or Bitcoin Core developer experience
+significantly.
+
+* Any test improvements or new tests that improve coverage are always welcome.
+* All other changes should have accompanying unit tests (see `src/test/`) or
+ functional tests (see `test/`). Contributors should note which tests cover
+ modified code. If no tests exist for a region of modified code, new tests
+ should accompany the change.
+* Bug fixes are most welcome when they come with steps to reproduce or an
+ explanation of the potential issue as well as reasoning for the way the bug
+ was fixed.
+* Features are welcome, but might be rejected due to design or scope issues.
+ If a feature is based on a lot of dependencies, contributors should first
+ consider building the system outside of Bitcoin Core, if possible.
+* Refactoring changes are only accepted if they are required for a feature or
+ bug fix or otherwise improve developer experience significantly. For example,
+ most "code style" refactoring changes require a thorough explanation why they
+ are useful, what downsides they have and why they *significantly* improve
+ developer experience or avoid serious programming bugs. Note that code style
+ is often a subjective matter. Unless they are explicitly mentioned to be
+ preferred in the [developer notes](/doc/developer-notes.md), stylistic code
+ changes are usually rejected.
+
+Bitcoin Core has a thorough review process and even the most trivial change
+needs to pass a lot of eyes and requires non-zero or even substantial time
+effort to review. There is a huge lack of active reviewers on the project, so
+patches often sit for a long time.
diff --git a/.travis.yml b/.travis.yml
index 8819d38914..647d117733 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -121,7 +121,7 @@ jobs:
- stage: test
env: >-
HOST=x86_64-unknown-linux-gnu
- PACKAGES="python3"
+ PACKAGES="python3-zmq"
DEP_OPTS="NO_WALLET=1"
GOAL="install"
BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports"
diff --git a/.travis/lint_04_install.sh b/.travis/lint_04_install.sh
index 3a6ff73d79..8c3a9124b9 100755
--- a/.travis/lint_04_install.sh
+++ b/.travis/lint_04_install.sh
@@ -6,5 +6,5 @@
export LC_ALL=C
-travis_retry pip install codespell
-travis_retry pip install flake8
+travis_retry pip install codespell==1.13.0
+travis_retry pip install flake8==3.5.0
diff --git a/Makefile.am b/Makefile.am
index 10dda65b21..7eb4ea2f52 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -168,7 +168,7 @@ $(BITCOIN_CLI_BIN): FORCE
$(MAKE) -C src $(@F)
if USE_LCOV
-LCOV_FILTER_PATTERN=-p "/usr/include/" -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 "src/leveldb/" -p "src/bench/" -p "src/univalue" -p "src/crypto/ctaes" -p "src/secp256k1"
baseline.info:
$(LCOV) -c -i -d $(abs_builddir)/src -o $@
@@ -294,5 +294,5 @@ clean-docs:
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
+ rm -rf test/functional/__pycache__ test/functional/test_framework/__pycache__ test/cache share/rpcauth/__pycache__
diff --git a/appveyor.yml b/appveyor.yml
deleted file mode 100644
index 99e7b9510b..0000000000
--- a/appveyor.yml
+++ /dev/null
@@ -1,45 +0,0 @@
-version: '{branch}.{build}'
-skip_tags: true
-image: Visual Studio 2017
-configuration: Release
-platform: x64
-environment:
- APPVEYOR_SAVE_CACHE_ON_ERROR: true
- CLCACHE_SERVER: 1
- PACKAGES: boost-filesystem boost-signals2 boost-interprocess boost-test libevent openssl zeromq berkeleydb secp256k1 leveldb
-cache:
-- C:\tools\vcpkg\installed
-- C:\Users\appveyor\clcache
-- build_msvc\cache
-init:
-- cmd: set PATH=C:\Python36-x64;C:\Python36-x64\Scripts;%PATH%
-install:
-- cmd: pip install git+https://github.com/frerich/clcache.git
-- ps: $packages = $env:PACKAGES -Split ' '
-- ps: for ($i=0; $i -lt $packages.length; $i++) {
- $env:ALL_PACKAGES += $packages[$i] + ":" + $env:PLATFORM + "-windows-static "
- }
-- cmd: git -C C:\Tools\vcpkg pull # This is a temporary fix, can be removed after appveyor update its image to include Microsoft/vcpkg#4046
-- cmd: vcpkg install %ALL_PACKAGES%
-- cmd: vcpkg upgrade --no-dry-run
-- cmd: del /s /q C:\Tools\vcpkg\installed\%PLATFORM%-windows-static\debug # Remove unused debug library
-before_build:
-- cmd: if not exist build_msvc\cache\ (del build_msvc\cache & mkdir build_msvc\cache)
-- cmd: if not exist build_msvc\%PLATFORM%\%CONFIGURATION%\ (mkdir build_msvc\%PLATFORM%\%CONFIGURATION%)
-- cmd: if exist build_msvc\cache\*.iobj (move build_msvc\cache\* build_msvc\%PLATFORM%\%CONFIGURATION%\)
-- cmd: clcache -M 2147483648
-- cmd: python build_msvc\msvc-autogen.py
-- ps: $files = (Get-ChildItem -Recurse | where {$_.extension -eq ".vcxproj"}).FullName
-- ps: for ($i = 0; $i -lt $files.length; $i++) {
- (Get-Content $files[$i]).Replace("</RuntimeLibrary>", "</RuntimeLibrary><DebugInformationFormat>None</DebugInformationFormat>").Replace("NDEBUG;", "") | Set-Content $files[$i]
- }
-- ps: Start-Process clcache-server
-build_script:
-- cmd: msbuild /p:TrackFileAccess=false /p:CLToolExe=clcache.exe build_msvc\bitcoin.sln /m /v:q /nowarn:C4244;C4267;C4715 /nologo
-after_build:
-- cmd: move build_msvc\%PLATFORM%\%CONFIGURATION%\*.iobj build_msvc\cache\
-- cmd: move build_msvc\%PLATFORM%\%CONFIGURATION%\*.ipdb build_msvc\cache\
-- cmd: del C:\Users\appveyor\clcache\stats.txt
-test_script:
-- cmd: build_msvc\%PLATFORM%\%CONFIGURATION%\test_bitcoin.exe
-deploy: off
diff --git a/build_msvc/common.vcxproj b/build_msvc/common.vcxproj
index 3a53f3bad3..5c87026efe 100644
--- a/build_msvc/common.vcxproj
+++ b/build_msvc/common.vcxproj
@@ -12,4 +12,9 @@
Outputs="$(MSBuildThisFileDirectory)..\src\config\bitcoin-config.h">
<Copy SourceFiles="$(MSBuildThisFileDirectory)bitcoin_config.h" DestinationFiles="$(MSBuildThisFileDirectory)..\src\config\bitcoin-config.h" />
</Target>
+ <ItemDefinitionGroup>
+ <ClCompile>
+ <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
+ </ClCompile>
+ </ItemDefinitionGroup>
</Project> \ No newline at end of file
diff --git a/build_msvc/test_bitcoin/test_bitcoin.vcxproj b/build_msvc/test_bitcoin/test_bitcoin.vcxproj
index 444a2ed725..2316e473aa 100644
--- a/build_msvc/test_bitcoin/test_bitcoin.vcxproj
+++ b/build_msvc/test_bitcoin/test_bitcoin.vcxproj
@@ -24,7 +24,7 @@
<ClCompile Include="..\..\src\wallet\test\*_tests.cpp" />
<ClCompile Include="..\..\src\test\test_bitcoin.cpp" />
<ClCompile Include="..\..\src\test\test_bitcoin_main.cpp" />
- <ClCompile Include="..\..\src\wallet\test\wallet_test_fixture.cpp" />
+ <ClCompile Include="..\..\src\wallet\test\*_fixture.cpp" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\libbitcoinconsensus\libbitcoinconsensus.vcxproj">
diff --git a/configure.ac b/configure.ac
index 4d84aacce1..72bd785e2e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -406,6 +406,18 @@ AC_ARG_WITH([utils],
[build_bitcoin_utils=$withval],
[build_bitcoin_utils=yes])
+AC_ARG_ENABLE([util-cli],
+ [AS_HELP_STRING([--enable-util-cli],
+ [build bitcoin-cli])],
+ [build_bitcoin_cli=$enableval],
+ [build_bitcoin_cli=$build_bitcoin_utils])
+
+AC_ARG_ENABLE([util-tx],
+ [AS_HELP_STRING([--enable-util-tx],
+ [build bitcoin-tx])],
+ [build_bitcoin_tx=$enableval],
+ [build_bitcoin_tx=$build_bitcoin_utils])
+
AC_ARG_WITH([libs],
[AS_HELP_STRING([--with-libs],
[build libraries (default=yes)])],
@@ -886,7 +898,7 @@ BITCOIN_QT_INIT
dnl sets $bitcoin_enable_qt, $bitcoin_enable_qt_test, $bitcoin_enable_qt_dbus
BITCOIN_QT_CONFIGURE([$use_pkgconfig])
-if test x$build_bitcoin_utils$build_bitcoind$bitcoin_enable_qt$use_tests$use_bench = xnonononono; then
+if test x$build_bitcoin_cli$build_bitcoin_tx$build_bitcoind$bitcoin_enable_qt$use_tests$use_bench = xnononononono; then
use_boost=no
else
use_boost=yes
@@ -1074,7 +1086,7 @@ if test x$use_pkgconfig = xyes; then
if test x$use_qr != xno; then
BITCOIN_QT_CHECK([PKG_CHECK_MODULES([QR], [libqrencode], [have_qrencode=yes], [have_qrencode=no])])
fi
- if test x$build_bitcoin_utils$build_bitcoind$bitcoin_enable_qt$use_tests != xnononono; then
+ if test x$build_bitcoin_cli$build_bitcoin_tx$build_bitcoind$bitcoin_enable_qt$use_tests != xnonononono; then
PKG_CHECK_MODULES([EVENT], [libevent],, [AC_MSG_ERROR(libevent not found.)])
if test x$TARGET_OS != xwindows; then
PKG_CHECK_MODULES([EVENT_PTHREADS], [libevent_pthreads],, [AC_MSG_ERROR(libevent_pthreads not found.)])
@@ -1099,7 +1111,7 @@ else
AC_CHECK_HEADER([openssl/ssl.h],, AC_MSG_ERROR(libssl headers missing),)
AC_CHECK_LIB([ssl], [main],SSL_LIBS=-lssl, AC_MSG_ERROR(libssl missing))
- if test x$build_bitcoin_utils$build_bitcoind$bitcoin_enable_qt$use_tests != xnononono; then
+ if test x$build_bitcoin_cli$build_bitcoin_tx$build_bitcoind$bitcoin_enable_qt$use_tests != xnonononono; then
AC_CHECK_HEADER([event2/event.h],, AC_MSG_ERROR(libevent headers missing),)
AC_CHECK_LIB([event],[main],EVENT_LIBS=-levent,AC_MSG_ERROR(libevent missing))
if test x$TARGET_OS != xwindows; then
@@ -1164,7 +1176,7 @@ dnl univalue check
need_bundled_univalue=yes
-if test x$build_bitcoin_utils$build_bitcoind$bitcoin_enable_qt$use_tests$use_bench = xnonononono; then
+if test x$build_bitcoin_cli$build_bitcoin_tx$build_bitcoind$bitcoin_enable_qt$use_tests$use_bench = xnononononono; then
need_bundled_univalue=no
else
@@ -1214,9 +1226,13 @@ AC_MSG_CHECKING([whether to build bitcoind])
AM_CONDITIONAL([BUILD_BITCOIND], [test x$build_bitcoind = xyes])
AC_MSG_RESULT($build_bitcoind)
-AC_MSG_CHECKING([whether to build utils (bitcoin-cli bitcoin-tx)])
-AM_CONDITIONAL([BUILD_BITCOIN_UTILS], [test x$build_bitcoin_utils = xyes])
-AC_MSG_RESULT($build_bitcoin_utils)
+AC_MSG_CHECKING([whether to build bitcoin-cli])
+AM_CONDITIONAL([BUILD_BITCOIN_CLI], [test x$build_bitcoin_cli = xyes])
+AC_MSG_RESULT($build_bitcoin_cli)
+
+AC_MSG_CHECKING([whether to build bitcoin-tx])
+AM_CONDITIONAL([BUILD_BITCOIN_TX], [test x$build_bitcoin_tx = xyes])
+AC_MSG_RESULT($build_bitcoin_tx)
AC_MSG_CHECKING([whether to build libraries])
AM_CONDITIONAL([BUILD_BITCOIN_LIBS], [test x$build_bitcoin_libs = xyes])
@@ -1342,7 +1358,7 @@ else
AC_MSG_RESULT([no])
fi
-if test x$build_bitcoin_utils$build_bitcoin_libs$build_bitcoind$bitcoin_enable_qt$use_bench$use_tests = xnononononono; then
+if test x$build_bitcoin_cli$build_bitcoin_tx$build_bitcoin_libs$build_bitcoind$bitcoin_enable_qt$use_bench$use_tests = xnonononononono; then
AC_MSG_ERROR([No targets! Please specify at least one of: --with-utils --with-libs --with-daemon --with-gui --enable-bench or --enable-tests])
fi
diff --git a/contrib/gitian-build.py b/contrib/gitian-build.py
index 2e8c99247d..faf8b014aa 100755
--- a/contrib/gitian-build.py
+++ b/contrib/gitian-build.py
@@ -65,14 +65,14 @@ def build():
print('\nCompiling ' + args.version + ' Windows')
subprocess.check_call(['bin/gbuild', '-j', args.jobs, '-m', args.memory, '--commit', 'bitcoin='+args.commit, '--url', 'bitcoin='+args.url, '../bitcoin/contrib/gitian-descriptors/gitian-win.yml'])
subprocess.check_call(['bin/gsign', '-p', args.sign_prog, '--signer', args.signer, '--release', args.version+'-win-unsigned', '--destination', '../gitian.sigs/', '../bitcoin/contrib/gitian-descriptors/gitian-win.yml'])
- subprocess.check_call('mv build/out/bitcoin-*-win-unsigned.tar.gz inputs/bitcoin-win-unsigned.tar.gz', shell=True)
+ subprocess.check_call('mv build/out/bitcoin-*-win-unsigned.tar.gz inputs/', shell=True)
subprocess.check_call('mv build/out/bitcoin-*.zip build/out/bitcoin-*.exe ../bitcoin-binaries/'+args.version, shell=True)
if args.macos:
print('\nCompiling ' + args.version + ' MacOS')
subprocess.check_call(['bin/gbuild', '-j', args.jobs, '-m', args.memory, '--commit', 'bitcoin='+args.commit, '--url', 'bitcoin='+args.url, '../bitcoin/contrib/gitian-descriptors/gitian-osx.yml'])
subprocess.check_call(['bin/gsign', '-p', args.sign_prog, '--signer', args.signer, '--release', args.version+'-osx-unsigned', '--destination', '../gitian.sigs/', '../bitcoin/contrib/gitian-descriptors/gitian-osx.yml'])
- subprocess.check_call('mv build/out/bitcoin-*-osx-unsigned.tar.gz inputs/bitcoin-osx-unsigned.tar.gz', shell=True)
+ subprocess.check_call('mv build/out/bitcoin-*-osx-unsigned.tar.gz inputs/', shell=True)
subprocess.check_call('mv build/out/bitcoin-*.tar.gz build/out/bitcoin-*.dmg ../bitcoin-binaries/'+args.version, shell=True)
os.chdir(workdir)
@@ -92,6 +92,7 @@ def sign():
if args.windows:
print('\nSigning ' + args.version + ' Windows')
+ subprocess.check_call('cp inputs/bitcoin-' + args.version + '-win-unsigned.tar.gz inputs/bitcoin-win-unsigned.tar.gz', shell=True)
subprocess.check_call(['bin/gbuild', '-i', '--commit', 'signature='+args.commit, '../bitcoin/contrib/gitian-descriptors/gitian-win-signer.yml'])
subprocess.check_call(['bin/gsign', '-p', args.sign_prog, '--signer', args.signer, '--release', args.version+'-win-signed', '--destination', '../gitian.sigs/', '../bitcoin/contrib/gitian-descriptors/gitian-win-signer.yml'])
subprocess.check_call('mv build/out/bitcoin-*win64-setup.exe ../bitcoin-binaries/'+args.version, shell=True)
@@ -99,6 +100,7 @@ def sign():
if args.macos:
print('\nSigning ' + args.version + ' MacOS')
+ subprocess.check_call('cp inputs/bitcoin-' + args.version + '-osx-unsigned.tar.gz inputs/bitcoin-osx-unsigned.tar.gz', shell=True)
subprocess.check_call(['bin/gbuild', '-i', '--commit', 'signature='+args.commit, '../bitcoin/contrib/gitian-descriptors/gitian-osx-signer.yml'])
subprocess.check_call(['bin/gsign', '-p', args.sign_prog, '--signer', args.signer, '--release', args.version+'-osx-signed', '--destination', '../gitian.sigs/', '../bitcoin/contrib/gitian-descriptors/gitian-osx-signer.yml'])
subprocess.check_call('mv build/out/bitcoin-osx-signed.dmg ../bitcoin-binaries/'+args.version+'/bitcoin-'+args.version+'-osx.dmg', shell=True)
diff --git a/depends/README.md b/depends/README.md
index 73bfc8b726..693bc36197 100644
--- a/depends/README.md
+++ b/depends/README.md
@@ -30,29 +30,38 @@ Common `host-platform-triplets` for cross compilation are:
No other options are needed, the paths are automatically configured.
-Install the required dependencies: Ubuntu & Debian
---------------------------------------------------
+### Install the required dependencies: Ubuntu & Debian
-For macOS cross compilation:
+#### For macOS cross compilation
sudo apt-get install curl librsvg2-bin libtiff-tools bsdmainutils cmake imagemagick libcap-dev libz-dev libbz2-dev python-setuptools
-For Win32/Win64 cross compilation:
+#### For Win32/Win64 cross compilation
- see [build-windows.md](../doc/build-windows.md#cross-compilation-for-ubuntu-and-windows-subsystem-for-linux)
-For linux (including i386, ARM) cross compilation:
+#### For linux (including i386, ARM) cross compilation
- sudo apt-get install curl g++-aarch64-linux-gnu g++-4.8-aarch64-linux-gnu gcc-4.8-aarch64-linux-gnu binutils-aarch64-linux-gnu g++-arm-linux-gnueabihf g++-4.8-arm-linux-gnueabihf gcc-4.8-arm-linux-gnueabihf binutils-arm-linux-gnueabihf g++-4.8-multilib gcc-4.8-multilib binutils-gold bsdmainutils
+Common linux dependencies:
+
+ sudo apt-get install make automake cmake curl g++-multilib libtool binutils-gold bsdmainutils pkg-config python3
+
+For linux ARM cross compilation:
+
+ sudo apt-get install g++-arm-linux-gnueabihf binutils-arm-linux-gnueabihf
+
+For linux AARCH64 cross compilation:
+
+ sudo apt-get install g++-aarch64-linux-gnu binutils-aarch64-linux-gnu
For linux RISC-V 64-bit cross compilation (there are no packages for 32-bit):
- sudo apt-get install curl g++-riscv64-linux-gnu binutils-riscv64-linux-gnu
+ sudo apt-get install g++-riscv64-linux-gnu binutils-riscv64-linux-gnu
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.
-Dependency Options:
+### Dependency Options
The following can be set when running make: make FOO=bar
SOURCES_PATH: downloaded sources will be placed here
@@ -70,7 +79,7 @@ The following can be set when running make: make FOO=bar
If some packages are not built, for example `make NO_WALLET=1`, the appropriate
options will be passed to bitcoin's configure. In this case, `--disable-wallet`.
-Additional targets:
+### Additional targets
download: run 'make download' to fetch all sources without building them
download-osx: run 'make download-osx' to fetch all sources needed for macOS builds
diff --git a/depends/packages/freetype.mk b/depends/packages/freetype.mk
index 76b025c463..41e02e2030 100644
--- a/depends/packages/freetype.mk
+++ b/depends/packages/freetype.mk
@@ -5,7 +5,7 @@ $(package)_file_name=$(package)-$($(package)_version).tar.bz2
$(package)_sha256_hash=3a3bb2c4e15ffb433f2032f50a5b5a92558206822e22bfe8cbe339af4aa82f88
define $(package)_set_vars
- $(package)_config_opts=--without-zlib --without-png --disable-static
+ $(package)_config_opts=--without-zlib --without-png --without-harfbuzz --without-bzip2 --disable-static
$(package)_config_opts_linux=--with-pic
endef
diff --git a/depends/packages/qt.mk b/depends/packages/qt.mk
index 5286f89c30..dc1d17cd57 100644
--- a/depends/packages/qt.mk
+++ b/depends/packages/qt.mk
@@ -64,6 +64,7 @@ $(package)_config_opts += -prefix $(host_prefix)
$(package)_config_opts += -qt-libpng
$(package)_config_opts += -qt-libjpeg
$(package)_config_opts += -qt-pcre
+$(package)_config_opts += -qt-harfbuzz
$(package)_config_opts += -system-zlib
$(package)_config_opts += -static
$(package)_config_opts += -silent
@@ -120,6 +121,7 @@ define $(package)_extract_cmds
endef
define $(package)_preprocess_cmds
+ sed -i.old "s|FT_Get_Font_Format|FT_Get_X11_Font_Format|" qtbase/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp && \
sed -i.old "s|updateqm.commands = \$$$$\$$$$LRELEASE|updateqm.commands = $($(package)_extract_dir)/qttools/bin/lrelease|" qttranslations/translations/translations.pro && \
sed -i.old "/updateqm.depends =/d" qttranslations/translations/translations.pro && \
sed -i.old "s/src_plugins.depends = src_sql src_network/src_plugins.depends = src_network/" qtbase/src/src.pro && \
diff --git a/doc/build-unix.md b/doc/build-unix.md
index 3f8848abf2..87dade42a3 100644
--- a/doc/build-unix.md
+++ b/doc/build-unix.md
@@ -70,7 +70,11 @@ tuned to conserve memory with additional CXXFLAGS:
Build requirements:
- sudo apt-get install build-essential libtool autotools-dev automake pkg-config libssl-dev libevent-dev bsdmainutils python3 libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-test-dev libboost-thread-dev
+ sudo apt-get install build-essential libtool autotools-dev automake pkg-config bsdmainutils python3
+
+Now, you can either build from self-compiled [depends](/depends/README.md) or install the required dependencies:
+
+ sudo apt-get install libssl-dev libevent-dev libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-test-dev libboost-thread-dev
BerkeleyDB is required for the wallet.
@@ -97,7 +101,7 @@ ZMQ dependencies (provides ZMQ API):
sudo apt-get install libzmq3-dev
-#### Dependencies for the GUI
+GUI dependencies:
If you want to build bitcoin-qt, make sure that the required packages for Qt development
are installed. Qt 5 is necessary to build the GUI.
diff --git a/doc/build-windows.md b/doc/build-windows.md
index 12adadacdc..8c4b79bebc 100644
--- a/doc/build-windows.md
+++ b/doc/build-windows.md
@@ -133,7 +133,7 @@ Installation
-------------
After building using the Windows subsystem it can be useful to copy the compiled
-executables to a directory on the windows drive in the same directory structure
+executables to a directory on the Windows drive in the same directory structure
as they appear in the release `.zip` archive. This can be done in the following
way. This will install to `c:\workspace\bitcoin`, for example:
diff --git a/doc/developer-notes.md b/doc/developer-notes.md
index 1d103d481b..c86648c5b8 100644
--- a/doc/developer-notes.md
+++ b/doc/developer-notes.md
@@ -705,10 +705,10 @@ Current subtrees include:
- Upstream at https://github.com/google/leveldb ; Maintained by Google, but
open important PRs to Core to avoid delay.
- **Note**: Follow the instructions in [Upgrading LevelDB](#upgrading-leveldb) when
- merging upstream changes to the leveldb subtree.
+ merging upstream changes to the LevelDB subtree.
- src/libsecp256k1
- - Upstream at https://github.com/bitcoin-core/secp256k1/ ; actively maintaned by Core contributors.
+ - Upstream at https://github.com/bitcoin-core/secp256k1/ ; actively maintained by Core contributors.
- src/crypto/ctaes
- Upstream at https://github.com/bitcoin-core/ctaes ; actively maintained by Core contributors.
diff --git a/doc/init.md b/doc/init.md
index 239b74e4e1..5778b09d05 100644
--- a/doc/init.md
+++ b/doc/init.md
@@ -22,7 +22,7 @@ Configuration
At a bare minimum, bitcoind requires that the rpcpassword setting be set
when running as a daemon. If the configuration file does not exist or this
-setting is not set, bitcoind will shutdown promptly after startup.
+setting is not set, bitcoind will shut down promptly after startup.
This password does not have to be remembered or typed as it is mostly used
as a fixed token that bitcoind and client programs read from the configuration
diff --git a/doc/man/Makefile.am b/doc/man/Makefile.am
index 08ff4d6ac1..9b36319e64 100644
--- a/doc/man/Makefile.am
+++ b/doc/man/Makefile.am
@@ -8,6 +8,10 @@ if ENABLE_QT
dist_man1_MANS+=bitcoin-qt.1
endif
-if BUILD_BITCOIN_UTILS
- dist_man1_MANS+=bitcoin-cli.1 bitcoin-tx.1
+if BUILD_BITCOIN_CLI
+ dist_man1_MANS+=bitcoin-cli.1
+endif
+
+if BUILD_BITCOIN_TX
+ dist_man1_MANS+=bitcoin-tx.1
endif
diff --git a/doc/release-notes-14282.md b/doc/release-notes-14282.md
new file mode 100644
index 0000000000..e6d8e0b70c
--- /dev/null
+++ b/doc/release-notes-14282.md
@@ -0,0 +1,6 @@
+Low-level RPC changes
+----------------------
+
+`-usehd` was removed in version 0.16. From that version onwards, all new
+wallets created are hierarchical deterministic wallets. Version 0.18 makes
+specifying `-usehd` invalid config.
diff --git a/doc/release-notes/release-notes-0.14.3.md b/doc/release-notes/release-notes-0.14.3.md
new file mode 100644
index 0000000000..8259152f0b
--- /dev/null
+++ b/doc/release-notes/release-notes-0.14.3.md
@@ -0,0 +1,118 @@
+Bitcoin Core version *0.14.3* is now available from:
+
+ <https://bitcoin.org/bin/bitcoin-core-0.14.3/>
+
+This is a new minor version release, including various bugfixes and
+performance improvements.
+
+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/>
+
+Compatibility
+==============
+
+Bitcoin Core is extensively tested on multiple operating systems using
+the Linux kernel, macOS 10.8+, and Windows Vista and later.
+
+Microsoft ended support for Windows XP on [April 8th, 2014](https://www.microsoft.com/en-us/WindowsForBusiness/end-of-xp-support),
+No attempt is made to prevent installing or running the software on Windows XP, you
+can still do so at your own risk but be aware that there are known instabilities and issues.
+Please do not report issues about Windows XP to the issue tracker.
+
+Bitcoin Core should also work on most other Unix-like systems but is not
+frequently tested on them.
+
+Notable changes
+===============
+
+Denial-of-Service vulnerability CVE-2018-17144
+ -------------------------------
+
+A denial-of-service vulnerability exploitable by miners has been discovered in
+Bitcoin Core versions 0.14.0 up to 0.16.2. It is recommended to upgrade any of
+the vulnerable versions to 0.14.3, 0.15.2 or 0.16.3 as soon as possible.
+
+Known Bugs
+==========
+
+Since 0.14.0 the approximate transaction fee shown in Bitcoin-Qt when using coin
+control and smart fee estimation does not reflect any change in target from the
+smart fee slider. It will only present an approximate fee calculated using the
+default target. The fee calculated using the correct target is still applied to
+the transaction and shown in the final send confirmation dialog.
+
+0.14.3 Change log
+=================
+
+Detailed release notes follow. This overview includes changes that affect
+behavior, not code moves, refactors and string updates. For convenience in locating
+the code changes and accompanying discussion, both the pull request and
+git merge commit are mentioned.
+
+### Consensus
+- #14247 `52965fb` Fix crash bug with duplicate inputs within a transaction (TheBlueMatt, sdaftuar)
+
+### RPC and other APIs
+
+- #10445 `87a21d5` Fix: make CCoinsViewDbCursor::Seek work for missing keys (Pieter Wuille, Gregory Maxwell)
+- #9853 Return correct error codes in setban(), fundrawtransaction(), removeprunedfunds(), bumpfee(), blockchain.cpp (John Newbery)
+
+
+### P2P protocol and network code
+
+- #10234 `d289b56` [net] listbanned RPC and QT should show correct banned subnets (John Newbery)
+
+### Build system
+
+
+### Miscellaneous
+
+- #10451 `3612219` contrib/init/bitcoind.openrcconf: Don't disable wallet by default (Luke Dashjr)
+- #10250 `e23cef0` Fix some empty vector references (Pieter Wuille)
+- #10196 `d28d583` PrioritiseTransaction updates the mempool tx counter (Suhas Daftuar)
+- #9497 `e207342` Fix CCheckQueue IsIdle (potential) race condition and remove dangerous constructors. (Jeremy Rubin)
+
+### GUI
+
+- #9481 `7abe7bb` Give fallback fee a reasonable indent (Luke Dashjr)
+- #9481 `3e4d7bf` Qt/Send: Figure a decent warning colour from theme (Luke Dashjr)
+- #9481 `e207342` Show more significant warning if we fall back to the default fee (Jonas Schnelli)
+
+### Wallet
+
+- #10308 `28b8b8b` Securely erase potentially sensitive keys/values (tjps)
+- #10265 `ff13f59` Make sure pindex is non-null before possibly referencing in LogPrintf call. (Karl-Johan Alm)
+
+Credits
+=======
+
+Thanks to everyone who directly contributed to this release:
+
+- Cory Fields
+- CryptAxe
+- fanquake
+- Jeremy Rubin
+- John Newbery
+- Jonas Schnelli
+- Gregory Maxwell
+- Karl-Johan Alm
+- Luke Dashjr
+- MarcoFalke
+- Matt Corallo
+- Mikerah
+- Pieter Wuille
+- practicalswift
+- Suhas Daftuar
+- Thomas Snider
+- Tjps
+- Wladimir J. van der Laan
+
+And to those that reported security issues:
+
+- awemany (for CVE-2018-17144, previously credited as "anonymous reporter")
+
diff --git a/doc/release-notes/release-notes-0.15.2.md b/doc/release-notes/release-notes-0.15.2.md
new file mode 100644
index 0000000000..1f58279051
--- /dev/null
+++ b/doc/release-notes/release-notes-0.15.2.md
@@ -0,0 +1,118 @@
+Bitcoin Core version *0.15.2* is now available from:
+
+ <https://bitcoincore.org/bin/bitcoin-core-0.15.2/>
+
+This is a new minor version release, including various bugfixes 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).
+
+The first time you run version 0.15.0 or higher, your chainstate database will
+be converted to a new format, which will take anywhere from a few minutes to
+half an hour, depending on the speed of your machine.
+
+The file format of `fee_estimates.dat` changed in version 0.15.0. Hence, a
+downgrade from version 0.15 or upgrade to version 0.15 will cause all fee
+estimates to be discarded.
+
+Note that the block database format also changed in version 0.8.0 and there is no
+automatic upgrade code from before version 0.8 to version 0.15.0. Upgrading
+directly from 0.7.x and earlier without redownloading the blockchain is not supported.
+However, as usual, old wallet versions are still supported.
+
+Downgrading warning
+-------------------
+
+The chainstate database for this release is not compatible with previous
+releases, so if you run 0.15 and then decide to switch back to any
+older version, you will need to run the old release with the `-reindex-chainstate`
+option to rebuild the chainstate data structures in the old format.
+
+If your node has pruning enabled, this will entail re-downloading and
+processing the entire blockchain.
+
+Compatibility
+==============
+
+Bitcoin Core is extensively tested on multiple operating systems using
+the Linux kernel, macOS 10.8+, and Windows Vista and later. Windows XP is not supported.
+
+Bitcoin Core should also work on most other Unix-like systems but is not
+frequently tested on them.
+
+
+Notable changes
+===============
+
+Denial-of-Service vulnerability CVE-2018-17144
+-------------------------------
+
+A denial-of-service vulnerability exploitable by miners has been discovered in
+Bitcoin Core versions 0.14.0 up to 0.16.2. It is recommended to upgrade any of
+the vulnerable versions to 0.15.2 or 0.16.3 as soon as possible.
+
+0.15.2 Change log
+=================
+
+### Build system
+
+- #11995 `9bb1a16` depends: Fix Qt build with XCode 9.2(fanquake)
+- #12946 `93b9a61` depends: Fix Qt build with XCode 9.3(fanquake)
+- #13544 `9fd3e00` depends: Update Qt download url (fanquake)
+- #11847 `cb7ef31` Make boost::multi_index comparators const (sdaftuar)
+
+### Consensus
+- #14247 `4b8a3f5` Fix crash bug with duplicate inputs within a transaction (TheBlueMatt, sdaftuar)
+
+### RPC
+- #11676 `7af2457` contrib/init: Update openrc-run filename (Luke Dashjr)
+- #11277 `7026845` Fix uninitialized URI in batch RPC requests (Russell Yanofsky)
+
+### Wallet
+- #11289 `3f1db56` Wrap dumpwallet warning and note scripts aren't dumped (MeshCollider)
+- #11289 `42ea47d` Add wallet backup text to import*, add* and dumpwallet RPCs (MeshCollider)
+- #11590 `6372a75` [Wallet] always show help-line of wallet encryption calls (Jonas Schnelli)
+
+### bitcoin-tx
+
+- #11554 `a69cc07` Sanity-check script sizes in bitcoin-tx (TheBlueMatt)
+
+### Tests
+- #11277 `3a6cdd4` Add test for multiwallet batch RPC calls (Russell Yanofsky)
+- #11647 `1c8c7f8` Add missing batch rpc calls to python coverage logs (Russell Yanofsky)
+- #11277 `1036c43` Add missing multiwallet rpc calls to python coverage logs (Russell Yanofsky)
+- #11277 `305f768` Limit AuthServiceProxyWrapper.\_\_getattr\_\_ wrapping (Russell Yanofsky)
+- #11277 `2eea279` Make AuthServiceProxy.\_batch method usable (Russell Yanofsky)
+
+Credits
+=======
+
+Thanks to everyone who directly contributed to this release:
+
+- fanquake
+- Jonas Schnelli
+- Luke Dashjr
+- Matt Corallo
+- MeshCollider
+- Russell Yanofsky
+- Suhas Daftuar
+- Wladimir J. van der Laan
+
+And to those that reported security issues:
+
+- awemany (for CVE-2018-17144, previously credited as "anonymous reporter")
+
diff --git a/doc/release-notes/release-notes-0.17.0.md b/doc/release-notes/release-notes-0.17.0.md
new file mode 100644
index 0000000000..418d7ba5f9
--- /dev/null
+++ b/doc/release-notes/release-notes-0.17.0.md
@@ -0,0 +1,1105 @@
+Bitcoin Core version 0.17.0 is now available from:
+
+ <https://bitcoincore.org/bin/bitcoin-core-0.17.0/>
+
+This is a new major version release, including new features, various bugfixes
+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).
+
+If your node has a txindex, the txindex db will be migrated the first time you run 0.17.0 or newer, which may take up to a few hours. Your node will not be functional until this migration completes.
+
+The first time you run version 0.15.0 or newer, your chainstate database will be converted to a
+new format, which will take anywhere from a few minutes to half an hour,
+depending on the speed of your machine.
+
+Note that the block database format also changed in version 0.8.0 and there is no
+automatic upgrade code from before version 0.8 to version 0.15.0. Upgrading
+directly from 0.7.x and earlier without redownloading the blockchain is not supported.
+However, as usual, old wallet versions are still supported.
+
+Downgrading warning
+-------------------
+
+The chainstate database for this release is not compatible with previous
+releases, so if you run 0.15 and then decide to switch back to any
+older version, you will need to run the old release with the `-reindex-chainstate`
+option to rebuild the chainstate data structures in the old format.
+
+If your node has pruning enabled, this will entail re-downloading and
+processing the entire blockchain.
+
+Compatibility
+==============
+
+Bitcoin Core is extensively tested on multiple operating systems using
+the Linux kernel, macOS 10.10+, and Windows 7 and newer (Windows XP is not supported).
+
+Bitcoin Core should also work on most other Unix-like systems but is not
+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.
+
+Known issues
+============
+
+- Upgrading from 0.13.0 or older currently results in memory blow-up during the roll-back of blocks to the SegWit activation point. In these cases, a full `-reindex` is necessary.
+
+- The GUI suffers from visual glitches in the new MacOS dark mode. This has to do with our Qt theme handling and is not a new problem in 0.17.0, but is expected to be resolved in 0.17.1.
+
+Notable changes
+===============
+
+Changed configuration options
+-----------------------------
+
+- `-includeconf=<file>` can be used to include additional configuration files.
+ Only works inside the `bitcoin.conf` file, not inside included files or from
+ command-line. Multiple files may be included. Can be disabled from command-
+ line via `-noincludeconf`. Note that multi-argument commands like
+ `-includeconf` will override preceding `-noincludeconf`, i.e.
+ ```
+ noincludeconf=1
+ includeconf=relative.conf
+ ```
+
+ as bitcoin.conf will still include `relative.conf`.
+
+GUI changes
+-----------
+
+- Block storage can be limited under Preferences, in the Main tab. Undoing this setting requires downloading the full blockchain again. This mode is incompatible with -txindex and -rescan.
+
+External wallet files
+---------------------
+
+The `-wallet=<path>` option now accepts full paths instead of requiring wallets
+to be located in the -walletdir directory.
+
+Newly created wallet format
+---------------------------
+
+If `-wallet=<path>` is specified with a path that does not exist, it will now
+create a wallet directory at the specified location (containing a wallet.dat
+data file, a db.log file, and database/log.?????????? files) instead of just
+creating a data file at the path and storing log files in the parent
+directory. This should make backing up wallets more straightforward than
+before because the specified wallet path can just be directly archived without
+having to look in the parent directory for transaction log files.
+
+For backwards compatibility, wallet paths that are names of existing data files
+in the `-walletdir` directory will continue to be accepted and interpreted the
+same as before.
+
+Dynamic loading and creation of wallets
+---------------------------------------
+
+Previously, wallets could only be loaded or created at startup, by specifying `-wallet` parameters on the command line or in the bitcoin.conf file. It is now possible to load, create and unload wallets dynamically at runtime:
+
+- Existing wallets can be loaded by calling the `loadwallet` RPC. The wallet can be specified as file/directory basename (which must be located in the `walletdir` directory), or as an absolute path to a file/directory.
+- New wallets can be created (and loaded) by calling the `createwallet` RPC. The provided name must not match a wallet file in the `walletdir` directory or the name of a wallet that is currently loaded.
+- Loaded wallets can be unloaded by calling the `unloadwallet` RPC.
+
+This feature is currently only available through the RPC interface.
+
+Coin selection
+--------------
+
+### Partial spend avoidance
+
+When an address is paid multiple times the coins from those separate payments can be spent separately which hurts privacy due to linking otherwise separate addresses. A new `-avoidpartialspends` flag has been added (default=false). If enabled, the wallet will always spend existing UTXO to the same address together even if it results in higher fees. If someone were to send coins to an address after it was used, those coins will still be included in future coin selections.
+
+Configuration sections for testnet and regtest
+----------------------------------------------
+
+It is now possible for a single configuration file to set different
+options for different networks. This is done by using sections or by
+prefixing the option with the network, such as:
+
+ main.uacomment=bitcoin
+ test.uacomment=bitcoin-testnet
+ regtest.uacomment=regtest
+ [main]
+ mempoolsize=300
+ [test]
+ mempoolsize=100
+ [regtest]
+ mempoolsize=20
+
+If the following options are not in a section, they will only apply to mainnet:
+`addnode=`, `connect=`, `port=`, `bind=`, `rpcport=`, `rpcbind=` and `wallet=`.
+The options to choose a network (`regtest=` and `testnet=`) must be specified
+outside of sections.
+
+'label' and 'account' APIs for wallet
+-------------------------------------
+
+A new 'label' API has been introduced for the wallet. This is intended as a
+replacement for the deprecated 'account' API. The 'account' can continue to
+be used in V0.17 by starting bitcoind with the '-deprecatedrpc=accounts'
+argument, and will be fully removed in V0.18.
+
+The label RPC methods mirror the account functionality, with the following functional differences:
+
+- Labels can be set on any address, not just receiving addresses. This functionality was previously only available through the GUI.
+- Labels can be deleted by reassigning all addresses using the `setlabel` RPC method.
+- There isn't support for sending transactions _from_ a label, or for determining which label a transaction was sent from.
+- Labels do not have a balance.
+
+Here are the changes to RPC methods:
+
+| Deprecated Method | New Method | Notes |
+| :---------------------- | :-------------------- | :-----------|
+| `getaccount` | `getaddressinfo` | `getaddressinfo` returns a json object with address information instead of just the name of the account as a string. |
+| `getaccountaddress` | n/a | There is no replacement for `getaccountaddress` since labels do not have an associated receive address. |
+| `getaddressesbyaccount` | `getaddressesbylabel` | `getaddressesbylabel` returns a json object with the addresses as keys, instead of a list of strings. |
+| `getreceivedbyaccount` | `getreceivedbylabel` | _no change in behavior_ |
+| `listaccounts` | `listlabels` | `listlabels` does not return a balance or accept `minconf` and `watchonly` arguments. |
+| `listreceivedbyaccount` | `listreceivedbylabel` | Both methods return new `label` fields, along with `account` fields for backward compatibility. |
+| `move` | n/a | _no replacement_ |
+| `sendfrom` | n/a | _no replacement_ |
+| `setaccount` | `setlabel` | Both methods now: <ul><li>allow assigning labels to any address, instead of raising an error if the address is not receiving address.<li>delete the previous label associated with an address when the final address using that label is reassigned to a different label, instead of making an implicit `getaccountaddress` call to ensure the previous label still has a receiving address. |
+
+| Changed Method | Notes |
+| :--------------------- | :------ |
+| `addmultisigaddress` | Renamed `account` named parameter to `label`. Still accepts `account` for backward compatibility if running with '-deprecatedrpc=accounts'. |
+| `getnewaddress` | Renamed `account` named parameter to `label`. Still accepts `account` for backward compatibility. if running with '-deprecatedrpc=accounts' |
+| `listunspent` | Returns new `label` fields. `account` field will be returned for backward compatibility if running with '-deprecatedrpc=accounts' |
+| `sendmany` | The `account` named parameter has been renamed to `dummy`. If provided, the `dummy` parameter must be set to the empty string, unless running with the `-deprecatedrpc=accounts` argument (in which case functionality is unchanged). |
+| `listtransactions` | The `account` named parameter has been renamed to `dummy`. If provided, the `dummy` parameter must be set to the string `*`, unless running with the `-deprecatedrpc=accounts` argument (in which case functionality is unchanged). |
+| `getbalance` | `account`, `minconf` and `include_watchonly` parameters are deprecated, and can only be used if running with '-deprecatedrpc=accounts' |
+
+BIP 174 Partially Signed Bitcoin Transactions support
+-----------------------------------------------------
+
+[BIP 174 PSBT](https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki) is an interchange format for Bitcoin transactions that are not fully signed
+yet, together with relevant metadata to help entities work towards signing it.
+It is intended to simplify workflows where multiple parties need to cooperate to
+produce a transaction. Examples include hardware wallets, multisig setups, and
+[CoinJoin](https://bitcointalk.org/?topic=279249) transactions.
+
+### Overall workflow
+
+Overall, the construction of a fully signed Bitcoin transaction goes through the
+following steps:
+
+- A **Creator** proposes a particular transaction to be created. He constructs
+ a PSBT that contains certain inputs and outputs, but no additional metadata.
+- For each input, an **Updater** adds information about the UTXOs being spent by
+ the transaction to the PSBT.
+- A potentially other Updater adds information about the scripts and public keys
+ involved in each of the inputs (and possibly outputs) of the PSBT.
+- **Signers** inspect the transaction and its metadata to decide whether they
+ agree with the transaction. They can use amount information from the UTXOs
+ to assess the values and fees involved. If they agree, they produce a
+ partial signature for the inputs for which they have relevant key(s).
+- A **Finalizer** is run for each input to convert the partial signatures and
+ possibly script information into a final `scriptSig` and/or `scriptWitness`.
+- An **Extractor** produces a valid Bitcoin transaction (in network format)
+ from a PSBT for which all inputs are finalized.
+
+Generally, each of the above (excluding Creator and Extractor) will simply
+add more and more data to a particular PSBT. In a naive workflow, they all have
+to operate sequentially, passing the PSBT from one to the next, until the
+Extractor can convert it to a real transaction. In order to permit parallel
+operation, **Combiners** can be employed which merge metadata from different
+PSBTs for the same unsigned transaction.
+
+The names above in bold are the names of the roles defined in BIP174. They're
+useful in understanding the underlying steps, but in practice, software and
+hardware implementations will typically implement multiple roles simultaneously.
+
+### RPCs
+
+- **`converttopsbt` (Creator)** is a utility RPC that converts an
+ unsigned raw transaction to PSBT format. It ignores existing signatures.
+- **`createpsbt` (Creator)** is a utility RPC that takes a list of inputs and
+ outputs and converts them to a PSBT with no additional information. It is
+ equivalent to calling `createrawtransaction` followed by `converttopsbt`.
+- **`walletcreatefundedpsbt` (Creator, Updater)** is a wallet RPC that creates a
+ PSBT with the specified inputs and outputs, adds additional inputs and change
+ to it to balance it out, and adds relevant metadata. In particular, for inputs
+ that the wallet knows about (counting towards its normal or watch-only
+ balance), UTXO information will be added. For outputs and inputs with UTXO
+ information present, key and script information will be added which the wallet
+ knows about. It is equivalent to running `createrawtransaction`, followed by
+ `fundrawtransaction`, and `converttopsbt`.
+- **`walletprocesspsbt` (Updater, Signer, Finalizer)** is a wallet RPC that takes as
+ input a PSBT, adds UTXO, key, and script data to inputs and outputs that miss
+ it, and optionally signs inputs. Where possible it also finalizes the partial
+ signatures.
+- **`finalizepsbt` (Finalizer, Extractor)** is a utility RPC that finalizes any
+ partial signatures, and if all inputs are finalized, converts the result to a
+ fully signed transaction which can be broadcast with `sendrawtransaction`.
+- **`combinepsbt` (Combiner)** is a utility RPC that implements a Combiner. It
+ can be used at any point in the workflow to merge information added to
+ different versions of the same PSBT. In particular it is useful to combine the
+ output of multiple Updaters or Signers.
+- **`decodepsbt`** is a diagnostic utility RPC which will show all information in
+ a PSBT in human-readable form, as well as compute its eventual fee if known.
+
+Upgrading non-HD wallets to HD wallets
+--------------------------------------
+
+Since Bitcoin Core 0.13.0, creating new BIP 32 Hierarchical Deterministic wallets has been supported by Bitcoin Core but old non-HD wallets could not be upgraded to HD. Now non-HD wallets can be upgraded to HD using the `-upgradewallet` command line option. This upgrade will result in the all keys in the keypool being marked as used and a new keypool generated. **A new backup must be made when this upgrade is performed.**
+
+Additionally, `-upgradewallet` can be used to upgraded from a non-split HD chain (all keys generated with `m/0'/0'/i'`) to a split HD chain (receiving keys generated with `'m/0'/0'/i'` and change keys generated with `m'/0'/1'/i'`). When this upgrade occurs, all keys already in the keypool will remain in the keypool to be used until all keys from before the upgrade are exhausted. This is to avoid issues with backups and downgrades when some keys may come from the change key keypool. Users can begin using the new split HD chain keypools by using the `newkeypool` RPC to mark all keys in the keypool as used and begin using a new keypool generated from the split HD chain.
+
+HD Master key rotation
+----------------------
+
+A new RPC, `sethdseed`, has been introduced which allows users to set a new HD seed or set their own HD seed. This allows for a new HD seed to be used. **A new backup must be made when a new HD seed is set.**
+
+Low-level RPC changes
+---------------------
+
+- The new RPC `scantxoutset` can be used to scan the UTXO set for entries
+ that match certain output descriptors. Refer to the [output descriptors
+ reference documentation](/doc/descriptors.md) for more details. This call
+ is similar to `listunspent` but does not use a wallet, meaning that the
+ wallet can be disabled at compile or run time. This call is experimental,
+ as such, is subject to changes or removal in future releases.
+
+- The `createrawtransaction` RPC will now accept an array or dictionary (kept for compatibility) for the `outputs` parameter. This means the order of transaction outputs can be specified by the client.
+- The `fundrawtransaction` RPC will reject the previously deprecated `reserveChangeKey` option.
+- `sendmany` now shuffles outputs to improve privacy, so any previously expected behavior with regards to output ordering can no longer be relied upon.
+- The new RPC `testmempoolaccept` can be used to test acceptance of a transaction to the mempool without adding it.
+- JSON transaction decomposition now includes a `weight` field which provides
+ the transaction's exact weight. This is included in REST /rest/tx/ and
+ /rest/block/ endpoints when in json mode. This is also included in `getblock`
+ (with verbosity=2), `listsinceblock`, `listtransactions`, and
+ `getrawtransaction` RPC commands.
+- New `fees` field introduced in `getrawmempool`, `getmempoolancestors`, `getmempooldescendants` and
+ `getmempoolentry` when verbosity is set to `true` with sub-fields `ancestor`, `base`, `modified`
+ and `descendant` denominated in BTC. This new field deprecates previous fee fields, such as
+ `fee`, `modifiedfee`, `ancestorfee` and `descendantfee`.
+- The new RPC `getzmqnotifications` returns information about active ZMQ
+ notifications.
+- When bitcoin is not started with any `-wallet=<path>` options, the name of
+ the default wallet returned by `getwalletinfo` and `listwallets` RPCs is
+ now the empty string `""` instead of `"wallet.dat"`. If bitcoin is started
+ with any `-wallet=<path>` options, there is no change in behavior, and the
+ name of any wallet is just its `<path>` string.
+- Passing an empty string (`""`) as the `address_type` parameter to
+ `getnewaddress`, `getrawchangeaddress`, `addmultisigaddress`,
+ `fundrawtransaction` RPCs is now an error. Previously, this would fall back
+ to using the default address type. It is still possible to pass null or leave
+ the parameter unset to use the default address type.
+
+- Bare multisig outputs to our keys are no longer automatically treated as
+ incoming payments. As this feature was only available for multisig outputs for
+ which you had all private keys in your wallet, there was generally no use for
+ them compared to single-key schemes. Furthermore, no address format for such
+ outputs is defined, and wallet software can't easily send to it. These outputs
+ will no longer show up in `listtransactions`, `listunspent`, or contribute to
+ your balance, unless they are explicitly watched (using `importaddress` or
+ `importmulti` with hex script argument). `signrawtransaction*` also still
+ works for them.
+
+- The `getwalletinfo` RPC method now returns an `hdseedid` value, which is always the same as the incorrectly-named `hdmasterkeyid` value. `hdmasterkeyid` will be removed in V0.18.
+- The `getaddressinfo` RPC method now returns an `hdseedid` value, which is always the same as the incorrectly-named `hdmasterkeyid` value. `hdmasterkeyid` will be removed in V0.18.
+
+- Parts of the `validateaddress` RPC method have been deprecated and moved to
+ `getaddressinfo`. Clients must transition to using `getaddressinfo` to access
+ this information before upgrading to v0.18. The following deprecated fields
+ have moved to `getaddressinfo` and will only be shown with
+ `-deprecatedrpc=validateaddress`: `ismine`, `iswatchonly`, `script`, `hex`,
+ `pubkeys`, `sigsrequired`, `pubkey`, `addresses`, `embedded`, `iscompressed`,
+ `account`, `timestamp`, `hdkeypath`, `hdmasterkeyid`.
+- `signrawtransaction` is deprecated and will be fully removed in v0.18. To use
+ `signrawtransaction` in v0.17, restart bitcoind with
+ `-deprecatedrpc=signrawtransaction`. Projects should transition to using
+ `signrawtransactionwithkey` and `signrawtransactionwithwallet` before
+ upgrading to v0.18.
+
+Other API changes
+-----------------
+
+- The `inactivehdmaster` property in the `dumpwallet` output has been corrected to `inactivehdseed`
+
+### Logging
+
+- The log timestamp format is now ISO 8601 (e.g. "2018-02-28T12:34:56Z").
+
+- When running bitcoind with `-debug` but without `-daemon`, logging to stdout
+ is now the default behavior. Setting `-printtoconsole=1` no longer implicitly
+ disables logging to debug.log. Instead, logging to file can be explicitly disabled
+ by setting `-debuglogfile=0`.
+
+Transaction index changes
+-------------------------
+
+The transaction index is now built separately from the main node procedure,
+meaning the `-txindex` flag can be toggled without a full reindex. If bitcoind
+is run with `-txindex` on a node that is already partially or fully synced
+without one, the transaction index will be built in the background and become
+available once caught up. When switching from running `-txindex` to running
+without the flag, the transaction index database will *not* be deleted
+automatically, meaning it could be turned back on at a later time without a full
+resync.
+
+Miner block size removed
+------------------------
+
+The `-blockmaxsize` option for miners to limit their blocks' sizes was
+deprecated in V0.15.1, and has now been removed. Miners should use the
+`-blockmaxweight` option if they want to limit the weight of their blocks.
+
+Python Support
+--------------
+
+Support for Python 2 has been discontinued for all test files and tools.
+
+0.17.0 change log
+=================
+
+### Consensus
+- #12204 `3fa24bb` Fix overly eager BIP30 bypass (morcos)
+
+### Policy
+- #12568 `ed6ae80` Allow dustrelayfee to be set to zero (luke-jr)
+- #13120 `ca2a233` Treat segwit as always active (MarcoFalke)
+- #13096 `062738c` Fix `MAX_STANDARD_TX_WEIGHT` check (jl2012)
+
+### Mining
+- #12693 `df529dc` Remove unused variable in SortForBlock (drewx2)
+- #12448 `84efa9a` Interrupt block generation on shutdown request (promag)
+
+### Block and transaction handling
+- #12225 `67447ba` Mempool cleanups (sdaftuar)
+- #12356 `fd65937` Fix 'mempool min fee not met' debug output (Empact)
+- #12287 `bf3353d` Optimise lock behaviour for GuessVerificationProgress() (jonasschnelli)
+- #11889 `47a7666` Drop extra script variable in ProduceSignature (ryanofsky)
+- #11880 `d59b8d6` Stop special-casing phashBlock handling in validation for TBV (TheBlueMatt)
+- #12431 `947c25e` Only call NotifyBlockTip when chainActive changes (jamesob)
+- #12653 `534b8fa` Allow to optional specify the directory for the blocks storage (jonasschnelli)
+- #12172 `3b62a91` Bugfix: RPC: savemempool: Don't save until LoadMempool() is finished (jtimon)
+- #12167 `88430cb` Make segwit failure due to `CLEANSTACK` violation return a `SCRIPT_ERR_CLEANSTACK` error code (maaku)
+- #12561 `24133b1` Check for block corruption in ConnectBlock() (sdaftuar)
+- #11617 `1b5723e` Avoid lock: Call FlushStateToDisk(…) regardless of fCheckForPruning (practicalswift)
+- #11739 `0a8b7b4` Enforce `SCRIPT_VERIFY_P2SH` and `SCRIPT_VERIFY_WITNESS` from genesis (sdaftuar)
+- #12885 `a49381d` Reduce implementation code inside CScript (sipa)
+- #13032 `34dd1a6` Output values for "min relay fee not met" error (kristapsk)
+- #13033 `a07e8ca` Build txindex in parallel with validation (jimpo)
+- #13080 `66cc47b` Add compile time checking for ::mempool.cs runtime locking assertions (practicalswift)
+- #13185 `08c1caf` Bugfix: the end of a reorged chain is invalid when connect fails (sipa)
+- #11689 `0264836` Fix missing locking in CTxMemPool::check(…) and CTxMemPool::setSanityCheck(…) (practicalswift)
+- #13011 `3c2a41a` Cache witness hash in CTransaction (MarcoFalke)
+- #13191 `0de7cc8` Specialized double-SHA256 with 64 byte inputs with SSE4.1 and AVX2 (sipa)
+- #13243 `ea263e1` Make reusable base class for auxiliary indices (jimpo)
+- #13393 `a607d23` Enable double-SHA256-for-64-byte code on 32-bit x86 (sipa)
+- #13428 `caabdea` validation: check the specified number of blocks (off-by-one) (kallewoof)
+- #13438 `450055b` Improve coverage of SHA256 SelfTest code (sipa)
+- #13431 `954f4a9` validation: count blocks correctly for check level < 3 (kallewoof)
+- #13386 `3a3eabe` SHA256 implementations based on Intel SHA Extensions (sipa)
+- #11658 `9a1ad2c` During IBD, when doing pruning, prune 10% extra to avoid pruning again soon after (luke-jr)
+- #13794 `8ce55df` chainparams: Update with data from assumed valid chain (MarcoFalke)
+- #13527 `e7ea858` Remove promiscuousmempoolflags (MarcoFalke)
+
+### P2P protocol and network code
+- #12342 `eaeaa2d` Extend #11583 ("Do not make it trivial for inbound peers to generate log entries") to include "version handshake timeout" message (clemtaylor)
+- #12218 `9a32114` Move misbehaving logging to net logging category (laanwj)
+- #10387 `5c2aff8` Eventually connect to `NODE_NETWORK_LIMITED` peers (jonasschnelli)
+- #9037 `a36834f` Add test-before-evict discipline to addrman (EthanHeilman)
+- #12622 `e1d6e2a` Correct addrman logging (laanwj)
+- #11962 `0a01843` add seed.bitcoin.sprovoost.nl to DNS seeds (Sjors)
+- #12569 `23e7fe8` Increase signal-to-noise ratio in debug.log by adjusting log level when logging failed non-manual connect():s (practicalswift)
+- #12855 `c199869` Minor accumulated cleanups (tjps)
+- #13153 `ef46c99` Add missing newlines to debug logging (laanwj)
+- #13162 `a174702` Don't incorrectly log that REJECT messages are unknown (jnewbery)
+- #13151 `7f4db9a` Serve blocks directly from disk when possible (laanwj)
+- #13134 `70d3541` Add option `-enablebip61` to configure sending of BIP61 notifications (laanwj)
+- #13532 `7209fec` Log warning when deprecated network name 'tor' is used (wodry)
+- #13615 `172f984` Remove unused interrupt from SendMessages (fanquake)
+- #13417 `1e90862` Tighten scope in `net_processing` (skeees)
+- #13298 `f8d470e` Bucketing INV delays (1 bucket) for incoming connections to hide tx time (naumenkogs)
+- #13672 `0d8d6be` Modified `in_addr6` cast in CConman class to work with msvc (sipsorcery)
+- #11637 `c575260` Remove dead service bits code (MarcoFalke)
+- #13212 `a6f00ce` Fixed a race condition when disabling the network (lmanners)
+- #13656 `1211b15` Remove the boost/algorithm/string/predicate.hpp dependency (251Labs)
+- #13423 `f58674a` Thread safety annotations in `net_processing` (skeees)
+- #13776 `7d36237` Add missing verification of IPv6 address in CNetAddr::GetIn6Addr(…) (practicalswift)
+- #13907 `48bf8ff` Introduce a maximum size for locators (gmaxwell)
+- #13951 `8a9ffec` Hardcoded seeds update pre-0.17 branch (laanwj)
+
+### Wallet
+- #12330 `2a30e67` Reduce scope of `cs_main` and `cs_wallet` locks in listtransactions (promag)
+- #12298 `a1ffddb` Refactor HaveKeys to early return on false result (promag)
+- #12282 `663911e` Disallow abandon of conflicted txes (MarcoFalke)
+- #12333 `d405bee` Make CWallet::ListCoins atomic (promag)
+- #12296 `8e6f9f4` Only fee-bump non-conflicted/non-confirmed txes (MarcoFalke)
+- #11866 `6bb9c13` Do not un-mark fInMempool on wallet txn if ATMP fails (TheBlueMatt)
+- #11882 `987a809` Disable default fallbackfee on mainnet (jonasschnelli)
+- #9991 `4ca7c1e` listreceivedbyaddress Filter Address (NicolasDorier)
+- #11687 `98bc27f` External wallet files (ryanofsky)
+- #12658 `af88094` Sanitize some wallet serialization (sipa)
+- #9680 `6acd870` Unify CWalletTx construction (ryanofsky)
+- #10637 `e057589` Coin Selection with Murch's algorithm (achow101, Xekyo)
+- #12408 `c39dd2e` Change output type globals to members (MarcoFalke)
+- #12694 `9552dfb` Actually disable BnB when there are preset inputs (achow101)
+- #11536 `cead84b` Rename account to label where appropriate (ryanofsky)
+- #12709 `02b7e83` shuffle sendmany recipients ordering (instagibbs)
+- #12699 `c948dc8` Shuffle transaction inputs before signing (instagibbs)
+- #10762 `6d53663` Remove Wallet dependencies from init.cpp (jnewbery)
+- #12857 `821980c` Avoid travis lint-include-guards error (ken2812221)
+- #12702 `dab0d68` importprivkey: hint about importmulti (kallewoof)
+- #12836 `9abdb7c` Make WalletInitInterface and DummyWalletInit private, fix nullptr deref (promag)
+- #12785 `215158a` Initialize `m_last_block_processed` to nullptr (practicalswift)
+- #12932 `8d651ae` Remove redundant lambda function arg in handleTransactionChanged (laanwj)
+- #12749 `a84b056` feebumper: discard change outputs below discard rate (instagibbs)
+- #12892 `9b3370d` introduce 'label' API for wallet (jnewbery)
+- #12925 `6d3de17` Logprint the start of a rescan (jonasschnelli)
+- #12888 `39439e5` debug log number of unknown wallet records on load (instagibbs)
+- #12977 `434150a` Refactor `g_wallet_init_interface` to const reference (promag)
+- #13017 `65d7083` Add wallets management functions (promag)
+- #12953 `d1d54ae` Deprecate accounts (jnewbery)
+- #12909 `476cb35` Make fee settings to be non-static members (MarcoFalke)
+- #13002 `487dcbe` Do not treat bare multisig outputs as IsMine unless watched (sipa)
+- #13028 `783bb64` Make vpwallets usage thread safe (promag)
+- #12507 `2afdc29` Interrupt rescan on shutdown request (promag)
+- #12729 `979150b` Get rid of ambiguous OutputType::NONE value (ryanofsky)
+- #13079 `5778d44` Fix rescanblockchain rpc to properly report progress (Empact)
+- #12560 `e03c0db` Upgrade path for non-HD wallets to HD (achow101)
+- #13161 `7cc1bd3` Reset BerkeleyDB handle after connection fails (real-or-random)
+- #13081 `0dec5b5` Add compile time checking for `cs_wallet` runtime locking assertions (practicalswift)
+- #13127 `19a3a9e` Add Clang thread safety annotations for variables guarded by `cs_db` (practicalswift)
+- #10740 `4cfe17c` `loadwallet` RPC - load wallet at runtime (jnewbery)
+- #12924 `6738813` Fix hdmaster-key / seed-key confusion (scripted diff) (jnewbery)
+- #13297 `d82c5d1` Fix incorrect comment for DeriveNewSeed (jnewbery)
+- #13063 `6378eef` Use shared pointer to retain wallet instance (promag)
+- #13142 `56fe3dc` Separate IsMine from solvability (sipa)
+- #13194 `fd96d54` Remove template matching and pseudo opcodes (sipa)
+- #13252 `c4cc8d9` Refactor ReserveKeyFromKeyPool for safety (Empact)
+- #13058 `343d4e4` `createwallet` RPC - create new wallet at runtime (jnewbery)
+- #13351 `2140f6c` Prevent segfault when sending to unspendable witness (MarcoFalke)
+- #13060 `3f0f394` Remove getlabeladdress RPC (jnewbery)
+- #13111 `000abbb` Add unloadwallet RPC (promag)
+- #13160 `868cf43` Unlock spent outputs (promag)
+- #13498 `f54f373` Fixups from account API deprecation (jnewbery)
+- #13491 `61a044a` Improve handling of INVALID in IsMine (sipa)
+- #13425 `028b0d9` Moving final scriptSig construction from CombineSignatures to ProduceSignature (PSBT signer logic) (achow101)
+- #13564 `88a15eb` loadwallet shouldn't create new wallets (jnewbery)
+- #12944 `619cd29` ScanforWalletTransactions should mark input txns as dirty (instagibbs)
+- #13630 `d6b2235` Drop unused pindexRet arg to CMerkleTx::GetDepthInMainChain (Empact)
+- #13566 `ad552a5` Fix get balance (jnewbery)
+- #13500 `4a3e8c5` Decouple wallet version from client version (achow101)
+- #13712 `aba2e66` Fix non-determinism in ParseHDKeypath(…). Avoid using an uninitialized variable in path calculation (practicalswift)
+- #9662 `6b6e854` Add createwallet "disableprivatekeys" option: a sane mode for watchonly-wallets (jonasschnelli)
+- #13683 `e8c7434` Introduce assertion to document the assumption that cache and cache_used are always set in tandem (practicalswift)
+- #12257 `5f7575e` Use destination groups instead of coins in coin select (kallewoof)
+- #13773 `89a116d` Fix accidental use of the comma operator (practicalswift)
+- #13805 `c88529a` Correctly limit output group size (sdaftuar)
+- #12992 `26f59f5` Add wallet name to log messages (PierreRochard)
+- #13667 `b81a8a5` Fix backupwallet for multiwallets (domob1812)
+- #13657 `51c693d` assert to ensure accuracy of CMerkleTx::GetBlocksToMaturity (Empact)
+- #13812 `9d86aad` sum ancestors rather than taking max in output groups (kallewoof)
+- #13876 `8eb9870` Catch `filesystem_error` and raise `InitError` (MarcoFalke)
+- #13808 `13d51a2` shuffle coins before grouping, where warranted (kallewoof)
+- #13666 `2115cba` Always create signatures with Low R values (achow101)
+- #13917 `0333914` Additional safety checks in PSBT signer (sipa)
+- #13968 `65e7a8b` couple of walletcreatefundedpsbt fixes (instagibbs)
+- #14055 `2307a6e` fix walletcreatefundedpsbt deriv paths, add test (instagibbs)
+
+### RPC and other APIs
+- #12336 `3843780` Remove deprecated rpc options (jnewbery)
+- #12193 `5dc00f6` Consistently use UniValue.pushKV instead of push_back(Pair()) (karel-3d) (MarcoFalke)
+- #12409 `0cc45ed` Reject deprecated reserveChangeKey in fundrawtransaction (MarcoFalke)
+- #10583 `8a98dfe` Split part of validateaddress into getaddressinfo (achow101)
+- #10579 `ffc6e48` Split signrawtransaction into wallet and non-wallet RPC command (achow101)
+- #12494 `e4ffcac` Declare CMutableTransaction a struct in rawtransaction.h (Empact)
+- #12503 `0e26591` createmultisig no longer takes addresses (instagibbs)
+- #12083 `228b086` Improve getchaintxstats test coverage (promag)
+- #12479 `cd5e438` Add child transactions to getrawmempool verbose output (conscott)
+- #11872 `702e8b7` createrawtransaction: Accept sorted outputs (MarcoFalke)
+- #12700 `ebdf84c` Document RPC method aliasing (ryanofsky)
+- #12727 `8ee5c7b` Remove unreachable help conditions in rpcwallet.cpp (lutangar)
+- #12778 `b648974` Add username and ip logging for RPC method requests (GabrielDav)
+- #12717 `ac898b6` rest: Handle utxo retrieval when ignoring the mempool (romanz)
+- #12787 `cd99e5b` Adjust ifdef to avoid unreachable code (practicalswift)
+- #11742 `18815b4` Add testmempoolaccept (MarcoFalke)
+- #12942 `fefb817` Drop redundant testing of signrawtransaction prevtxs args (Empact)
+- #11200 `5f2a399` Allow for aborting rescans in the GUI (achow101)
+- #12791 `3a8a4dc` Expose a transaction's weight via RPC (TheBlueMatt)
+- #12436 `6e67754` Adds a functional test to validate the transaction version number in the RPC output (251Labs)
+- #12240 `6f8b345` Introduced a new `fees` structure that aggregates all sub-field fee types denominated in BTC (mryandao)
+- #12321 `eac067a` p2wsh and p2sh-p2wsh address in decodescript (fivepiece)
+- #13090 `17266a1` Remove Safe mode (achow101, laanwj)
+- #12639 `7eb7076` Reduce `cs_main` lock in listunspent (promag)
+- #10267 `7b966d9` New -includeconf argument for including external configuration files (kallewoof)
+- #10757 `b9551d3` Introduce getblockstats to plot things (jtimon)
+- #13288 `a589f53` Remove the need to include rpc/blockchain.cpp in order to put `GetDifficulty` under test (Empact)
+- #13394 `e1f8dce` cli: Ignore libevent warnings (theuni)
+- #13439 `3f398d7` Avoid "duplicate" return value for invalid submitblock (TheBlueMatt)
+- #13570 `a247594` Add new "getzmqnotifications" method (domob1812)
+- #13072 `b25a4c2` Update createmultisig RPC to support segwit (ajtowns)
+- #12196 `8fceae0` Add scantxoutset RPC method (jonasschnelli)
+- #13557 `b654723` BIP 174 PSBT Serializations and RPCs (achow101)
+- #13697 `f030410` Support output descriptors in scantxoutset (sipa)
+- #13927 `bced8ea` Use pushKV in some new PSBT RPCs (domob1812)
+- #13918 `a9c56b6` Replace median fee rate with feerate percentiles in getblockstats (marcinja)
+- #13721 `9f23c16` Bugfixes for BIP 174 combining and deserialization (achow101)
+- #13960 `517010e` Fix PSBT deserialization of 0-input transactions (achow101)
+
+### GUI
+- #12416 `c997f88` Fix Windows build errors introduced in #10498 (practicalswift)
+- #11733 `e782099` Remove redundant locks (practicalswift)
+- #12426 `bfa3911` Initialize members in WalletModel (MarcoFalke)
+- #12489 `e117cfe` Bugfix: respect user defined configuration file (-conf) in QT settings (jonasschnelli)
+- #12421 `be263fa` navigate to transaction history page after send (Sjors)
+- #12580 `ce56fdd` Show a transaction's virtual size in its details dialog (dooglus)
+- #12501 `c8ea91a` Improved "custom fee" explanation in tooltip (randolf)
+- #12616 `cff95a6` Set modal overlay hide button as default (promag)
+- #12620 `8a43bdc` Remove TransactionTableModel::TxIDRole (promag)
+- #12080 `56cc022` Add support to search the address book (promag)
+- #12621 `2bac3e4` Avoid querying unnecessary model data when filtering transactions (promag)
+- #12721 `e476826` remove "new" button during receive-mode in addressbook (jonasschnelli)
+- #12723 `310dc61` Qt5: Warning users about invalid-BIP21 URI bitcoin:// (krab)
+- #12610 `25cf18f` Multiwallet for the GUI (jonasschnelli)
+- #12779 `f4353da` Remove unused method setupAmountWidget(…) (practicalswift)
+- #12795 `68484d6` do not truncate .dat extension for wallets in gui (instagibbs)
+- #12870 `1d54004` make clean removes `src/qt/moc_` files (Sjors)
+- #13055 `bdda14d` Don't log to console by default (laanwj)
+- #13141 `57c57df` fixes broken link on readme (marcoagner)
+- #12928 `ef006d9` Initialize non-static class members that were previously neither initialized where defined nor in constructor (practicalswift)
+- #13158 `81c533c` Improve sendcoinsdialog readability (marcoagner)
+- #11491 `40c34a0` Add proxy icon in statusbar (mess110)
+- #13264 `2a7c53b` Satoshi unit (GreatSock)
+- #13097 `e545503` Support wallets loaded dynamically (promag)
+- #13284 `f8be434` fix visual "overflow" of amount input (brandonrninefive)
+- #13275 `a315b79` use `[default wallet]` as name for wallet with no name (jonasschnelli)
+- #13273 `3fd0c23` Qt/Bugfix: fix handling default wallet with no name (jonasschnelli)
+- #13341 `25d2df2` Stop translating command line options (laanwj)
+- #13043 `6e249e4` OptionsDialog: add prune setting (Sjors)
+- #13506 `6579d80` load wallet in UI after possible init aborts (jonasschnelli)
+- #13458 `dc53f7f` Drop qt4 support (laanwj)
+- #13528 `b877c39` Move BitcoinGUI initializers to class, fix initializer order warning (laanwj)
+- #13536 `baf3a3a` coincontrol: Remove unused qt4 workaround (MarcoFalke)
+- #13537 `10ffca7` Peer table: Visualize inbound/outbound state for every row (wodry)
+- #13791 `2c14c1f` Reject dialogs if key escape is pressed (promag)
+
+### Build system
+- #12371 `c9ca4f6` Add gitian PGP key: akx20000 (ghost)
+- #11966 `f4f4f51` clientversion: Use full commit hash for commit-based version descriptions (luke-jr)
+- #12417 `ae0fbf0` Upgrade `mac_alias` to 2.0.7 (droark)
+- #12444 `1f055ef` gitian: Bump descriptors for (0.)17 (theuni)
+- #12402 `59e032b` expat 2.2.5, ccache 3.4.1, miniupnpc 2.0.20180203 (fanquake)
+- #12029 `daa84b3` Add a makefile target for Doxygen documentation (Ov3rlo4d)
+- #12466 `6645eaf` Only use `D_DARWIN_C_SOURCE` when building miniupnpc on darwin (fanquake)
+- #11986 `765a3eb` zeromq 4.2.3 (fanquake)
+- #12373 `f13d756` Add build support for profiling (murrayn)
+- #12631 `a312e20` gitian: Alphabetize signing keys & add kallewoof key (kallewoof)
+- #12607 `29fad97` Remove ccache (fanquake)
+- #12625 `c4219ff` biplist 1.0.3 (fanquake)
+- #12666 `05042d3` configure: UniValue 1.0.4 is required for pushKV(, bool) (luke-jr)
+- #12678 `6324c68` Fix a few compilation issues with Clang 7 and -Werror (vasild)
+- #12692 `de6bdfd` Add configure options for various -fsanitize flags (eklitzke)
+- #12901 `7e23972` Show enabled sanitizers in configure output (practicalswift)
+- #12899 `3076993` macOS: Prevent Xcode 9.3 build warnings (AkioNak)
+- #12715 `8fd6243` Add 'make clean' rule (hkjn)
+- #13133 `a024a18` Remove python2 from configure.ac (ken2812221)
+- #13005 `cb088b1` Make --enable-debug to pick better options (practicalswift)
+- #13254 `092b366` Remove improper `qt/moc_*` cleaning glob from the general Makefile (Empact)
+- #13306 `f5a7733` split warnings out of CXXFLAGS (theuni)
+- #13385 `7c7508c` Guard against accidental introduction of new Boost dependencies (practicalswift)
+- #13041 `5779dc4` Add linter checking for accidental introduction of locale dependence (practicalswift)
+- #13408 `70a03c6` crypto: cleanup sha256 build (theuni)
+- #13435 `cf7ca60` When build fails due to lib missing, indicate which one (Empact)
+- #13445 `8eb76f3` Reset default -g -O2 flags when enable debug (ken2812221)
+- #13465 `81069a7` Avoid concurrency issue when make multiple target (ken2812221)
+- #13454 `45c00f8` Make sure `LC_ALL=C` is set in all shell scripts (practicalswift)
+- #13480 `31145a3` Avoid copies in range-for loops and add a warning to detect them (theuni)
+- #13486 `66e1a08` Move rpc/util.cpp from libbitcoin-util to libbitcoin-server (ken2812221)
+- #13580 `40334c7` Detect if char equals `int8_t` (ken2812221)
+- #12788 `287e4ed` Tune wildcards for LIBSECP256K1 target (kallewoof)
+- #13611 `b55f0c3` bugfix: Use `__cpuid_count` for gnu C to avoid gitian build fail (ken2812221)
+- #12971 `a6d14b1` Upgrade Qt to 5.9.6 (TheCharlatan)
+- #13543 `6c6a300` Add RISC-V support (laanwj)
+- #13177 `dcb154e` GCC-7 and glibc-2.27 back compat code (ken2812221)
+- #13659 `90b1c7e` add missing leveldb defines (theuni)
+- #13368 `c0f1569` Update gitian-build.sh for docker (achow101)
+- #13171 `19d8ca5` Change gitian-descriptors to use bionic instead (ken2812221)
+- #13604 `75bea05` Add depends 32-bit arm support for bitcoin-qt (TheCharlatan)
+- #13623 `9cdb19f` Migrate gitian-build.sh to python (ken2812221)
+- #13689 `8c36432` disable Werror when building zmq (greenaddress)
+- #13617 `cf7f9ae` release: Require macos 10.10+ (fanquake)
+- #13750 `c883653` use MacOS friendly sed syntax in qt.mk (Sjors)
+- #13095 `415f2bf` update `ax_boost_chrono`/`unit_test_framework` (fanquake)
+- #13732 `e8ffec6` Fix Qt's rcc determinism (Fuzzbawls)
+- #13782 `8284f1d` Fix osslsigncode compile issue in gitian-build (ken2812221)
+- #13696 `2ab7208` Add aarch64 qt depends support for cross compiling bitcoin-qt (TheCharlatan)
+- #13705 `b413ba0` Add format string linter (practicalswift)
+- #14000 `48c8459` fix qt determinism (theuni)
+- #14018 `3e4829a` Bugfix: NSIS: Exclude `Makefile*` from docs (luke-jr)
+- #12906 `048ac83` Avoid `interface` keyword to fix windows gitian build (ryanofsky)
+- #13314 `a9b6957` Fix FreeBSD build by including utilstrencodings.h (laanwj)
+
+### Tests and QA
+- #12252 `8d57319` Require all tests to follow naming convention (ajtowns)
+- #12295 `935eb8d` Enable flake8 warnings for all currently non-violated rules (practicalswift)
+- #11858 `b4d8549` Prepare tests for Windows (MarcoFalke)
+- #11771 `2dbc4a4` Change invalidtxrequest to use BitcoinTestFramework (jnewbery)
+- #12200 `d09968f` Bind functional test nodes to 127.0.0.1 (Sjors)
+- #12425 `26dc2da` Add some script tests (richardkiss)
+- #12455 `23481fa` Fix bip68 sequence test to reflect updated rpc error message (Empact)
+- #12477 `acd1e61` Plug memory leaks and stack-use-after-scope (MarcoFalke)
+- #12443 `07090c5` Move common args to bitcoin.conf (MarcoFalke)
+- #12570 `39dcac2` Add test cases for HexStr (`std::reverse_iterator` and corner cases) (kostaz)
+- #12582 `6012f1c` Fix ListCoins test failure due to unset `g_wallet_allow_fallback_fee` (ryanofsky)
+- #12516 `7f99964` Avoid unintentional unsigned integer wraparounds in tests (practicalswift)
+- #12512 `955fd23` Don't test against the mempool min fee information in mempool_limit.py (Empact)
+- #12600 `29088b1` Add a test for large tx output scripts with segwit input (richardkiss)
+- #12627 `791c3ea` Fix some tests to work on native windows (MarcoFalke)
+- #12405 `0f58d7f` travis: Full clone for git subtree check (MarcoFalke)
+- #11772 `0630974` Change invalidblockrequest to use BitcoinTestFramework (jnewbery)
+- #12681 `1846296` Fix ComputeTimeSmart test failure with `-DDEBUG_LOCKORDER` (ryanofsky)
+- #12682 `9f04c8e` travis: Clone depth 1 unless `$check_doc` (MarcoFalke)
+- #12710 `00d1680` Append scripts to new `test_list` array to fix bad assignment (jeffrade)
+- #12720 `872c921` Avoiding 'file' function name from python2 (jeffrade)
+- #12728 `4ba3d4f` rename TestNode to TestP2PConn in tests (jnewbery)
+- #12746 `2405ce1` Remove unused argument `max_invalid` from `check_estimates(…)` (practicalswift)
+- #12718 `185d484` Require exact match in `assert_start_raises_init_eror` (jnewbery, MarcoFalke)
+- #12076 `6d36f59` Use node.datadir instead of tmpdir in test framework (MarcoFalke)
+- #12772 `b43aba8` ci: Bump travis timeout for make check to 50m (jnewbery)
+- #12806 `18606eb` Fix function names in `feature_blocksdir` (MarcoFalke)
+- #12811 `0d8fc8d` Make summary row bold-red if any test failed and show failed tests at end of table (laanwj)
+- #12790 `490644d` Use blockmaxweight where tests previously had blockmaxsize (conscott)
+- #11773 `f0f9732` Change `feature_block.py` to use BitcoinTestFramework (jnewbery)
+- #12839 `40f4baf` Remove travis checkout depth (laanwj)
+- #11817 `2a09a78` Change `feature_csv_activation.py` to use BitcoinTestFramework (jnewbery)
+- #12284 `fa5825d` Remove assigned but never used local variables. Enable Travis checking for unused local variables (practicalswift)
+- #12719 `9beded5` Add note about test suite naming convention in developer-notes.md (practicalswift)
+- #12861 `c564424` Stop `feature_block.py` from blowing up memory (jnewbery)
+- #12851 `648252e` travis: Run verify-commits only on cron jobs (MarcoFalke)
+- #12853 `2106c4c` Match full plain text by default (MarcoFalke)
+- #11818 `9a2db3b` I accidentally (deliberately) killed it (the ComparisonTestFramework) (jnewbery)
+- #12766 `69310a3` Tidy up REST interface functional tests (romanz)
+- #12849 `83c7533` Add logging in loops in `p2p_sendhears.py` (ccdle12)
+- #12895 `d6f10b2` Add note about test suite name uniqueness requirement to developer notes (practicalswift)
+- #12856 `27278df` Add Metaclass for BitcoinTestFramework (WillAyd)
+- #12918 `6fc5a05` Assert on correct variable (kallewoof)
+- #11878 `a04440f` Add Travis check for duplicate includes (practicalswift)
+- #12917 `cf8073f` Windows fixups for functional tests (MarcoFalke)
+- #12926 `dd1ca9e` Run unit tests in parallel (sipa)
+- #12920 `b1fdfc1` Fix sign for expected values (kallewoof)
+- #12947 `979f598` Wallet hd functional test speedup and clarification (instagibbs)
+- #12993 `0d69921` Remove compatibility code not needed now when we're on Python 3 (practicalswift)
+- #12996 `6a278e0` Remove redundant bytes(…) calls (practicalswift)
+- #12949 `6b46288` Avoid copies of CTransaction (MarcoFalke)
+- #13007 `0d12570` Fix dangling wallet pointer in vpwallets (promag)
+- #13048 `cac6d11` Fix `feature_block` flakiness (jnewbery)
+- #12510 `d5b2e98` Add `rpc_bind` test to default-run tests (laanwj)
+- #13022 `896a9d0` Attach node index to `test_node` AssertionError and print messages (jamesob)
+- #13024 `018c7e5` Add rpcauth pair that generated by rpcauth.py (ken2812221)
+- #13013 `a0079d4` bench: Amend `mempool_eviction` test for witness txs (MarcoFalke)
+- #13051 `e074097` Normalize executable location (MarcoFalke)
+- #13056 `106d929` Make rpcauth.py testable and add unit tests (nixbox)
+- #13073 `a785bc3` add rpcauth-test to `AC_CONFIG_LINKS` to fix out-of-tree make check (laanwj)
+- #12830 `25ad2f7` Clarify address book error messages, add tests (jamesob)
+- #13082 `24106a8` don't test against min relay fee information in `mining_prioritisetransaction.py` (kristapsk)
+- #13003 `8d045a0` Add test for orphan handling (MarcoFalke)
+- #13105 `9e9b48d` Add --failfast option to functional test runner (jamesob)
+- #13130 `3186ad4` Fix race in `rpc_deprecated.py` (jnewbery)
+- #13136 `baf6b4e` Fix flake8 warnings in several wallet functional tests (jnewbery)
+- #13094 `bf9b03d` Add test for 64-bit Windows PE, modify 32-bit test results (ken2812221)
+- #13183 `9458b05` travis: New travis job for `check_docs` steps (glaksmono)
+- #12265 `1834d4d` fundrawtransaction: lock watch-only shared address (kallewoof)
+- #13188 `4a50ec0` Remove unused option --srcdir (MarcoFalke)
+- #12755 `612ba35` Better stderr testing (jnewbery)
+- #13198 `196c5a9` Avoid printing to console during cache creation (sdaftuar)
+- #13075 `cb9bbf7` Remove 'account' API from wallet functional tests (jnewbery)
+- #13221 `ffa86af` travis: Rename the build stage `check_doc` to `lint` (practicalswift)
+- #13205 `3cbd25f` Remove spurious error log in `p2p_segwit.py` (jnewbery)
+- #13291 `536120e` Don't include torcontrol.cpp into the test file (Empact)
+- #13281 `2ac6315` Move linters to test/lint, add readme (MarcoFalke)
+- #13215 `f8a29ca` travis: Build tests on ubuntu 18.04 with docker (ken2812221)
+- #13349 `24f7011` bench: Don't return a bool from main (laanwj)
+- #13347 `87a9d03` travis: Skip cache for lint stage (MarcoFalke)
+- #13355 `0b1c0c4` Fix "gmake check" under OpenBSD 6.3 (probably `*BSD`): Avoid using GNU grep specific regexp handling (practicalswift)
+- #13353 `d4f6dac` Fixup setting of PATH env var (MarcoFalke)
+- #13352 `e24bf1c` Avoid checking reject code for now (MarcoFalke)
+- #13383 `2722a1f` bench: Use non-throwing parsedouble(…) instead of throwing boost::lexical_cast<double>(…) (practicalswift)
+- #13367 `264efdc` Increase includeconf test coverage (MarcoFalke)
+- #13404 `3d3d8ae` speed up of `tx_validationcache_tests` by reusing of CTransaction (lucash-dev)
+- #13421 `531a033` Remove `portseed_offset` from test runner (MarcoFalke)
+- #13440 `5315660` Log as utf-8 (MarcoFalke)
+- #13066 `fa4b906` Migrate verify-commits script to python, run in travis (ken2812221)
+- #13447 `4b1edd3` travis: Increase `travis_wait` time while verifying commits (ken2812221)
+- #13350 `f532d52` Add logging to provide anchor points when debugging p2p_sendheaders (lmanners)
+- #13406 `4382f19` travis: Change mac goal to all deploy (ken2812221)
+- #13457 `b222138` Drop variadic macro (MarcoFalke)
+- #13512 `3a45493` mininode: Expose connection state through `is_connected` (MarcoFalke)
+- #13496 `9ab4c2a` Harden lint-filenames.sh (wodry)
+- #13219 `08516e0` bench: Add block assemble benchmark (MarcoFalke)
+- #13530 `b1dc39d` bench: Add missing pow.h header (laanwj)
+- #12686 `2643fa5` Add -ftrapv to CFLAGS and CXXFLAGS when --enable-debug is used. Enable -ftrapv in Travis (practicalswift)
+- #12882 `d96bdd7` Make `test_bitcoin` pass under ThreadSanitzer (clang). Fix lock-order-inversion (potential deadlock) (practicalswift)
+- #13535 `2328039` `wallet_basic`: Specify minimum required amount for listunspent (MarcoFalke)
+- #13551 `c93c360` Fix incorrect documentation for test case `cuckoocache_hit_rate_ok` (practicalswift)
+- #13563 `b330f3f` bench: Simplify coinselection (promag)
+- #13517 `a6ed99a` Remove need to handle the network thread in tests (MarcoFalke)
+- #13522 `686e97a` Fix `p2p_sendheaders` race (jnewbery)
+- #13467 `3dc2dcf` Make `p2p_segwit` easier to debug (jnewbery)
+- #13598 `0212187` bench: Fix incorrect behaviour in prevector.cpp (AkioNak)
+- #13565 `b05ded1` Fix AreInputsStandard test to reference the proper scriptPubKey (Empact)
+- #13145 `d3dae3d` Use common getPath method to create temp directory in tests (winder)
+- #13645 `2ea7eb6` skip `rpc_zmq` functional test as necessary (jamesob)
+- #13626 `8f1106d` Fix some TODOs in `p2p_segwit` (MarcoFalke)
+- #13138 `8803c91` Remove accounts from `wallet_importprunedfunds.py` (jnewbery)
+- #13663 `cbc9b50` Avoid read/write to default datadir (MarcoFalke)
+- #13682 `f8a32a3` bench: Remove unused variable (practicalswift)
+- #13638 `6fcdb5e` Use `MAX_SCRIPT_ELEMENT_SIZE` from script.py (domob1812)
+- #13687 `9d26b69` travis: Check that ~/.bitcoin is never created (MarcoFalke)
+- #13715 `e1260a7` fixes mininode's P2PConnection sending messages on closing transport (marcoagner)
+- #13729 `aa9429a` travis: Avoid unnecessarily setting env variables on the lint build (Empact)
+- #13747 `ab28b5b` Skip P2PConnection's `is_closing()` check when not available (domob1812)
+- #13650 `7a9bca6` travis: Don't store debug info if --enable-debug is set (ken2812221)
+- #13711 `f98d1e0` bench: Add benchmark for unserialize prevector (AkioNak)
+- #13771 `365384f` travis: Retry to fetch docker image (MarcoFalke)
+- #13806 `4d550ff` Fix `bench/block_assemble` assert failure (jamesob)
+- #13779 `d25079a` travis: Improve readability of travis.yml and log outputs (scravy)
+- #13822 `0fb9c87` bench: Make coinselection output groups pass eligibility filter (achow101)
+- #13247 `e83d82a` Add tests to SingleThreadedSchedulerClient() and document the memory model (skeees)
+- #13811 `660abc1` travis: Run `bench_bitcoin` once (MarcoFalke)
+- #13837 `990e182` Extract `rpc_timewait` as test param (MarcoFalke)
+- #13851 `9c4324d` fix locale for lint-shell (scravy)
+- #13823 `489b51b` quote path in authproxy for external multiwallets (MarcoFalke)
+- #13849 `2b67354` travis: Use only travis jobs: instead of mix of jobs+matrix (scravy)
+- #13859 `2384323` Add emojis to `test_runner` path and wallet filename (MarcoFalke)
+- #13916 `8ac7125` `wait_for_verack` by default (MarcoFalke)
+- #13669 `f66e1c7` Cleanup `create_transaction` implementations (conscott)
+- #13924 `09ada21` Simplify comparison in `rpc_blockchain.py` (domob1812)
+- #13913 `a08533c` Remove redundant checkmempool/checkblockindex `extra_args` (MarcoFalke)
+- #13915 `a04888a` Add test for max number of entries in locator (MarcoFalke)
+- #13867 `1b04b55` Make extended tests pass on native Windows (MarcoFalke)
+- #13944 `0df7a6c` Port usage of deprecated optparse module to argparse module (Kvaciral)
+- #13928 `b8eb0df` blocktools enforce named args for amount (MarcoFalke)
+- #13054 `bffb35f` Enable automatic detection of undefined names in Python tests scripts. Remove wildcard imports (practicalswift)
+- #14069 `cf3d7f9` Use assert not `BOOST_CHECK_*` from multithreaded tests (skeees)
+- #14071 `fab0fbe` Stop txindex thread before calling destructor (MarcoFalke)
+
+### Miscellaneous
+- #11909 `8897135` contrib: Replace developer keys with list of pgp fingerprints (MarcoFalke)
+- #12394 `fe53d5f` gitian-builder.sh: fix --setup doc, since lxc is default (Sjors)
+- #12468 `294a766` Add missing newline in init.cpp log message (Aesti)
+- #12308 `dcfe218` contrib: Add support for out-of-tree builds in gen-manpages.sh (laanwj)
+- #12451 `aae64a2` Bump leveldb subtree (MarcoFalke)
+- #12527 `d77b4a7` gitian-build.sh: fix signProg being recognized as two parameters (ken2812221)
+- #12588 `d74b01d` utils: Remove deprecated pyzmq call from python zmq example (kosciej)
+- #10271 `bc67982` Use `std::thread::hardware_concurrency`, instead of Boost, to determine available cores (fanquake)
+- #12097 `14475e2` scripts: Lint-whitespace: use perl instead of grep -p (Sjors)
+- #12098 `17c44b2` scripts: Lint-whitespace: add param to check last n commits (Sjors)
+- #11900 `842f61a` script: Simplify checkminimalpush checks, add safety assert (instagibbs)
+- #12567 `bb98aec` util: Print timestamp strings in logs using iso 8601 formatting (practicalswift)
+- #12572 `d8d9162` script: Lint-whitespace: find errors more easily (AkioNak)
+- #10694 `ae5bcc7` Remove redundant code in MutateTxSign(CMutableTransaction&, const std::string&) (practicalswift)
+- #12659 `3d16f58` Improve Fatal LevelDB Log Messages (eklitzke)
+- #12643 `0f0229d` util: Remove unused `sync_chain` (MarcoFalke)
+- #12102 `7fb8fb4` Apply hardening measures in bitcoind systemd service file (Flowdalic)
+- #12652 `55f490a` bitcoin-cli: Provide a better error message when bitcoind is not running (practicalswift)
+- #12630 `c290508` Provide useful error message if datadir is not writable (murrayn)
+- #11881 `624bee9` Remove Python2 support (jnewbery)
+- #12821 `082e26c` contrib: Remove unused import string (MarcoFalke)
+- #12829 `252c1b0` Python3 fixup (jnewbery)
+- #12822 `ff48f62` Revert 7deba93bdc76616011a9f493cbc203d60084416f and fix expired-key-sigs properly (TheBlueMatt)
+- #12820 `5e53b80` contrib: Fix check-doc script regexes (MarcoFalke)
+- #12713 `4490871` Track negated options in the option parser (eklitzke)
+- #12708 `b2e5fe8` Make verify-commits.sh test that merges are clean (sipa)
+- #12891 `3190785` logging: Add lint-logs.sh to check for newline termination (jnewbery)
+- #12923 `a7cbe38` util: Pass `pthread_self()` to `pthread_setschedparam` instead of 0 (laanwj)
+- #12871 `fb17fae` Add shell script linting: Check for shellcheck warnings in shell scripts (practicalswift)
+- #12970 `5df84de` logging: Bypass timestamp formatting when not logging (theuni)
+- #12987 `fe8fa22` tests/tools: Enable additional Python flake8 rules for automatic linting via Travis (practicalswift)
+- #12972 `0782508` Add python3 script shebang lint (ken2812221)
+- #13004 `58bbc55` Print to console by default when not run with -daemon (practicalswift)
+- #13039 `8b4081a` Add logging and error handling for file syncing (laanwj)
+- #13020 `4741ca5` Consistently log CValidationState on call failure (Empact)
+- #13031 `826acc9` Fix for utiltime to compile with msvc (sipsorcery)
+- #13119 `81743b5` Remove script to clean up datadirs (MarcoFalke)
+- #12954 `5a66642` util: Refactor logging code into a global object (jimpo)
+- #12769 `35eb9d6` Add systemd service to bitcoind in debian package (ghost)
+- #13146 `0bc980b` rpcauth: Make it possible to provide a custom password (laanwj)
+- #13148 `b62b437` logging: Fix potential use-after-free in logprintstr(…) (practicalswift)
+- #13214 `0612d96` Enable Travis checking for two Python linting rules we are currently not violating (practicalswift)
+- #13197 `6826989` util: Warn about ignored recursive -includeconf calls (kallewoof)
+- #13176 `d9ebb63` Improve CRollingBloomFilter performance: replace modulus with FastMod (martinus)
+- #13228 `d792e47` Add script to detect circular dependencies between source modules (sipa)
+- #13320 `e08c130` Ensure gitian-build.sh uses bash (jhfrontz)
+- #13301 `e4082d5` lint: Add linter to error on `#include <*.cpp>` (Empact)
+- #13374 `56f6936` utils and libraries: checking for bitcoin address in translations (kaplanmaxe)
+- #13230 `7c32b41` Simplify include analysis by enforcing the developer guide's include syntax (practicalswift)
+- #13450 `32bf4c6` Add linter: Enforce the source code file naming convention described in the developer notes (practicalswift)
+- #13479 `fa2ea37` contrib: Fix cve-2018-12356 by hardening the regex (loganaden)
+- #13448 `a90ca40` Add linter: Make sure we explicitly open all text files using UTF-8 encoding in Python (practicalswift)
+- #13494 `d67eff8` Follow-up to #13454: Fix broken build by exporting `LC_ALL=C` (practicalswift)
+- #13510 `03f3925` Scripts and tools: Obsolete #!/bin/bash shebang (DesWurstes)
+- #13577 `c9eb8d1` logging: Avoid nstart may be used uninitialized in appinitmain warning (mruddy)
+- #13603 `453ae5e` bitcoin-tx: Stricter check for valid integers (domob1812)
+- #13118 `c05c93c` RPCAuth Detection in Logs (Linrono)
+- #13647 `4027ec1` Scripts and tools: Fix `BIND_NOW` check in security-check.py (conradoplg)
+- #13692 `f5d166a` contrib: Clone core repo in gitian-build (MarcoFalke)
+- #13699 `4c6d1b9` contrib: Correct version check (kallewoof)
+- #13695 `dcc0cff` lint: Add linter for circular dependencies (Empact)
+- #13733 `0d1ebf4` utils: Refactor argsmanager a little (AtsukiTak)
+- #13714 `29b4ee6` contrib: Add lxc network setup for bionic host (ken2812221)
+- #13764 `f8685f4` contrib: Fix test-security-check fail in ubuntu 18.04 (ken2812221)
+- #13809 `77168f7` contrib: Remove debian and rpm subfolder (MarcoFalke)
+- #13799 `230652c` Ignore unknown config file options; warn instead of error (sipa)
+- #13894 `df9f712` shutdown: Stop threads before resetting ptrs (MarcoFalke)
+- #13925 `71dec5c` Merge leveldb subtree (MarcoFalke)
+- #13939 `ef86f26` lint: Make format string linter understand basic template parameter syntax (practicalswift)
+- #14105 `eb202ea` util: Report parse errors in configuration file (laanwj)
+- #12604 `9903537` Add DynamicMemoryUsage() to CDBWrapper to estimate LevelDB memory use (eklitzke)
+- #12495 `047865e` Increase LevelDB `max_open_files` (eklitzke)
+- #12784 `e80716d` Fix bug in memory usage calculation (unintended integer division) (practicalswift)
+- #12618 `becd8dd` Set `SCHED_BATCH` priority on the loadblk thread (eklitzke)
+- #12854 `5ca1509` Add P2P, Network, and Qt categories to the desktop icon (luke-jr)
+- #11862 `4366f61` Network specific conf sections (ajtowns)
+- #13441 `4a7e64f` Prevent shared conf files from failing with different available options in different binaries (achow101)
+- #13471 `5eca4e8` For AVX2 code, also check for AVX, XSAVE, and OS support (sipa)
+- #13503 `c655b2c` Document FreeBSD quirk. Fix FreeBSD build: Use std::min<int>(…) to allow for compilation under certain FreeBSD versions (practicalswift)
+- #13725 `07ce278` Fix bitcoin-cli --version (Empact)
+
+### Documentation
+- #12306 `216f9a4` Improvements to UNIX documentation (axvr)
+- #12309 `895fbd7` Explain how to update chainTxData in release process (laanwj)
+- #12317 `85123be` Document method for reviewers to verify chainTxData (jnewbery)
+- #12331 `d32528e` Properly alphabetize output of CLI --help option (murrayn)
+- #12322 `c345148` Remove step making cloned repository world-writable for Windows build (murrayn)
+- #12354 `b264528` add gpg key for fivepiece (fivepiece)
+- #11761 `89005dd` initial QT documentation (Sjors)
+- #12232 `fdc2188` Improve "Turn Windows Features On or Off" step (MCFX2)
+- #12487 `4528f74` init: Remove translation for `-blockmaxsize` option help (laanwj)
+- #12546 `a4a5fc7` Minor improvements to Compatibility Notes (randolf)
+- #12434 `21e2670` dev-notes: Members should be initialized (MarcoFalke)
+- #12452 `71f56da` clarified systemd installation instructions in init.md for Ubuntu users (DaveFromBinary)
+- #12615 `1f93491` allow for SIGNER containing spaces (ken2812221)
+- #12603 `85424d7` PeerLogicValidation interface (jamesob)
+- #12581 `12ac2f0` Mention configure without wallet in FreeBSD instructions (dbolser)
+- #12619 `8a709fb` Give hint about gitian not able to download (kallewoof)
+- #12668 `de2fcaa` do update before fetching packages in WSL build guide (nvercamm)
+- #12586 `e7721e6` Update osx brew install instruction (fanquake)
+- #12760 `7466a26` Improve documentation on standard communication channels (jimpo)
+- #12797 `0415b1e` init: Fix help message for checkblockindex (MarcoFalke)
+- #12800 `2d97611` Add note about our preference for scoped enumerations ("enum class") (practicalswift)
+- #12798 `174d016` Refer to witness reserved value as spec. in the BIP (MarcoFalke)
+- #12759 `d3908e2` Improve formatting of developer notes (eklitzke)
+- #12877 `2b54155` Use bitcoind in Tor documentation (knoxcard)
+- #12896 `b15485e` Fix conflicting statements about initialization in developer notes (practicalswift)
+- #12850 `319991d` add qrencode to brew install instructions (buddilla)
+- #12007 `cd8e45b` Clarify the meaning of fee delta not being a fee rate in prioritisetransaction RPC (honzik666)
+- #12927 `06ead15` fixed link, replaced QT with Qt (trulex)
+- #12852 `ebd786b` devtools: Setup ots git integration (MarcoFalke)
+- #12933 `3cf76c2` Refine header include policy (MarcoFalke)
+- #12951 `6df0c6c` Fix comment in FindForkInGlobalIndex (jamesob)
+- #12982 `a63b4e3` Fix inconsistent namespace formatting guidelines (ryanofsky)
+- #13026 `9b3a67e` Fix include comment in src/interfaces/wallet.h (promag)
+- #13012 `d1e3c5e` Add comments for chainparams.h, validation.cpp (jamesob)
+- #13064 `569e381` List support for BIP173 in bips.md (sipa)
+- #12997 `646b7f6` build-windows: Switch to Artful, since Zesty is EOL (MarcoFalke)
+- #12384 `c5f7efe` Add version footnote to tor.md (Willtech)
+- #13165 `627c376` Mention good first issue list in CONTRIBUTING.md (fanquake)
+- #13295 `fb77310` Update OpenBSD build instructions for OpenBSD 6.3 (practicalswift)
+- #13340 `3a8e3f4` remove leftover check-doc documentation (fanquake)
+- #13346 `60f0358` update bitcoin-dot-org links in release-process.md (fanquake)
+- #13372 `f014933` split FreeBSD build instructions out of build-unix.md (steverusso)
+- #13366 `861de3b` Rename “OS X” to the newer “macOS” convention (giulio92)
+- #13369 `f8bcef3` update transifex doc link (mess110)
+- #13312 `b22115d` Add a note about the source code filename naming convention (practicalswift)
+- #13460 `1939536` Remove note to install all boost dev packages (MarcoFalke)
+- #13476 `9501938` Fix incorrect shell quoting in FreeBSD build instructions (murrayn)
+- #13402 `43fa355` Document validationinterace callback blocking deadlock potential (TheBlueMatt)
+- #13488 `d6cf4bd` Improve readability of "Squashing commits" (wodry)
+- #13531 `ee02deb` Clarify that mempool txiter is `const_iterator` (MarcoFalke)
+- #13418 `01f9098` More precise explanation of parameter onlynet (wodry)
+- #13592 `1756cb4` Modify policy to not translate command-line help (ken2812221)
+- #13588 `b77c38e` Improve doc of options addnode, connect, seednode (wodry)
+- #13614 `17e9106` Update command line help for -printtoconsole and -debuglogfile (satwo, fanquake)
+- #13605 `8cc048e` corrected text to reflect new(er) process of specifying fingerprints (jhfrontz)
+- #13481 `b641f60` Rewrite some validation docs as lock annotations (MarcoFalke)
+- #13680 `30640f8` Remove outdated comment about miner ignoring CPFP (jamesob)
+- #13625 `7146672` Add release notes for -printtoconsole and -debuglogfile changes (satwo)
+- #13718 `f7f574d` Specify preferred Python string formatting technique (masonicboom)
+- #12764 `10b9a81` Remove field in getblocktemplate help that has never been used (conscott)
+- #13742 `d2186b3` Adjust bitcoincore.org links (MarcoFalke)
+- #13706 `94dd89e` Minor improvements to release-process.md (MitchellCash)
+- #13775 `ef4fac0` Remove newlines from error message (practicalswift)
+- #13803 `feb7dd9` add note to contributor docs about warranted PR's (kallewoof)
+- #13814 `67af7ef` Add BIP174 to list of implemented BIPs (sipa)
+- #13835 `c1cba35` Fix memory consistency model in comment (skeees)
+- #13824 `aa30e4b` Remove outdated net comment (MarcoFalke)
+- #13853 `317477a` correct versions in dependencies.md (fanquake)
+- #13872 `37ab117` Reformat -help output for help2man (real-or-random)
+- #13717 `8c3c402` Link to python style guidelines from developer notes (masonicboom)
+- #13895 `1cd5f2c` fix GetWarnings docs to reflect behavior (Empact)
+- #13911 `3e3a50a` Revert translated string change, clarify wallet log messages (PierreRochard)
+- #13908 `d6faea4` upgrade rescan time warning from minutes to >1 hour (masonicboom)
+- #13905 `73a09b4` fixed bitcoin-cli -help output for help2man (hebasto)
+- #14100 `2936dbc` Change documentation for =0 for non-boolean options (laanwj)
+- #14096 `465a583` Add reference documentation for descriptors language (sipa)
+- #12757 `0c5f67b` Clarify include guard naming convention (practicalswift)
+- #13844 `d3325b0` Correct the help output for `-prune` (hebasto)
+
+Credits
+=======
+
+Thanks to everyone who directly contributed to this release:
+
+- 251
+- 532479301
+- Aaron Clauson
+- Akio Nakamura
+- Akira Takizawa
+- Alex Morcos
+- Alex Vear
+- Alexey Ivanov
+- Alin Rus
+- Andrea Comand
+- Andrew Chow
+- Anthony Towns
+- AtsukiTak
+- Ben Woosley
+- Bernhard M. Wiedemann
+- Brandon Ruggles
+- buddilla
+- ccdle12
+- Chris Moore
+- Chun Kuan Lee
+- Clem Taylor
+- Conor Scott
+- Conrado Gouvea
+- Cory Fields
+- Cristian Mircea Messel
+- ctp-tsteenholdt
+- Damian Williamson
+- Dan Bolser
+- Daniel Kraft
+- Darko Janković
+- DaveFromBinary
+- David A. Harding
+- DesWurstes
+- Dimitris Apostolou
+- donaloconnor
+- Douglas Roark
+- DrahtBot
+- Drew Rasmussen
+- e0
+- Ernest Hemingway
+- Ethan Heilman
+- Evan Klitzke
+- fanquake
+- Felix Wolfsteller
+- fivepiece
+- Florian Schmaus
+- Fuzzbawls
+- Gabriel Davidian
+- Giulio Lombardo
+- Gleb
+- Grady Laksmono
+- GreatSock
+- Gregory Maxwell
+- Gregory Sanders
+- Hennadii Stepanov
+- Henrik Jonsson
+- Indospace.io
+- James O'Beirne
+- Jan Čapek
+- Jeff Frontz
+- Jeff Rade
+- Jeremy Rubin
+- JeremyRand
+- Jesse Cohen
+- Jim Posen
+- joemphilips
+- John Bampton
+- John Newbery
+- johnlow95
+- Johnson Lau
+- Jonas Nick
+- Jonas Schnelli
+- João Barbosa
+- Jorge Timón
+- Josh Hartshorn
+- Julian Fleischer
+- kallewoof
+- Karel Bilek
+- Karl-Johan Alm
+- Ken Lee
+- Kevin Pan
+- Kosta Zertsekel
+- Kristaps Kaupe
+- Kvaciral
+- Lawrence Nahum
+- Linrono
+- lmanners
+- Loganaden Velvindron
+- Lowell Manners
+- lucash.dev@gmail.com
+- Luke Dashjr
+- lutangar
+- Marcin Jachymiak
+- marcoagner
+- MarcoFalke
+- Mark Erhardt
+- Mark Friedenbach
+- Martin Ankerl
+- Mason Simon
+- Matt Corallo
+- Matteo Sumberaz
+- Max Kaplan
+- MeshCollider
+- Michał Zabielski
+- Mitchell Cash
+- mruddy
+- mryandao
+- murrayn
+- Nick Vercammen
+- Nicolas Dorier
+- Nikolay Mitev
+- okayplanet
+- Pierre Rochard
+- Pieter Wuille
+- practicalswift
+- Qasim Javed
+- Randolf Richardson
+- Richard Kiss
+- Roman Zeyde
+- Russell Yanofsky
+- Samuel B. Atwood
+- Sebastian Kung
+- Sjors Provoost
+- Steve Lee
+- steverusso
+- Suhas Daftuar
+- Tamas Blummer
+- TheCharlatan
+- Thomas Kerin
+- Thomas Snider
+- Tim Ruffing
+- Varunram
+- Vasil Dimov
+- Will Ayd
+- William Robinson
+- winder
+- Wladimir J. van der Laan
+- wodry
+
+And to those that reported security issues:
+
+- awemany (for CVE-2018-17144, previously credited as "anonymous reporter")
+
+As well as everyone that helped translating on [Transifex](https://www.transifex.com/projects/p/bitcoin/).
diff --git a/doc/release-process.md b/doc/release-process.md
index 3ba622ee6d..f2fe44c8bf 100644
--- a/doc/release-process.md
+++ b/doc/release-process.md
@@ -296,6 +296,8 @@ bitcoin.org (see below for bitcoin.org update instructions).
- bitcoincore.org blog post
+ - bitcoincore.org RPC documentation update
+
- Update title of #bitcoin on Freenode IRC
- Optionally twitter, reddit /r/Bitcoin, ... but this will usually sort out itself
diff --git a/src/Makefile.am b/src/Makefile.am
index f7d7a5d377..7a2e9fa5e8 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -83,8 +83,11 @@ if BUILD_BITCOIND
bin_PROGRAMS += bitcoind
endif
-if BUILD_BITCOIN_UTILS
- bin_PROGRAMS += bitcoin-cli bitcoin-tx
+if BUILD_BITCOIN_CLI
+ bin_PROGRAMS += bitcoin-cli
+endif
+if BUILD_BITCOIN_TX
+ bin_PROGRAMS += bitcoin-tx
endif
.PHONY: FORCE check-symbols check-security
@@ -187,6 +190,7 @@ BITCOIN_CORE_H = \
validation.h \
validationinterface.h \
versionbits.h \
+ versionbitsinfo.h \
walletinitinterface.h \
wallet/coincontrol.h \
wallet/crypter.h \
@@ -400,6 +404,7 @@ libbitcoin_common_a_SOURCES = \
script/ismine.cpp \
script/sign.cpp \
script/standard.cpp \
+ versionbitsinfo.cpp \
warnings.cpp \
$(BITCOIN_CORE_H)
diff --git a/src/Makefile.test.include b/src/Makefile.test.include
index 269a6ff805..4506d5dd6a 100644
--- a/src/Makefile.test.include
+++ b/src/Makefile.test.include
@@ -51,6 +51,7 @@ BITCOIN_TESTS =\
test/cuckoocache_tests.cpp \
test/denialofservice_tests.cpp \
test/descriptor_tests.cpp \
+ test/fs_tests.cpp \
test/getarg_tests.cpp \
test/hash_tests.cpp \
test/key_io_tests.cpp \
@@ -110,11 +111,14 @@ BITCOIN_TESTS += \
wallet/test/psbt_wallet_tests.cpp \
wallet/test/wallet_tests.cpp \
wallet/test/wallet_crypto_tests.cpp \
- wallet/test/coinselector_tests.cpp
+ wallet/test/coinselector_tests.cpp \
+ wallet/test/init_tests.cpp
BITCOIN_TEST_SUITE += \
wallet/test/wallet_test_fixture.cpp \
- wallet/test/wallet_test_fixture.h
+ wallet/test/wallet_test_fixture.h \
+ wallet/test/init_test_fixture.cpp \
+ wallet/test/init_test_fixture.h
endif
test_test_bitcoin_SOURCES = $(BITCOIN_TEST_SUITE) $(BITCOIN_TESTS) $(JSON_TEST_FILES) $(RAW_TEST_FILES)
@@ -161,7 +165,7 @@ nodist_test_test_bitcoin_SOURCES = $(GENERATED_TEST_FILES)
$(BITCOIN_TESTS): $(GENERATED_TEST_FILES)
-CLEAN_BITCOIN_TEST = test/*.gcda test/*.gcno $(GENERATED_TEST_FILES)
+CLEAN_BITCOIN_TEST = test/*.gcda test/*.gcno $(GENERATED_TEST_FILES) $(BITCOIN_TESTS:=.log)
CLEANFILES += $(CLEAN_BITCOIN_TEST)
@@ -174,8 +178,10 @@ bitcoin_test_clean : FORCE
rm -f $(CLEAN_BITCOIN_TEST) $(test_test_bitcoin_OBJECTS) $(TEST_BINARY)
check-local: $(BITCOIN_TESTS:.cpp=.cpp.test)
+if BUILD_BITCOIN_TX
@echo "Running test/util/bitcoin-util-test.py..."
$(PYTHON) $(top_builddir)/test/util/bitcoin-util-test.py
+endif
@echo "Running test/util/rpcauth-test.py..."
$(PYTHON) $(top_builddir)/test/util/rpcauth-test.py
$(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C secp256k1 check
diff --git a/src/addrman.h b/src/addrman.h
index cf1949c28c..6d5780afa8 100644
--- a/src/addrman.h
+++ b/src/addrman.h
@@ -187,36 +187,37 @@ public:
*/
class CAddrMan
{
-private:
+protected:
//! critical section to protect the inner data structures
mutable CCriticalSection cs;
+private:
//! last used nId
- int nIdCount;
+ int nIdCount GUARDED_BY(cs);
//! table with information about all nIds
- std::map<int, CAddrInfo> mapInfo;
+ std::map<int, CAddrInfo> mapInfo GUARDED_BY(cs);
//! find an nId based on its network address
- std::map<CNetAddr, int> mapAddr;
+ std::map<CNetAddr, int> mapAddr GUARDED_BY(cs);
//! randomly-ordered vector of all nIds
- std::vector<int> vRandom;
+ std::vector<int> vRandom GUARDED_BY(cs);
// number of "tried" entries
- int nTried;
+ int nTried GUARDED_BY(cs);
//! list of "tried" buckets
- int vvTried[ADDRMAN_TRIED_BUCKET_COUNT][ADDRMAN_BUCKET_SIZE];
+ int vvTried[ADDRMAN_TRIED_BUCKET_COUNT][ADDRMAN_BUCKET_SIZE] GUARDED_BY(cs);
//! number of (unique) "new" entries
- int nNew;
+ int nNew GUARDED_BY(cs);
//! list of "new" buckets
- int vvNew[ADDRMAN_NEW_BUCKET_COUNT][ADDRMAN_BUCKET_SIZE];
+ int vvNew[ADDRMAN_NEW_BUCKET_COUNT][ADDRMAN_BUCKET_SIZE] GUARDED_BY(cs);
//! last time Good was called (memory only)
- int64_t nLastGood;
+ int64_t nLastGood GUARDED_BY(cs);
//! Holds addrs inserted into tried table that collide with existing entries. Test-before-evict discipline used to resolve these collisions.
std::set<int> m_tried_collisions;
@@ -229,58 +230,58 @@ protected:
FastRandomContext insecure_rand;
//! Find an entry.
- CAddrInfo* Find(const CNetAddr& addr, int *pnId = nullptr);
+ CAddrInfo* Find(const CNetAddr& addr, int *pnId = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs);
//! find an entry, creating it if necessary.
//! nTime and nServices of the found node are updated, if necessary.
- CAddrInfo* Create(const CAddress &addr, const CNetAddr &addrSource, int *pnId = nullptr);
+ CAddrInfo* Create(const CAddress &addr, const CNetAddr &addrSource, int *pnId = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs);
//! Swap two elements in vRandom.
- void SwapRandom(unsigned int nRandomPos1, unsigned int nRandomPos2);
+ void SwapRandom(unsigned int nRandomPos1, unsigned int nRandomPos2) EXCLUSIVE_LOCKS_REQUIRED(cs);
//! Move an entry from the "new" table(s) to the "tried" table
- void MakeTried(CAddrInfo& info, int nId);
+ void MakeTried(CAddrInfo& info, int nId) EXCLUSIVE_LOCKS_REQUIRED(cs);
//! Delete an entry. It must not be in tried, and have refcount 0.
- void Delete(int nId);
+ void Delete(int nId) EXCLUSIVE_LOCKS_REQUIRED(cs);
//! Clear a position in a "new" table. This is the only place where entries are actually deleted.
- void ClearNew(int nUBucket, int nUBucketPos);
+ void ClearNew(int nUBucket, int nUBucketPos) EXCLUSIVE_LOCKS_REQUIRED(cs);
//! Mark an entry "good", possibly moving it from "new" to "tried".
- void Good_(const CService &addr, bool test_before_evict, int64_t time);
+ void Good_(const CService &addr, bool test_before_evict, int64_t time) EXCLUSIVE_LOCKS_REQUIRED(cs);
//! Add an entry to the "new" table.
- bool Add_(const CAddress &addr, const CNetAddr& source, int64_t nTimePenalty);
+ bool Add_(const CAddress &addr, const CNetAddr& source, int64_t nTimePenalty) EXCLUSIVE_LOCKS_REQUIRED(cs);
//! Mark an entry as attempted to connect.
- void Attempt_(const CService &addr, bool fCountFailure, int64_t nTime);
+ void Attempt_(const CService &addr, bool fCountFailure, int64_t nTime) EXCLUSIVE_LOCKS_REQUIRED(cs);
//! Select an address to connect to, if newOnly is set to true, only the new table is selected from.
- CAddrInfo Select_(bool newOnly);
+ CAddrInfo Select_(bool newOnly) EXCLUSIVE_LOCKS_REQUIRED(cs);
//! See if any to-be-evicted tried table entries have been tested and if so resolve the collisions.
- void ResolveCollisions_();
+ void ResolveCollisions_() EXCLUSIVE_LOCKS_REQUIRED(cs);
//! Return a random to-be-evicted tried table address.
- CAddrInfo SelectTriedCollision_();
+ CAddrInfo SelectTriedCollision_() EXCLUSIVE_LOCKS_REQUIRED(cs);
//! Wraps GetRandInt to allow tests to override RandomInt and make it determinismistic.
virtual int RandomInt(int nMax);
#ifdef DEBUG_ADDRMAN
//! Perform consistency check. Returns an error code or zero.
- int Check_();
+ int Check_() EXCLUSIVE_LOCKS_REQUIRED(cs);
#endif
//! Select several addresses at once.
- void GetAddr_(std::vector<CAddress> &vAddr);
+ void GetAddr_(std::vector<CAddress> &vAddr) EXCLUSIVE_LOCKS_REQUIRED(cs);
//! Mark an entry as currently-connected-to.
- void Connected_(const CService &addr, int64_t nTime);
+ void Connected_(const CService &addr, int64_t nTime) EXCLUSIVE_LOCKS_REQUIRED(cs);
//! Update an entry's service bits.
- void SetServices_(const CService &addr, ServiceFlags nServices);
+ void SetServices_(const CService &addr, ServiceFlags nServices) EXCLUSIVE_LOCKS_REQUIRED(cs);
public:
/**
diff --git a/src/amount.h b/src/amount.h
index 2bd367cba2..449fd1b15f 100644
--- a/src/amount.h
+++ b/src/amount.h
@@ -12,7 +12,6 @@
typedef int64_t CAmount;
static const CAmount COIN = 100000000;
-static const CAmount CENT = 1000000;
/** No amount larger than this (in satoshi) is valid.
*
diff --git a/src/arith_uint256.cpp b/src/arith_uint256.cpp
index 13fa176f8b..791dad7a60 100644
--- a/src/arith_uint256.cpp
+++ b/src/arith_uint256.cpp
@@ -176,7 +176,7 @@ unsigned int base_uint<BITS>::bits() const
for (int pos = WIDTH - 1; pos >= 0; pos--) {
if (pn[pos]) {
for (int nbits = 31; nbits > 0; nbits--) {
- if (pn[pos] & 1 << nbits)
+ if (pn[pos] & 1U << nbits)
return 32 * pos + nbits + 1;
}
return 32 * pos + 1;
diff --git a/src/bench/ccoins_caching.cpp b/src/bench/ccoins_caching.cpp
index db303eeead..b8d82c0a89 100644
--- a/src/bench/ccoins_caching.cpp
+++ b/src/bench/ccoins_caching.cpp
@@ -12,8 +12,8 @@
// FIXME: Dedup with SetupDummyInputs in test/transaction_tests.cpp.
//
// Helper: create two dummy transactions, each with
-// two outputs. The first has 11 and 50 CENT outputs
-// paid to a TX_PUBKEY, the second 21 and 22 CENT outputs
+// two outputs. The first has 11 and 50 COIN outputs
+// paid to a TX_PUBKEY, the second 21 and 22 COIN outputs
// paid to a TX_PUBKEYHASH.
//
static std::vector<CMutableTransaction>
@@ -31,16 +31,16 @@ SetupDummyInputs(CBasicKeyStore& keystoreRet, CCoinsViewCache& coinsRet)
// Create some dummy input transactions
dummyTransactions[0].vout.resize(2);
- dummyTransactions[0].vout[0].nValue = 11 * CENT;
+ dummyTransactions[0].vout[0].nValue = 11 * COIN;
dummyTransactions[0].vout[0].scriptPubKey << ToByteVector(key[0].GetPubKey()) << OP_CHECKSIG;
- dummyTransactions[0].vout[1].nValue = 50 * CENT;
+ dummyTransactions[0].vout[1].nValue = 50 * COIN;
dummyTransactions[0].vout[1].scriptPubKey << ToByteVector(key[1].GetPubKey()) << OP_CHECKSIG;
AddCoins(coinsRet, dummyTransactions[0], 0);
dummyTransactions[1].vout.resize(2);
- dummyTransactions[1].vout[0].nValue = 21 * CENT;
+ dummyTransactions[1].vout[0].nValue = 21 * COIN;
dummyTransactions[1].vout[0].scriptPubKey = GetScriptForDestination(key[2].GetPubKey().GetID());
- dummyTransactions[1].vout[1].nValue = 22 * CENT;
+ dummyTransactions[1].vout[1].nValue = 22 * COIN;
dummyTransactions[1].vout[1].scriptPubKey = GetScriptForDestination(key[3].GetPubKey().GetID());
AddCoins(coinsRet, dummyTransactions[1], 0);
@@ -72,7 +72,7 @@ static void CCoinsCaching(benchmark::State& state)
t1.vin[2].prevout.n = 1;
t1.vin[2].scriptSig << std::vector<unsigned char>(65, 0) << std::vector<unsigned char>(33, 4);
t1.vout.resize(2);
- t1.vout[0].nValue = 90 * CENT;
+ t1.vout[0].nValue = 90 * COIN;
t1.vout[0].scriptPubKey << OP_1;
// Benchmark.
@@ -80,7 +80,7 @@ static void CCoinsCaching(benchmark::State& state)
bool success = AreInputsStandard(t1, coins);
assert(success);
CAmount value = coins.GetValueIn(t1);
- assert(value == (50 + 21 + 22) * CENT);
+ assert(value == (50 + 21 + 22) * COIN);
}
}
diff --git a/src/bench/checkblock.cpp b/src/bench/checkblock.cpp
index 6f03581c4b..e325333c01 100644
--- a/src/bench/checkblock.cpp
+++ b/src/bench/checkblock.cpp
@@ -20,7 +20,7 @@ namespace block_bench {
static void DeserializeBlockTest(benchmark::State& state)
{
CDataStream stream((const char*)block_bench::block413567,
- (const char*)&block_bench::block413567[sizeof(block_bench::block413567)],
+ (const char*)block_bench::block413567 + sizeof(block_bench::block413567),
SER_NETWORK, PROTOCOL_VERSION);
char a = '\0';
stream.write(&a, 1); // Prevent compaction
@@ -36,7 +36,7 @@ static void DeserializeBlockTest(benchmark::State& state)
static void DeserializeAndCheckBlockTest(benchmark::State& state)
{
CDataStream stream((const char*)block_bench::block413567,
- (const char*)&block_bench::block413567[sizeof(block_bench::block413567)],
+ (const char*)block_bench::block413567 + sizeof(block_bench::block413567),
SER_NETWORK, PROTOCOL_VERSION);
char a = '\0';
stream.write(&a, 1); // Prevent compaction
diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp
index 09507fd249..f466505114 100644
--- a/src/bitcoin-cli.cpp
+++ b/src/bitcoin-cli.cpp
@@ -17,6 +17,7 @@
#include <memory>
#include <stdio.h>
+#include <tuple>
#include <event2/buffer.h>
#include <event2/keyvalq_struct.h>
@@ -511,6 +512,10 @@ static int CommandLineRPC(int argc, char *argv[])
int main(int argc, char* argv[])
{
+#ifdef WIN32
+ util::WinCmdLineArgs winArgs;
+ std::tie(argc, argv) = winArgs.get();
+#endif
SetupEnvironment();
if (!SetupNetworking()) {
fprintf(stderr, "Error: Initializing networking failed\n");
diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp
index 9ee3e8eee7..a3fcb87675 100644
--- a/src/bitcoin-tx.cpp
+++ b/src/bitcoin-tx.cpp
@@ -240,10 +240,10 @@ static void MutateTxAddInput(CMutableTransaction& tx, const std::string& strInpu
throw std::runtime_error("TX input missing separator");
// extract and validate TXID
- std::string strTxid = vStrInputParts[0];
- if ((strTxid.size() != 64) || !IsHex(strTxid))
+ uint256 txid;
+ if (!ParseHashStr(vStrInputParts[0], txid)) {
throw std::runtime_error("invalid TX input txid");
- uint256 txid(uint256S(strTxid));
+ }
static const unsigned int minTxOutSz = 9;
static const unsigned int maxVout = MAX_BLOCK_WEIGHT / (WITNESS_SCALE_FACTOR * minTxOutSz);
@@ -590,7 +590,10 @@ static void MutateTxSign(CMutableTransaction& tx, const std::string& flagStr)
if (!prevOut.checkObject(types))
throw std::runtime_error("prevtxs internal object typecheck fail");
- uint256 txid = ParseHashStr(prevOut["txid"].get_str(), "txid");
+ uint256 txid;
+ if (!ParseHashStr(prevOut["txid"].get_str(), txid)) {
+ throw std::runtime_error("txid must be hexadecimal string (not '" + prevOut["txid"].get_str() + "')");
+ }
const int nOut = prevOut["vout"].get_int();
if (nOut < 0)
diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp
index bf04d95b50..18fcd9bc2a 100644
--- a/src/bitcoind.cpp
+++ b/src/bitcoind.cpp
@@ -185,6 +185,10 @@ static bool AppInit(int argc, char* argv[])
int main(int argc, char* argv[])
{
+#ifdef WIN32
+ util::WinCmdLineArgs winArgs;
+ std::tie(argc, argv) = winArgs.get();
+#endif
SetupEnvironment();
// Connect bitcoind signal handlers
diff --git a/src/chainparams.cpp b/src/chainparams.cpp
index b80cc2c259..0574e2395e 100644
--- a/src/chainparams.cpp
+++ b/src/chainparams.cpp
@@ -10,9 +10,13 @@
#include <tinyformat.h>
#include <util.h>
#include <utilstrencodings.h>
+#include <versionbitsinfo.h>
#include <assert.h>
+#include <boost/algorithm/string/classification.hpp>
+#include <boost/algorithm/string/split.hpp>
+
static CBlock CreateGenesisBlock(const char* pszTimestamp, const CScript& genesisOutputScript, uint32_t nTime, uint32_t nNonce, uint32_t nBits, int32_t nVersion, const CAmount& genesisReward)
{
CMutableTransaction txNew;
@@ -52,12 +56,6 @@ static CBlock CreateGenesisBlock(uint32_t nTime, uint32_t nNonce, uint32_t nBits
return CreateGenesisBlock(pszTimestamp, genesisOutputScript, nTime, nNonce, nBits, nVersion, genesisReward);
}
-void CChainParams::UpdateVersionBitsParameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout)
-{
- consensus.vDeployments[d].nStartTime = nStartTime;
- consensus.vDeployments[d].nTimeout = nTimeout;
-}
-
/**
* Main network
*/
@@ -270,7 +268,7 @@ public:
*/
class CRegTestParams : public CChainParams {
public:
- CRegTestParams() {
+ explicit CRegTestParams(const ArgsManager& args) {
strNetworkID = "regtest";
consensus.nSubsidyHalvingInterval = 150;
consensus.BIP16Exception = uint256();
@@ -308,6 +306,8 @@ public:
nDefaultPort = 18444;
nPruneAfterHeight = 1000;
+ UpdateVersionBitsParametersFromArgs(args);
+
genesis = CreateGenesisBlock(1296688602, 2, 0x207fffff, 1, 50 * COIN);
consensus.hashGenesisBlock = genesis.GetHash();
assert(consensus.hashGenesisBlock == uint256S("0x0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206"));
@@ -343,23 +343,65 @@ public:
/* enable fallback fee on regtest */
m_fallback_fee_enabled = true;
}
+
+ /**
+ * Allows modifying the Version Bits regtest parameters.
+ */
+ void UpdateVersionBitsParameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout)
+ {
+ consensus.vDeployments[d].nStartTime = nStartTime;
+ consensus.vDeployments[d].nTimeout = nTimeout;
+ }
+ void UpdateVersionBitsParametersFromArgs(const ArgsManager& args);
};
-static std::unique_ptr<CChainParams> globalChainParams;
+void CRegTestParams::UpdateVersionBitsParametersFromArgs(const ArgsManager& args)
+{
+ if (!args.IsArgSet("-vbparams")) return;
+
+ for (const std::string& strDeployment : args.GetArgs("-vbparams")) {
+ std::vector<std::string> vDeploymentParams;
+ boost::split(vDeploymentParams, strDeployment, boost::is_any_of(":"));
+ if (vDeploymentParams.size() != 3) {
+ throw std::runtime_error("Version bits parameters malformed, expecting deployment:start:end");
+ }
+ int64_t nStartTime, nTimeout;
+ if (!ParseInt64(vDeploymentParams[1], &nStartTime)) {
+ throw std::runtime_error(strprintf("Invalid nStartTime (%s)", vDeploymentParams[1]));
+ }
+ if (!ParseInt64(vDeploymentParams[2], &nTimeout)) {
+ throw std::runtime_error(strprintf("Invalid nTimeout (%s)", vDeploymentParams[2]));
+ }
+ bool found = false;
+ for (int j=0; j < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++j) {
+ if (vDeploymentParams[0] == VersionBitsDeploymentInfo[j].name) {
+ UpdateVersionBitsParameters(Consensus::DeploymentPos(j), nStartTime, nTimeout);
+ found = true;
+ LogPrintf("Setting version bits activation parameters for %s to start=%ld, timeout=%ld\n", vDeploymentParams[0], nStartTime, nTimeout);
+ break;
+ }
+ }
+ if (!found) {
+ throw std::runtime_error(strprintf("Invalid deployment (%s)", vDeploymentParams[0]));
+ }
+ }
+}
+
+static std::unique_ptr<const CChainParams> globalChainParams;
const CChainParams &Params() {
assert(globalChainParams);
return *globalChainParams;
}
-std::unique_ptr<CChainParams> CreateChainParams(const std::string& chain)
+std::unique_ptr<const CChainParams> CreateChainParams(const std::string& chain)
{
if (chain == CBaseChainParams::MAIN)
return std::unique_ptr<CChainParams>(new CMainParams());
else if (chain == CBaseChainParams::TESTNET)
return std::unique_ptr<CChainParams>(new CTestNetParams());
else if (chain == CBaseChainParams::REGTEST)
- return std::unique_ptr<CChainParams>(new CRegTestParams());
+ return std::unique_ptr<CChainParams>(new CRegTestParams(gArgs));
throw std::runtime_error(strprintf("%s: Unknown chain %s.", __func__, chain));
}
@@ -368,8 +410,3 @@ void SelectParams(const std::string& network)
SelectBaseParams(network);
globalChainParams = CreateChainParams(network);
}
-
-void UpdateVersionBitsParameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout)
-{
- globalChainParams->UpdateVersionBitsParameters(d, nStartTime, nTimeout);
-}
diff --git a/src/chainparams.h b/src/chainparams.h
index 722e52ff40..19818b40af 100644
--- a/src/chainparams.h
+++ b/src/chainparams.h
@@ -80,7 +80,6 @@ public:
const std::vector<SeedSpec6>& FixedSeeds() const { return vFixedSeeds; }
const CCheckpointData& Checkpoints() const { return checkpointData; }
const ChainTxData& TxData() const { return chainTxData; }
- void UpdateVersionBitsParameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout);
protected:
CChainParams() {}
@@ -107,7 +106,7 @@ protected:
* @returns a CChainParams* of the chosen chain.
* @throws a std::runtime_error if the chain is not supported.
*/
-std::unique_ptr<CChainParams> CreateChainParams(const std::string& chain);
+std::unique_ptr<const CChainParams> CreateChainParams(const std::string& chain);
/**
* Return the currently selected parameters. This won't change after app
@@ -121,9 +120,4 @@ const CChainParams &Params();
*/
void SelectParams(const std::string& chain);
-/**
- * Allows modifying the Version Bits regtest parameters.
- */
-void UpdateVersionBitsParameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout);
-
#endif // BITCOIN_CHAINPARAMS_H
diff --git a/src/chainparamsbase.cpp b/src/chainparamsbase.cpp
index e9e8ce03b4..870640e77d 100644
--- a/src/chainparamsbase.cpp
+++ b/src/chainparamsbase.cpp
@@ -20,6 +20,7 @@ void SetupChainParamsBaseOptions()
gArgs.AddArg("-regtest", "Enter regression test mode, which uses a special chain in which blocks can be solved instantly. "
"This is intended for regression testing tools and app development.", true, OptionsCategory::CHAINPARAMS);
gArgs.AddArg("-testnet", "Use the test chain", false, OptionsCategory::CHAINPARAMS);
+ gArgs.AddArg("-vbparams=deployment:start:end", "Use given start/end times for specified version bits deployment (regtest-only)", true, OptionsCategory::CHAINPARAMS);
}
static std::unique_ptr<CBaseChainParams> globalChainBaseParams;
diff --git a/src/core_io.h b/src/core_io.h
index d53a45c0cb..2c3b64d81e 100644
--- a/src/core_io.h
+++ b/src/core_io.h
@@ -25,7 +25,16 @@ std::string ScriptToAsmStr(const CScript& script, const bool fAttemptSighashDeco
bool DecodeHexTx(CMutableTransaction& tx, const std::string& hex_tx, bool try_no_witness = false, bool try_witness = true);
bool DecodeHexBlk(CBlock&, const std::string& strHexBlk);
bool DecodeHexBlockHeader(CBlockHeader&, const std::string& hex_header);
-uint256 ParseHashStr(const std::string&, const std::string& strName);
+
+/**
+ * Parse a hex string into 256 bits
+ * @param[in] strHex a hex-formatted, 64-character string
+ * @param[out] result the result of the parasing
+ * @returns true if successful, false if not
+ *
+ * @see ParseHashV for an RPC-oriented version of this
+ */
+bool ParseHashStr(const std::string& strHex, uint256& result);
std::vector<unsigned char> ParseHexUV(const UniValue& v, const std::string& strName);
bool DecodePSBT(PartiallySignedTransaction& psbt, const std::string& base64_tx, std::string& error);
int ParseSighashString(const UniValue& sighash);
diff --git a/src/core_read.cpp b/src/core_read.cpp
index b02016c014..301f99bc1c 100644
--- a/src/core_read.cpp
+++ b/src/core_read.cpp
@@ -193,14 +193,13 @@ bool DecodePSBT(PartiallySignedTransaction& psbt, const std::string& base64_tx,
return true;
}
-uint256 ParseHashStr(const std::string& strHex, const std::string& strName)
+bool ParseHashStr(const std::string& strHex, uint256& result)
{
- if (!IsHex(strHex)) // Note: IsHex("") is false
- throw std::runtime_error(strName + " must be hexadecimal string (not '" + strHex + "')");
+ if ((strHex.size() != 64) || !IsHex(strHex))
+ return false;
- uint256 result;
result.SetHex(strHex);
- return result;
+ return true;
}
std::vector<unsigned char> ParseHexUV(const UniValue& v, const std::string& strName)
diff --git a/src/fs.cpp b/src/fs.cpp
index df79b5e3df..a146107c4c 100644
--- a/src/fs.cpp
+++ b/src/fs.cpp
@@ -113,4 +113,106 @@ std::string get_filesystem_error_message(const fs::filesystem_error& e)
#endif
}
+#ifdef WIN32
+#ifdef __GLIBCXX__
+
+// reference: https://github.com/gcc-mirror/gcc/blob/gcc-7_3_0-release/libstdc%2B%2B-v3/include/std/fstream#L270
+
+static std::string openmodeToStr(std::ios_base::openmode mode)
+{
+ switch (mode & ~std::ios_base::ate) {
+ case std::ios_base::out:
+ case std::ios_base::out | std::ios_base::trunc:
+ return "w";
+ case std::ios_base::out | std::ios_base::app:
+ case std::ios_base::app:
+ return "a";
+ case std::ios_base::in:
+ return "r";
+ case std::ios_base::in | std::ios_base::out:
+ return "r+";
+ case std::ios_base::in | std::ios_base::out | std::ios_base::trunc:
+ return "w+";
+ case std::ios_base::in | std::ios_base::out | std::ios_base::app:
+ case std::ios_base::in | std::ios_base::app:
+ return "a+";
+ case std::ios_base::out | std::ios_base::binary:
+ case std::ios_base::out | std::ios_base::trunc | std::ios_base::binary:
+ return "wb";
+ case std::ios_base::out | std::ios_base::app | std::ios_base::binary:
+ case std::ios_base::app | std::ios_base::binary:
+ return "ab";
+ case std::ios_base::in | std::ios_base::binary:
+ return "rb";
+ case std::ios_base::in | std::ios_base::out | std::ios_base::binary:
+ return "r+b";
+ case std::ios_base::in | std::ios_base::out | std::ios_base::trunc | std::ios_base::binary:
+ return "w+b";
+ case std::ios_base::in | std::ios_base::out | std::ios_base::app | std::ios_base::binary:
+ case std::ios_base::in | std::ios_base::app | std::ios_base::binary:
+ return "a+b";
+ default:
+ return std::string();
+ }
+}
+
+void ifstream::open(const fs::path& p, std::ios_base::openmode mode)
+{
+ close();
+ m_file = fsbridge::fopen(p, openmodeToStr(mode).c_str());
+ if (m_file == nullptr) {
+ return;
+ }
+ m_filebuf = __gnu_cxx::stdio_filebuf<char>(m_file, mode);
+ rdbuf(&m_filebuf);
+ if (mode & std::ios_base::ate) {
+ seekg(0, std::ios_base::end);
+ }
+}
+
+void ifstream::close()
+{
+ if (m_file != nullptr) {
+ m_filebuf.close();
+ fclose(m_file);
+ }
+ m_file = nullptr;
+}
+
+void ofstream::open(const fs::path& p, std::ios_base::openmode mode)
+{
+ close();
+ m_file = fsbridge::fopen(p, openmodeToStr(mode).c_str());
+ if (m_file == nullptr) {
+ return;
+ }
+ m_filebuf = __gnu_cxx::stdio_filebuf<char>(m_file, mode);
+ rdbuf(&m_filebuf);
+ if (mode & std::ios_base::ate) {
+ seekp(0, std::ios_base::end);
+ }
+}
+
+void ofstream::close()
+{
+ if (m_file != nullptr) {
+ m_filebuf.close();
+ fclose(m_file);
+ }
+ m_file = nullptr;
+}
+#else // __GLIBCXX__
+
+static_assert(sizeof(*fs::path().BOOST_FILESYSTEM_C_STR) == sizeof(wchar_t),
+ "Warning: This build is using boost::filesystem ofstream and ifstream "
+ "implementations which will fail to open paths containing multibyte "
+ "characters. You should delete this static_assert to ignore this warning, "
+ "or switch to a different C++ standard library like the Microsoft C++ "
+ "Standard Library (where boost uses non-standard extensions to construct "
+ "stream objects with wide filenames), or the GNU libstdc++ library (where "
+ "a more complicated workaround has been implemented above).");
+
+#endif // __GLIBCXX__
+#endif // WIN32
+
} // fsbridge
diff --git a/src/fs.h b/src/fs.h
index 5492bdd4ec..bdccb15232 100644
--- a/src/fs.h
+++ b/src/fs.h
@@ -7,10 +7,12 @@
#include <stdio.h>
#include <string>
+#if defined WIN32 && defined __GLIBCXX__
+#include <ext/stdio_filebuf.h>
+#endif
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
-#include <boost/filesystem/detail/utf8_codecvt_facet.hpp>
/** Filesystem operations and types */
namespace fs = boost::filesystem;
@@ -40,6 +42,54 @@ namespace fsbridge {
};
std::string get_filesystem_error_message(const fs::filesystem_error& e);
+
+ // GNU libstdc++ specific workaround for opening UTF-8 paths on Windows.
+ //
+ // On Windows, it is only possible to reliably access multibyte file paths through
+ // `wchar_t` APIs, not `char` APIs. But because the C++ standard doesn't
+ // require ifstream/ofstream `wchar_t` constructors, and the GNU library doesn't
+ // provide them (in contrast to the Microsoft C++ library, see
+ // https://stackoverflow.com/questions/821873/how-to-open-an-stdfstream-ofstream-or-ifstream-with-a-unicode-filename/822032#822032),
+ // Boost is forced to fall back to `char` constructors which may not work properly.
+ //
+ // Work around this issue by creating stream objects with `_wfopen` in
+ // combination with `__gnu_cxx::stdio_filebuf`. This workaround can be removed
+ // with an upgrade to C++17, where streams can be constructed directly from
+ // `std::filesystem::path` objects.
+
+#if defined WIN32 && defined __GLIBCXX__
+ class ifstream : public std::istream
+ {
+ public:
+ ifstream() = default;
+ explicit ifstream(const fs::path& p, std::ios_base::openmode mode = std::ios_base::in) { open(p, mode); }
+ ~ifstream() { close(); }
+ void open(const fs::path& p, std::ios_base::openmode mode = std::ios_base::in);
+ bool is_open() { return m_filebuf.is_open(); }
+ void close();
+
+ private:
+ __gnu_cxx::stdio_filebuf<char> m_filebuf;
+ FILE* m_file = nullptr;
+ };
+ class ofstream : public std::ostream
+ {
+ public:
+ ofstream() = default;
+ explicit ofstream(const fs::path& p, std::ios_base::openmode mode = std::ios_base::out) { open(p, mode); }
+ ~ofstream() { close(); }
+ void open(const fs::path& p, std::ios_base::openmode mode = std::ios_base::out);
+ bool is_open() { return m_filebuf.is_open(); }
+ void close();
+
+ private:
+ __gnu_cxx::stdio_filebuf<char> m_filebuf;
+ FILE* m_file = nullptr;
+ };
+#else // !(WIN32 && __GLIBCXX__)
+ typedef fs::ifstream ifstream;
+ typedef fs::ofstream ofstream;
+#endif // WIN32 && __GLIBCXX__
};
#endif // BITCOIN_FS_H
diff --git a/src/init.cpp b/src/init.cpp
index d10edbd8b6..f9efaf7dc1 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -323,7 +323,7 @@ void SetupServerArgs()
// Hidden Options
std::vector<std::string> hidden_args = {"-h", "-help",
- "-dbcrashratio", "-forcecompactdb", "-usehd",
+ "-dbcrashratio", "-forcecompactdb",
// GUI args. These will be overwritten by SetupUIArgs for the GUI
"-allowselfsignedrootcertificates", "-choosedatadir", "-lang=<lang>", "-min", "-resetguisettings", "-rootcertificates=<file>", "-splash", "-uiplatform"};
@@ -445,7 +445,6 @@ void SetupServerArgs()
gArgs.AddArg("-limitancestorsize=<n>", strprintf("Do not accept transactions whose size with all in-mempool ancestors exceeds <n> kilobytes (default: %u)", DEFAULT_ANCESTOR_SIZE_LIMIT), true, OptionsCategory::DEBUG_TEST);
gArgs.AddArg("-limitdescendantcount=<n>", strprintf("Do not accept transactions if any ancestor would have <n> or more in-mempool descendants (default: %u)", DEFAULT_DESCENDANT_LIMIT), true, OptionsCategory::DEBUG_TEST);
gArgs.AddArg("-limitdescendantsize=<n>", strprintf("Do not accept transactions if any ancestor would have more than <n> kilobytes of in-mempool descendants (default: %u).", DEFAULT_DESCENDANT_SIZE_LIMIT), true, OptionsCategory::DEBUG_TEST);
- gArgs.AddArg("-vbparams=deployment:start:end", "Use given start/end times for specified version bits deployment (regtest-only)", true, OptionsCategory::DEBUG_TEST);
gArgs.AddArg("-addrmantest", "Allows to test address relay on localhost", true, OptionsCategory::DEBUG_TEST);
gArgs.AddArg("-debug=<category>", "Output debugging information (default: -nodebug, supplying <category> is optional). "
"If <category> is not supplied or if <category> = 1, output all debugging information. <category> can be: " + ListLogCategories() + ".", false, OptionsCategory::DEBUG_TEST);
@@ -1101,39 +1100,6 @@ bool AppInitParameterInteraction()
fEnableReplacement = (std::find(vstrReplacementModes.begin(), vstrReplacementModes.end(), "fee") != vstrReplacementModes.end());
}
- if (gArgs.IsArgSet("-vbparams")) {
- // Allow overriding version bits parameters for testing
- if (!chainparams.MineBlocksOnDemand()) {
- return InitError("Version bits parameters may only be overridden on regtest.");
- }
- for (const std::string& strDeployment : gArgs.GetArgs("-vbparams")) {
- std::vector<std::string> vDeploymentParams;
- boost::split(vDeploymentParams, strDeployment, boost::is_any_of(":"));
- if (vDeploymentParams.size() != 3) {
- return InitError("Version bits parameters malformed, expecting deployment:start:end");
- }
- int64_t nStartTime, nTimeout;
- if (!ParseInt64(vDeploymentParams[1], &nStartTime)) {
- return InitError(strprintf("Invalid nStartTime (%s)", vDeploymentParams[1]));
- }
- if (!ParseInt64(vDeploymentParams[2], &nTimeout)) {
- return InitError(strprintf("Invalid nTimeout (%s)", vDeploymentParams[2]));
- }
- bool found = false;
- for (int j=0; j<(int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++j)
- {
- if (vDeploymentParams[0].compare(VersionBitsDeploymentInfo[j].name) == 0) {
- UpdateVersionBitsParameters(Consensus::DeploymentPos(j), nStartTime, nTimeout);
- found = true;
- LogPrintf("Setting version bits activation parameters for %s to start=%ld, timeout=%ld\n", vDeploymentParams[0], nStartTime, nTimeout);
- break;
- }
- }
- if (!found) {
- return InitError(strprintf("Invalid deployment (%s)", vDeploymentParams[0]));
- }
- }
- }
return true;
}
diff --git a/src/net.cpp b/src/net.cpp
index f83f39a67d..c8d3efceed 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -1153,310 +1153,322 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) {
}
}
-void CConnman::ThreadSocketHandler()
+void CConnman::DisconnectNodes()
{
- unsigned int nPrevNodeCount = 0;
- while (!interruptNet)
{
- //
- // Disconnect nodes
- //
- {
- LOCK(cs_vNodes);
+ LOCK(cs_vNodes);
- if (!fNetworkActive) {
- // Disconnect any connected nodes
- for (CNode* pnode : vNodes) {
- if (!pnode->fDisconnect) {
- LogPrint(BCLog::NET, "Network not active, dropping peer=%d\n", pnode->GetId());
- pnode->fDisconnect = true;
- }
+ if (!fNetworkActive) {
+ // Disconnect any connected nodes
+ for (CNode* pnode : vNodes) {
+ if (!pnode->fDisconnect) {
+ LogPrint(BCLog::NET, "Network not active, dropping peer=%d\n", pnode->GetId());
+ pnode->fDisconnect = true;
}
}
+ }
- // Disconnect unused nodes
- std::vector<CNode*> vNodesCopy = vNodes;
- for (CNode* pnode : vNodesCopy)
+ // Disconnect unused nodes
+ std::vector<CNode*> vNodesCopy = vNodes;
+ for (CNode* pnode : vNodesCopy)
+ {
+ if (pnode->fDisconnect)
{
- if (pnode->fDisconnect)
- {
- // remove from vNodes
- vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
+ // remove from vNodes
+ vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
- // release outbound grant (if any)
- pnode->grantOutbound.Release();
+ // release outbound grant (if any)
+ pnode->grantOutbound.Release();
- // close socket and cleanup
- pnode->CloseSocketDisconnect();
+ // close socket and cleanup
+ pnode->CloseSocketDisconnect();
- // hold in disconnected pool until all refs are released
- pnode->Release();
- vNodesDisconnected.push_back(pnode);
- }
+ // hold in disconnected pool until all refs are released
+ pnode->Release();
+ vNodesDisconnected.push_back(pnode);
}
}
+ }
+ {
+ // Delete disconnected nodes
+ std::list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
+ for (CNode* pnode : vNodesDisconnectedCopy)
{
- // Delete disconnected nodes
- std::list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
- for (CNode* pnode : vNodesDisconnectedCopy)
- {
- // wait until threads are done using it
- if (pnode->GetRefCount() <= 0) {
- bool fDelete = false;
- {
- TRY_LOCK(pnode->cs_inventory, lockInv);
- if (lockInv) {
- TRY_LOCK(pnode->cs_vSend, lockSend);
- if (lockSend) {
- fDelete = true;
- }
+ // wait until threads are done using it
+ if (pnode->GetRefCount() <= 0) {
+ bool fDelete = false;
+ {
+ TRY_LOCK(pnode->cs_inventory, lockInv);
+ if (lockInv) {
+ TRY_LOCK(pnode->cs_vSend, lockSend);
+ if (lockSend) {
+ fDelete = true;
}
}
- if (fDelete) {
- vNodesDisconnected.remove(pnode);
- DeleteNode(pnode);
- }
+ }
+ if (fDelete) {
+ vNodesDisconnected.remove(pnode);
+ DeleteNode(pnode);
}
}
}
- size_t vNodesSize;
+ }
+}
+
+void CConnman::NotifyNumConnectionsChanged()
+{
+ size_t vNodesSize;
+ {
+ LOCK(cs_vNodes);
+ vNodesSize = vNodes.size();
+ }
+ if(vNodesSize != nPrevNodeCount) {
+ nPrevNodeCount = vNodesSize;
+ if(clientInterface)
+ clientInterface->NotifyNumConnectionsChanged(vNodesSize);
+ }
+}
+
+void CConnman::InactivityCheck(CNode *pnode)
+{
+ int64_t nTime = GetSystemTimeInSeconds();
+ if (nTime - pnode->nTimeConnected > 60)
+ {
+ if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
+ {
+ LogPrint(BCLog::NET, "socket no message in first 60 seconds, %d %d from %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0, pnode->GetId());
+ pnode->fDisconnect = true;
+ }
+ else if (nTime - pnode->nLastSend > TIMEOUT_INTERVAL)
{
- LOCK(cs_vNodes);
- vNodesSize = vNodes.size();
+ LogPrintf("socket sending timeout: %is\n", nTime - pnode->nLastSend);
+ pnode->fDisconnect = true;
+ }
+ else if (nTime - pnode->nLastRecv > (pnode->nVersion > BIP0031_VERSION ? TIMEOUT_INTERVAL : 90*60))
+ {
+ LogPrintf("socket receive timeout: %is\n", nTime - pnode->nLastRecv);
+ pnode->fDisconnect = true;
+ }
+ else if (pnode->nPingNonceSent && pnode->nPingUsecStart + TIMEOUT_INTERVAL * 1000000 < GetTimeMicros())
+ {
+ LogPrintf("ping timeout: %fs\n", 0.000001 * (GetTimeMicros() - pnode->nPingUsecStart));
+ pnode->fDisconnect = true;
}
- if(vNodesSize != nPrevNodeCount) {
- nPrevNodeCount = vNodesSize;
- if(clientInterface)
- clientInterface->NotifyNumConnectionsChanged(vNodesSize);
+ else if (!pnode->fSuccessfullyConnected)
+ {
+ LogPrint(BCLog::NET, "version handshake timeout from %d\n", pnode->GetId());
+ pnode->fDisconnect = true;
}
+ }
+}
- //
- // Find which sockets have data to receive
- //
- struct timeval timeout;
- timeout.tv_sec = 0;
- timeout.tv_usec = 50000; // frequency to poll pnode->vSend
-
- fd_set fdsetRecv;
- fd_set fdsetSend;
- fd_set fdsetError;
- FD_ZERO(&fdsetRecv);
- FD_ZERO(&fdsetSend);
- FD_ZERO(&fdsetError);
- SOCKET hSocketMax = 0;
- bool have_fds = false;
+void CConnman::SocketHandler()
+{
+ //
+ // Find which sockets have data to receive
+ //
+ struct timeval timeout;
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 50000; // frequency to poll pnode->vSend
- for (const ListenSocket& hListenSocket : vhListenSocket) {
- FD_SET(hListenSocket.socket, &fdsetRecv);
- hSocketMax = std::max(hSocketMax, hListenSocket.socket);
- have_fds = true;
- }
+ fd_set fdsetRecv;
+ fd_set fdsetSend;
+ fd_set fdsetError;
+ FD_ZERO(&fdsetRecv);
+ FD_ZERO(&fdsetSend);
+ FD_ZERO(&fdsetError);
+ SOCKET hSocketMax = 0;
+ bool have_fds = false;
+ for (const ListenSocket& hListenSocket : vhListenSocket) {
+ FD_SET(hListenSocket.socket, &fdsetRecv);
+ hSocketMax = std::max(hSocketMax, hListenSocket.socket);
+ have_fds = true;
+ }
+
+ {
+ LOCK(cs_vNodes);
+ for (CNode* pnode : vNodes)
{
- LOCK(cs_vNodes);
- for (CNode* pnode : vNodes)
+ // Implement the following logic:
+ // * If there is data to send, select() for sending data. As this only
+ // happens when optimistic write failed, we choose to first drain the
+ // write buffer in this case before receiving more. This avoids
+ // needlessly queueing received data, if the remote peer is not themselves
+ // receiving data. This means properly utilizing TCP flow control signalling.
+ // * Otherwise, if there is space left in the receive buffer, select() for
+ // receiving data.
+ // * Hand off all complete messages to the processor, to be handled without
+ // blocking here.
+
+ bool select_recv = !pnode->fPauseRecv;
+ bool select_send;
{
- // Implement the following logic:
- // * If there is data to send, select() for sending data. As this only
- // happens when optimistic write failed, we choose to first drain the
- // write buffer in this case before receiving more. This avoids
- // needlessly queueing received data, if the remote peer is not themselves
- // receiving data. This means properly utilizing TCP flow control signalling.
- // * Otherwise, if there is space left in the receive buffer, select() for
- // receiving data.
- // * Hand off all complete messages to the processor, to be handled without
- // blocking here.
-
- bool select_recv = !pnode->fPauseRecv;
- bool select_send;
- {
- LOCK(pnode->cs_vSend);
- select_send = !pnode->vSendMsg.empty();
- }
+ LOCK(pnode->cs_vSend);
+ select_send = !pnode->vSendMsg.empty();
+ }
- LOCK(pnode->cs_hSocket);
- if (pnode->hSocket == INVALID_SOCKET)
- continue;
+ LOCK(pnode->cs_hSocket);
+ if (pnode->hSocket == INVALID_SOCKET)
+ continue;
- FD_SET(pnode->hSocket, &fdsetError);
- hSocketMax = std::max(hSocketMax, pnode->hSocket);
- have_fds = true;
+ FD_SET(pnode->hSocket, &fdsetError);
+ hSocketMax = std::max(hSocketMax, pnode->hSocket);
+ have_fds = true;
- if (select_send) {
- FD_SET(pnode->hSocket, &fdsetSend);
- continue;
- }
- if (select_recv) {
- FD_SET(pnode->hSocket, &fdsetRecv);
- }
+ if (select_send) {
+ FD_SET(pnode->hSocket, &fdsetSend);
+ continue;
+ }
+ if (select_recv) {
+ FD_SET(pnode->hSocket, &fdsetRecv);
}
}
+ }
- int nSelect = select(have_fds ? hSocketMax + 1 : 0,
- &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
- if (interruptNet)
- return;
+ int nSelect = select(have_fds ? hSocketMax + 1 : 0,
+ &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
+ if (interruptNet)
+ return;
- if (nSelect == SOCKET_ERROR)
+ if (nSelect == SOCKET_ERROR)
+ {
+ if (have_fds)
{
- if (have_fds)
- {
- int nErr = WSAGetLastError();
- LogPrintf("socket select error %s\n", NetworkErrorString(nErr));
- for (unsigned int i = 0; i <= hSocketMax; i++)
- FD_SET(i, &fdsetRecv);
- }
- FD_ZERO(&fdsetSend);
- FD_ZERO(&fdsetError);
- if (!interruptNet.sleep_for(std::chrono::milliseconds(timeout.tv_usec/1000)))
- return;
+ int nErr = WSAGetLastError();
+ LogPrintf("socket select error %s\n", NetworkErrorString(nErr));
+ for (unsigned int i = 0; i <= hSocketMax; i++)
+ FD_SET(i, &fdsetRecv);
}
+ FD_ZERO(&fdsetSend);
+ FD_ZERO(&fdsetError);
+ if (!interruptNet.sleep_for(std::chrono::milliseconds(timeout.tv_usec/1000)))
+ return;
+ }
- //
- // Accept new connections
- //
- for (const ListenSocket& hListenSocket : vhListenSocket)
+ //
+ // Accept new connections
+ //
+ for (const ListenSocket& hListenSocket : vhListenSocket)
+ {
+ if (hListenSocket.socket != INVALID_SOCKET && FD_ISSET(hListenSocket.socket, &fdsetRecv))
{
- if (hListenSocket.socket != INVALID_SOCKET && FD_ISSET(hListenSocket.socket, &fdsetRecv))
- {
- AcceptConnection(hListenSocket);
- }
+ AcceptConnection(hListenSocket);
}
+ }
+
+ //
+ // Service each socket
+ //
+ std::vector<CNode*> vNodesCopy;
+ {
+ LOCK(cs_vNodes);
+ vNodesCopy = vNodes;
+ for (CNode* pnode : vNodesCopy)
+ pnode->AddRef();
+ }
+ for (CNode* pnode : vNodesCopy)
+ {
+ if (interruptNet)
+ return;
//
- // Service each socket
+ // Receive
//
- std::vector<CNode*> vNodesCopy;
+ bool recvSet = false;
+ bool sendSet = false;
+ bool errorSet = false;
{
- LOCK(cs_vNodes);
- vNodesCopy = vNodes;
- for (CNode* pnode : vNodesCopy)
- pnode->AddRef();
+ LOCK(pnode->cs_hSocket);
+ if (pnode->hSocket == INVALID_SOCKET)
+ continue;
+ recvSet = FD_ISSET(pnode->hSocket, &fdsetRecv);
+ sendSet = FD_ISSET(pnode->hSocket, &fdsetSend);
+ errorSet = FD_ISSET(pnode->hSocket, &fdsetError);
}
- for (CNode* pnode : vNodesCopy)
+ if (recvSet || errorSet)
{
- if (interruptNet)
- return;
-
- //
- // Receive
- //
- bool recvSet = false;
- bool sendSet = false;
- bool errorSet = false;
+ // typical socket buffer is 8K-64K
+ char pchBuf[0x10000];
+ int nBytes = 0;
{
LOCK(pnode->cs_hSocket);
if (pnode->hSocket == INVALID_SOCKET)
continue;
- recvSet = FD_ISSET(pnode->hSocket, &fdsetRecv);
- sendSet = FD_ISSET(pnode->hSocket, &fdsetSend);
- errorSet = FD_ISSET(pnode->hSocket, &fdsetError);
+ nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
}
- if (recvSet || errorSet)
+ if (nBytes > 0)
{
- // typical socket buffer is 8K-64K
- char pchBuf[0x10000];
- int nBytes = 0;
- {
- LOCK(pnode->cs_hSocket);
- if (pnode->hSocket == INVALID_SOCKET)
- continue;
- nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
- }
- if (nBytes > 0)
- {
- bool notify = false;
- if (!pnode->ReceiveMsgBytes(pchBuf, nBytes, notify))
- pnode->CloseSocketDisconnect();
- RecordBytesRecv(nBytes);
- if (notify) {
- size_t nSizeAdded = 0;
- auto it(pnode->vRecvMsg.begin());
- for (; it != pnode->vRecvMsg.end(); ++it) {
- if (!it->complete())
- break;
- nSizeAdded += it->vRecv.size() + CMessageHeader::HEADER_SIZE;
- }
- {
- LOCK(pnode->cs_vProcessMsg);
- pnode->vProcessMsg.splice(pnode->vProcessMsg.end(), pnode->vRecvMsg, pnode->vRecvMsg.begin(), it);
- pnode->nProcessQueueSize += nSizeAdded;
- pnode->fPauseRecv = pnode->nProcessQueueSize > nReceiveFloodSize;
- }
- WakeMessageHandler();
- }
- }
- else if (nBytes == 0)
- {
- // socket closed gracefully
- if (!pnode->fDisconnect) {
- LogPrint(BCLog::NET, "socket closed\n");
- }
+ bool notify = false;
+ if (!pnode->ReceiveMsgBytes(pchBuf, nBytes, notify))
pnode->CloseSocketDisconnect();
- }
- else if (nBytes < 0)
- {
- // error
- int nErr = WSAGetLastError();
- if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
+ RecordBytesRecv(nBytes);
+ if (notify) {
+ size_t nSizeAdded = 0;
+ auto it(pnode->vRecvMsg.begin());
+ for (; it != pnode->vRecvMsg.end(); ++it) {
+ if (!it->complete())
+ break;
+ nSizeAdded += it->vRecv.size() + CMessageHeader::HEADER_SIZE;
+ }
{
- if (!pnode->fDisconnect)
- LogPrintf("socket recv error %s\n", NetworkErrorString(nErr));
- pnode->CloseSocketDisconnect();
+ LOCK(pnode->cs_vProcessMsg);
+ pnode->vProcessMsg.splice(pnode->vProcessMsg.end(), pnode->vRecvMsg, pnode->vRecvMsg.begin(), it);
+ pnode->nProcessQueueSize += nSizeAdded;
+ pnode->fPauseRecv = pnode->nProcessQueueSize > nReceiveFloodSize;
}
+ WakeMessageHandler();
}
}
-
- //
- // Send
- //
- if (sendSet)
+ else if (nBytes == 0)
{
- LOCK(pnode->cs_vSend);
- size_t nBytes = SocketSendData(pnode);
- if (nBytes) {
- RecordBytesSent(nBytes);
+ // socket closed gracefully
+ if (!pnode->fDisconnect) {
+ LogPrint(BCLog::NET, "socket closed\n");
}
+ pnode->CloseSocketDisconnect();
}
-
- //
- // Inactivity checking
- //
- int64_t nTime = GetSystemTimeInSeconds();
- if (nTime - pnode->nTimeConnected > 60)
+ else if (nBytes < 0)
{
- if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
- {
- LogPrint(BCLog::NET, "socket no message in first 60 seconds, %d %d from %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0, pnode->GetId());
- pnode->fDisconnect = true;
- }
- else if (nTime - pnode->nLastSend > TIMEOUT_INTERVAL)
- {
- LogPrintf("socket sending timeout: %is\n", nTime - pnode->nLastSend);
- pnode->fDisconnect = true;
- }
- else if (nTime - pnode->nLastRecv > (pnode->nVersion > BIP0031_VERSION ? TIMEOUT_INTERVAL : 90*60))
- {
- LogPrintf("socket receive timeout: %is\n", nTime - pnode->nLastRecv);
- pnode->fDisconnect = true;
- }
- else if (pnode->nPingNonceSent && pnode->nPingUsecStart + TIMEOUT_INTERVAL * 1000000 < GetTimeMicros())
- {
- LogPrintf("ping timeout: %fs\n", 0.000001 * (GetTimeMicros() - pnode->nPingUsecStart));
- pnode->fDisconnect = true;
- }
- else if (!pnode->fSuccessfullyConnected)
+ // error
+ int nErr = WSAGetLastError();
+ if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
{
- LogPrint(BCLog::NET, "version handshake timeout from %d\n", pnode->GetId());
- pnode->fDisconnect = true;
+ if (!pnode->fDisconnect)
+ LogPrintf("socket recv error %s\n", NetworkErrorString(nErr));
+ pnode->CloseSocketDisconnect();
}
}
}
+
+ //
+ // Send
+ //
+ if (sendSet)
{
- LOCK(cs_vNodes);
- for (CNode* pnode : vNodesCopy)
- pnode->Release();
+ LOCK(pnode->cs_vSend);
+ size_t nBytes = SocketSendData(pnode);
+ if (nBytes) {
+ RecordBytesSent(nBytes);
+ }
}
+
+ InactivityCheck(pnode);
+ }
+ {
+ LOCK(cs_vNodes);
+ for (CNode* pnode : vNodesCopy)
+ pnode->Release();
+ }
+}
+
+void CConnman::ThreadSocketHandler()
+{
+ while (!interruptNet)
+ {
+ DisconnectNodes();
+ NotifyNumConnectionsChanged();
+ SocketHandler();
}
}
@@ -2217,6 +2229,7 @@ CConnman::CConnman(uint64_t nSeed0In, uint64_t nSeed1In) : nSeed0(nSeed0In), nSe
setBannedIsDirty = false;
fAddressesInitialized = false;
nLastNodeId = 0;
+ nPrevNodeCount = 0;
nSendBufferMaxSize = 0;
nReceiveFloodSize = 0;
flagInterruptMsgProc = false;
diff --git a/src/net.h b/src/net.h
index 9f6c426ab7..49360a7206 100644
--- a/src/net.h
+++ b/src/net.h
@@ -149,6 +149,7 @@ public:
nLocalServices = connOptions.nLocalServices;
nMaxConnections = connOptions.nMaxConnections;
nMaxOutbound = std::min(connOptions.nMaxOutbound, connOptions.nMaxConnections);
+ m_use_addrman_outgoing = connOptions.m_use_addrman_outgoing;
nMaxAddnode = connOptions.nMaxAddnode;
nMaxFeeler = connOptions.nMaxFeeler;
nBestHeight = connOptions.nBestHeight;
@@ -174,6 +175,7 @@ public:
void Stop();
void Interrupt();
bool GetNetworkActive() const { return fNetworkActive; };
+ bool GetUseAddrmanOutgoing() const { return m_use_addrman_outgoing; };
void SetNetworkActive(bool active);
void OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant *grantOutbound = nullptr, const char *strDest = nullptr, bool fOneShot = false, bool fFeeler = false, bool manual_connection = false);
bool CheckIncomingNonce(uint64_t nonce);
@@ -336,6 +338,10 @@ private:
void ThreadOpenConnections(std::vector<std::string> connect);
void ThreadMessageHandler();
void AcceptConnection(const ListenSocket& hListenSocket);
+ void DisconnectNodes();
+ void NotifyNumConnectionsChanged();
+ void InactivityCheck(CNode *pnode);
+ void SocketHandler();
void ThreadSocketHandler();
void ThreadDNSAddressSeed();
@@ -406,6 +412,7 @@ private:
std::list<CNode*> vNodesDisconnected;
mutable CCriticalSection cs_vNodes;
std::atomic<NodeId> nLastNodeId;
+ unsigned int nPrevNodeCount;
/** Services this instance offers */
ServiceFlags nLocalServices;
@@ -416,6 +423,7 @@ private:
int nMaxOutbound;
int nMaxAddnode;
int nMaxFeeler;
+ bool m_use_addrman_outgoing;
std::atomic<int> nBestHeight;
CClientUIInterface* clientInterface;
NetEventsInterface* m_msgproc;
diff --git a/src/net_processing.cpp b/src/net_processing.cpp
index b48a3bd221..a1b6e021ae 100644
--- a/src/net_processing.cpp
+++ b/src/net_processing.cpp
@@ -3144,8 +3144,6 @@ void PeerLogicValidation::EvictExtraOutboundPeers(int64_t time_in_seconds)
NodeId worst_peer = -1;
int64_t oldest_block_announcement = std::numeric_limits<int64_t>::max();
- LOCK(cs_main);
-
connman->ForEachNode([&](CNode* pnode) {
AssertLockHeld(cs_main);
@@ -3193,6 +3191,8 @@ void PeerLogicValidation::EvictExtraOutboundPeers(int64_t time_in_seconds)
void PeerLogicValidation::CheckForStaleTipAndEvictPeers(const Consensus::Params &consensusParams)
{
+ LOCK(cs_main);
+
if (connman == nullptr) return;
int64_t time_in_seconds = GetTime();
@@ -3200,10 +3200,9 @@ void PeerLogicValidation::CheckForStaleTipAndEvictPeers(const Consensus::Params
EvictExtraOutboundPeers(time_in_seconds);
if (time_in_seconds > m_stale_tip_check_time) {
- LOCK(cs_main);
// Check whether our tip is stale, and if so, allow using an extra
// outbound peer
- if (TipMayBeStale(consensusParams)) {
+ if (!fImporting && !fReindex && connman->GetNetworkActive() && connman->GetUseAddrmanOutgoing() && TipMayBeStale(consensusParams)) {
LogPrintf("Potential stale tip detected, will try using extra outbound peer (last tip update: %d seconds ago)\n", time_in_seconds - g_last_tip_update);
connman->SetTryNewOutboundPeer(true);
} else if (connman->GetTryNewOutboundPeer()) {
diff --git a/src/net_processing.h b/src/net_processing.h
index 496c3c7b0d..0113e25f7e 100644
--- a/src/net_processing.h
+++ b/src/net_processing.h
@@ -9,6 +9,9 @@
#include <net.h>
#include <validationinterface.h>
#include <consensus/params.h>
+#include <sync.h>
+
+extern CCriticalSection cs_main;
/** Default for -maxorphantx, maximum number of orphan transactions kept in memory */
static const unsigned int DEFAULT_MAX_ORPHAN_TRANSACTIONS = 100;
@@ -65,10 +68,10 @@ public:
/** Evict extra outbound peers. If we think our tip may be stale, connect to an extra outbound */
void CheckForStaleTipAndEvictPeers(const Consensus::Params &consensusParams);
/** If we have extra outbound peers, try to disconnect the one with the oldest block announcement */
- void EvictExtraOutboundPeers(int64_t time_in_seconds);
+ void EvictExtraOutboundPeers(int64_t time_in_seconds) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
private:
- int64_t m_stale_tip_check_time; //! Next time to check for stale tip
+ int64_t m_stale_tip_check_time; //!< Next time to check for stale tip
/** Enable BIP61 (sending reject messages) */
const bool m_enable_bip61;
diff --git a/src/netbase.cpp b/src/netbase.cpp
index 093fd0bdb7..04d5eb12c8 100644
--- a/src/netbase.cpp
+++ b/src/netbase.cpp
@@ -191,10 +191,10 @@ enum SOCKSVersion: uint8_t {
/** Values defined for METHOD in RFC1928 */
enum SOCKS5Method: uint8_t {
- NOAUTH = 0x00, //! No authentication required
- GSSAPI = 0x01, //! GSSAPI
- USER_PASS = 0x02, //! Username/password
- NO_ACCEPTABLE = 0xff, //! No acceptable methods
+ NOAUTH = 0x00, //!< No authentication required
+ GSSAPI = 0x01, //!< GSSAPI
+ USER_PASS = 0x02, //!< Username/password
+ NO_ACCEPTABLE = 0xff, //!< No acceptable methods
};
/** Values defined for CMD in RFC1928 */
@@ -206,15 +206,15 @@ enum SOCKS5Command: uint8_t {
/** Values defined for REP in RFC1928 */
enum SOCKS5Reply: uint8_t {
- SUCCEEDED = 0x00, //! Succeeded
- GENFAILURE = 0x01, //! General failure
- NOTALLOWED = 0x02, //! Connection not allowed by ruleset
- NETUNREACHABLE = 0x03, //! Network unreachable
- HOSTUNREACHABLE = 0x04, //! Network unreachable
- CONNREFUSED = 0x05, //! Connection refused
- TTLEXPIRED = 0x06, //! TTL expired
- CMDUNSUPPORTED = 0x07, //! Command not supported
- ATYPEUNSUPPORTED = 0x08, //! Address type not supported
+ SUCCEEDED = 0x00, //!< Succeeded
+ GENFAILURE = 0x01, //!< General failure
+ NOTALLOWED = 0x02, //!< Connection not allowed by ruleset
+ NETUNREACHABLE = 0x03, //!< Network unreachable
+ HOSTUNREACHABLE = 0x04, //!< Network unreachable
+ CONNREFUSED = 0x05, //!< Connection refused
+ TTLEXPIRED = 0x06, //!< TTL expired
+ CMDUNSUPPORTED = 0x07, //!< Command not supported
+ ATYPEUNSUPPORTED = 0x08, //!< Address type not supported
};
/** Values defined for ATYPE in RFC1928 */
diff --git a/src/policy/fees.h b/src/policy/fees.h
index 2733c5a7de..90f159b48c 100644
--- a/src/policy/fees.h
+++ b/src/policy/fees.h
@@ -50,9 +50,9 @@ std::string StringForFeeReason(FeeReason reason);
/* Used to determine type of fee estimation requested */
enum class FeeEstimateMode {
- UNSET, //! Use default settings based on other criteria
- ECONOMICAL, //! Force estimateSmartFee to use non-conservative estimates
- CONSERVATIVE, //! Force estimateSmartFee to use conservative estimates
+ UNSET, //!< Use default settings based on other criteria
+ ECONOMICAL, //!< Force estimateSmartFee to use non-conservative estimates
+ CONSERVATIVE, //!< Force estimateSmartFee to use conservative estimates
};
bool FeeModeFromString(const std::string& mode_string, FeeEstimateMode& fee_estimate_mode);
diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h
index fb9db508d2..6d8b530f69 100644
--- a/src/primitives/transaction.h
+++ b/src/primitives/transaction.h
@@ -64,7 +64,7 @@ public:
COutPoint prevout;
CScript scriptSig;
uint32_t nSequence;
- CScriptWitness scriptWitness; //! Only serialized through CTransaction
+ CScriptWitness scriptWitness; //!< Only serialized through CTransaction
/* Setting nSequence to this value for every input in a transaction
* disables nLockTime. */
diff --git a/src/qt/README.md b/src/qt/README.md
index 3ec538b4f4..0eb18f7cd5 100644
--- a/src/qt/README.md
+++ b/src/qt/README.md
@@ -64,8 +64,8 @@ Represents the view to a single wallet.
* `callback.h`
* `guiconstants.h`: UI colors, app name, etc
* `guiutil.h`: several helper functions
-* `macdockiconhandler.(h/cpp)`
-* `macdockiconhandler.(h/cpp)`: display notifications in macOS
+* `macdockiconhandler.(h/mm)`: macOS dock icon handler
+* `macnotificationhandler.(h/mm)`: display notifications in macOS
## Contribute
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp
index 1e950e2686..a014ad4b28 100644
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -51,7 +51,6 @@
#include <QThread>
#include <QTimer>
#include <QTranslator>
-#include <QSslConfiguration>
#if defined(QT_STATICPLUGIN)
#include <QtPlugin>
@@ -552,6 +551,10 @@ static void SetupUIArgs()
#ifndef BITCOIN_QT_TEST
int main(int argc, char *argv[])
{
+#ifdef WIN32
+ util::WinCmdLineArgs winArgs;
+ std::tie(argc, argv) = winArgs.get();
+#endif
SetupEnvironment();
std::unique_ptr<interfaces::Node> node = interfaces::MakeNode();
@@ -573,13 +576,6 @@ int main(int argc, char *argv[])
#ifdef Q_OS_MAC
QApplication::setAttribute(Qt::AA_DontShowIconsInMenus);
#endif
-#if QT_VERSION >= 0x050500
- // Because of the POODLE attack it is recommended to disable SSLv3 (https://disablessl3.com/),
- // so set SSL protocols to TLS1.0+.
- QSslConfiguration sslconf = QSslConfiguration::defaultConfiguration();
- sslconf.setProtocol(QSsl::TlsV1_0OrLater);
- QSslConfiguration::setDefaultConfiguration(sslconf);
-#endif
// Register meta types used for QMetaObject::invokeMethod
qRegisterMetaType< bool* >();
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index 51aff08c42..311841017f 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -620,14 +620,16 @@ void BitcoinGUI::createTrayIconMenu()
trayIconMenu->addAction(toggleHideAction);
trayIconMenu->addSeparator();
#endif
- trayIconMenu->addAction(sendCoinsMenuAction);
- trayIconMenu->addAction(receiveCoinsMenuAction);
- trayIconMenu->addSeparator();
- trayIconMenu->addAction(signMessageAction);
- trayIconMenu->addAction(verifyMessageAction);
- trayIconMenu->addSeparator();
+ if (enableWallet) {
+ trayIconMenu->addAction(sendCoinsMenuAction);
+ trayIconMenu->addAction(receiveCoinsMenuAction);
+ trayIconMenu->addSeparator();
+ trayIconMenu->addAction(signMessageAction);
+ trayIconMenu->addAction(verifyMessageAction);
+ trayIconMenu->addSeparator();
+ trayIconMenu->addAction(openRPCConsoleAction);
+ }
trayIconMenu->addAction(optionsAction);
- trayIconMenu->addAction(openRPCConsoleAction);
#ifndef Q_OS_MAC // This is built-in on Mac
trayIconMenu->addSeparator();
trayIconMenu->addAction(quitAction);
diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp
index b2cf4b6399..183444efab 100644
--- a/src/qt/clientmodel.cpp
+++ b/src/qt/clientmodel.cpp
@@ -177,6 +177,11 @@ QString ClientModel::dataDir() const
return GUIUtil::boostPathToQString(GetDataDir());
}
+QString ClientModel::blocksDir() const
+{
+ return GUIUtil::boostPathToQString(GetBlocksDir());
+}
+
void ClientModel::updateBanlist()
{
banTableModel->refresh();
diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h
index ed7ecbf73b..79e7074cca 100644
--- a/src/qt/clientmodel.h
+++ b/src/qt/clientmodel.h
@@ -69,6 +69,7 @@ public:
bool isReleaseVersion() const;
QString formatClientStartupTime() const;
QString dataDir() const;
+ QString blocksDir() const;
bool getProxyInfo(std::string& ip_port) const;
diff --git a/src/qt/forms/debugwindow.ui b/src/qt/forms/debugwindow.ui
index 695ed61228..dca16d6f78 100644
--- a/src/qt/forms/debugwindow.ui
+++ b/src/qt/forms/debugwindow.ui
@@ -127,6 +127,9 @@
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
</property>
+ <property name="toolTip">
+ <string>To specify a non-default location of the data directory use the '%1' option.</string>
+ </property>
<property name="text">
<string>N/A</string>
</property>
@@ -142,13 +145,42 @@
</widget>
</item>
<item row="5" column="0">
+ <widget class="QLabel" name="label_11">
+ <property name="text">
+ <string>Blocksdir</string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="1" colspan="2">
+ <widget class="QLabel" name="blocksDir">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="toolTip">
+ <string>To specify a non-default location of the blocks directory use the '%1' option.</string>
+ </property>
+ <property name="text">
+ <string>N/A</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="0">
<widget class="QLabel" name="label_13">
<property name="text">
<string>Startup time</string>
</property>
</widget>
</item>
- <item row="5" column="1" colspan="2">
+ <item row="6" column="1" colspan="2">
<widget class="QLabel" name="startupTime">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -164,7 +196,7 @@
</property>
</widget>
</item>
- <item row="6" column="0">
+ <item row="7" column="0">
<widget class="QLabel" name="labelNetwork">
<property name="font">
<font>
@@ -177,14 +209,14 @@
</property>
</widget>
</item>
- <item row="7" column="0">
+ <item row="8" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Name</string>
</property>
</widget>
</item>
- <item row="7" column="1" colspan="2">
+ <item row="8" column="1" colspan="2">
<widget class="QLabel" name="networkName">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -200,14 +232,14 @@
</property>
</widget>
</item>
- <item row="8" column="0">
+ <item row="9" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Number of connections</string>
</property>
</widget>
</item>
- <item row="8" column="1" colspan="2">
+ <item row="9" column="1" colspan="2">
<widget class="QLabel" name="numberOfConnections">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -223,7 +255,7 @@
</property>
</widget>
</item>
- <item row="9" column="0">
+ <item row="10" column="0">
<widget class="QLabel" name="label_10">
<property name="font">
<font>
@@ -236,14 +268,14 @@
</property>
</widget>
</item>
- <item row="10" column="0">
+ <item row="11" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Current number of blocks</string>
</property>
</widget>
</item>
- <item row="10" column="1" colspan="2">
+ <item row="11" column="1" colspan="2">
<widget class="QLabel" name="numberOfBlocks">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -259,14 +291,14 @@
</property>
</widget>
</item>
- <item row="11" column="0">
+ <item row="12" column="0">
<widget class="QLabel" name="labelLastBlockTime">
<property name="text">
<string>Last block time</string>
</property>
</widget>
</item>
- <item row="11" column="1" colspan="2">
+ <item row="12" column="1" colspan="2">
<widget class="QLabel" name="lastBlockTime">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -282,7 +314,7 @@
</property>
</widget>
</item>
- <item row="12" column="0">
+ <item row="13" column="0">
<widget class="QLabel" name="labelMempoolTitle">
<property name="font">
<font>
@@ -295,14 +327,14 @@
</property>
</widget>
</item>
- <item row="13" column="0">
+ <item row="14" column="0">
<widget class="QLabel" name="labelNumberOfTransactions">
<property name="text">
<string>Current number of transactions</string>
</property>
</widget>
</item>
- <item row="13" column="1">
+ <item row="14" column="1">
<widget class="QLabel" name="mempoolNumberTxs">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -318,14 +350,14 @@
</property>
</widget>
</item>
- <item row="14" column="0">
+ <item row="15" column="0">
<widget class="QLabel" name="labelMemoryUsage">
<property name="text">
<string>Memory usage</string>
</property>
</widget>
</item>
- <item row="14" column="1">
+ <item row="15" column="1">
<widget class="QLabel" name="mempoolSize">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -341,7 +373,7 @@
</property>
</widget>
</item>
- <item row="12" column="2" rowspan="3">
+ <item row="13" column="2" rowspan="3">
<layout class="QVBoxLayout" name="verticalLayoutDebugButton">
<property name="spacing">
<number>3</number>
@@ -381,7 +413,7 @@
</item>
</layout>
</item>
- <item row="15" column="0">
+ <item row="16" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp
index 7afe25d25a..5f6af61a70 100644
--- a/src/qt/guiutil.cpp
+++ b/src/qt/guiutil.cpp
@@ -60,8 +60,6 @@
#include <QFontDatabase>
#endif
-static fs::detail::utf8_codecvt_facet utf8;
-
namespace GUIUtil {
QString dateTimeStr(const QDateTime &date)
@@ -369,7 +367,7 @@ bool openBitcoinConf()
fs::path pathConfig = GetConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME));
/* Create the file */
- fs::ofstream configFile(pathConfig, std::ios_base::app);
+ fsbridge::ofstream configFile(pathConfig, std::ios_base::app);
if (!configFile.good())
return false;
@@ -613,7 +611,7 @@ fs::path static GetAutostartFilePath()
bool GetStartOnSystemStartup()
{
- fs::ifstream optionFile(GetAutostartFilePath());
+ fsbridge::ifstream optionFile(GetAutostartFilePath());
if (!optionFile.good())
return false;
// Scan through file for "Hidden=true":
@@ -644,7 +642,7 @@ bool SetStartOnSystemStartup(bool fAutoStart)
fs::create_directories(GetAutostartDir());
- fs::ofstream optionFile(GetAutostartFilePath(), std::ios_base::out|std::ios_base::trunc);
+ fsbridge::ofstream optionFile(GetAutostartFilePath(), std::ios_base::out | std::ios_base::trunc);
if (!optionFile.good())
return false;
std::string chain = gArgs.GetChainName();
@@ -764,12 +762,12 @@ void setClipboard(const QString& str)
fs::path qstringToBoostPath(const QString &path)
{
- return fs::path(path.toStdString(), utf8);
+ return fs::path(path.toStdString());
}
QString boostPathToQString(const fs::path &path)
{
- return QString::fromStdString(path.string(utf8));
+ return QString::fromStdString(path.string());
}
QString formatDurationStr(int secs)
diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp
index 3857befdf2..c004c783f2 100644
--- a/src/qt/rpcconsole.cpp
+++ b/src/qt/rpcconsole.cpp
@@ -459,6 +459,9 @@ RPCConsole::RPCConsole(interfaces::Node& node, const PlatformStyle *_platformSty
move(QApplication::desktop()->availableGeometry().center() - frameGeometry().center());
}
+ QChar nonbreaking_hyphen(8209);
+ ui->dataDir->setToolTip(ui->dataDir->toolTip().arg(QString(nonbreaking_hyphen) + "datadir"));
+ ui->blocksDir->setToolTip(ui->blocksDir->toolTip().arg(QString(nonbreaking_hyphen) + "blocksdir"));
ui->openDebugLogfileButton->setToolTip(ui->openDebugLogfileButton->toolTip().arg(tr(PACKAGE_NAME)));
if (platformStyle->getImagesOnButtons()) {
@@ -536,6 +539,7 @@ bool RPCConsole::eventFilter(QObject* obj, QEvent *event)
// forward these events to lineEdit
if(obj == autoCompleter->popup()) {
QApplication::postEvent(ui->lineEdit, new QKeyEvent(*keyevt));
+ autoCompleter->popup()->hide();
return true;
}
break;
@@ -661,6 +665,7 @@ void RPCConsole::setClientModel(ClientModel *model)
ui->clientVersion->setText(model->formatFullVersion());
ui->clientUserAgent->setText(model->formatSubVersion());
ui->dataDir->setText(model->dataDir());
+ ui->blocksDir->setText(model->blocksDir());
ui->startupTime->setText(model->formatClientStartupTime());
ui->networkName->setText(QString::fromStdString(Params().NetworkIDString()));
diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp
index 6d08a3b0fb..68410c8bd6 100644
--- a/src/qt/transactionview.cpp
+++ b/src/qt/transactionview.cpp
@@ -106,7 +106,11 @@ TransactionView::TransactionView(const PlatformStyle *platformStyle, QWidget *pa
} else {
amountWidget->setFixedWidth(100);
}
- amountWidget->setValidator(new QDoubleValidator(0, 1e20, 8, this));
+ QDoubleValidator *amountValidator = new QDoubleValidator(0, 1e20, 8, this);
+ QLocale amountLocale(QLocale::C);
+ amountLocale.setNumberOptions(QLocale::RejectGroupSeparator);
+ amountValidator->setLocale(amountLocale);
+ amountWidget->setValidator(amountValidator);
hlayout->addWidget(amountWidget);
// Delay before filtering transactions in ms
diff --git a/src/rest.cpp b/src/rest.cpp
index 6ba15172fa..1850c0b7a6 100644
--- a/src/rest.cpp
+++ b/src/rest.cpp
@@ -105,15 +105,6 @@ static std::string AvailableDataFormatsString()
return formats;
}
-static bool ParseHashStr(const std::string& strReq, uint256& v)
-{
- if (!IsHex(strReq) || (strReq.size() != 64))
- return false;
-
- v.SetHex(strReq);
- return true;
-}
-
static bool CheckWarmup(HTTPRequest* req)
{
std::string statusmessage;
@@ -157,13 +148,13 @@ static bool rest_headers(HTTPRequest* req,
}
}
- CDataStream ssHeader(SER_NETWORK, PROTOCOL_VERSION);
- for (const CBlockIndex *pindex : headers) {
- ssHeader << pindex->GetBlockHeader();
- }
-
switch (rf) {
case RetFormat::BINARY: {
+ CDataStream ssHeader(SER_NETWORK, PROTOCOL_VERSION);
+ for (const CBlockIndex *pindex : headers) {
+ ssHeader << pindex->GetBlockHeader();
+ }
+
std::string binaryHeader = ssHeader.str();
req->WriteHeader("Content-Type", "application/octet-stream");
req->WriteReply(HTTP_OK, binaryHeader);
@@ -171,6 +162,11 @@ static bool rest_headers(HTTPRequest* req,
}
case RetFormat::HEX: {
+ CDataStream ssHeader(SER_NETWORK, PROTOCOL_VERSION);
+ for (const CBlockIndex *pindex : headers) {
+ ssHeader << pindex->GetBlockHeader();
+ }
+
std::string strHex = HexStr(ssHeader.begin(), ssHeader.end()) + "\n";
req->WriteHeader("Content-Type", "text/plain");
req->WriteReply(HTTP_OK, strHex);
@@ -224,11 +220,10 @@ static bool rest_block(HTTPRequest* req,
return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not found");
}
- CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION | RPCSerializationFlags());
- ssBlock << block;
-
switch (rf) {
case RetFormat::BINARY: {
+ CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION | RPCSerializationFlags());
+ ssBlock << block;
std::string binaryBlock = ssBlock.str();
req->WriteHeader("Content-Type", "application/octet-stream");
req->WriteReply(HTTP_OK, binaryBlock);
@@ -236,6 +231,8 @@ static bool rest_block(HTTPRequest* req,
}
case RetFormat::HEX: {
+ CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION | RPCSerializationFlags());
+ ssBlock << block;
std::string strHex = HexStr(ssBlock.begin(), ssBlock.end()) + "\n";
req->WriteHeader("Content-Type", "text/plain");
req->WriteReply(HTTP_OK, strHex);
@@ -360,11 +357,11 @@ static bool rest_tx(HTTPRequest* req, const std::string& strURIPart)
if (!GetTransaction(hash, tx, Params().GetConsensus(), hashBlock, true))
return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not found");
- CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION | RPCSerializationFlags());
- ssTx << tx;
-
switch (rf) {
case RetFormat::BINARY: {
+ CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION | RPCSerializationFlags());
+ ssTx << tx;
+
std::string binaryTx = ssTx.str();
req->WriteHeader("Content-Type", "application/octet-stream");
req->WriteReply(HTTP_OK, binaryTx);
@@ -372,6 +369,9 @@ static bool rest_tx(HTTPRequest* req, const std::string& strURIPart)
}
case RetFormat::HEX: {
+ CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION | RPCSerializationFlags());
+ ssTx << tx;
+
std::string strHex = HexStr(ssTx.begin(), ssTx.end()) + "\n";
req->WriteHeader("Content-Type", "text/plain");
req->WriteReply(HTTP_OK, strHex);
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index 439427cd7e..ff71b19250 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -30,6 +30,7 @@
#include <utilstrencodings.h>
#include <hash.h>
#include <validationinterface.h>
+#include <versionbitsinfo.h>
#include <warnings.h>
#include <assert.h>
@@ -181,7 +182,7 @@ static UniValue getbestblockhash(const JSONRPCRequest& request)
"getbestblockhash\n"
"\nReturns the hash of the best (tip) block in the longest blockchain.\n"
"\nResult:\n"
- "\"hex\" (string) the block hash hex encoded\n"
+ "\"hex\" (string) the block hash, hex-encoded\n"
"\nExamples:\n"
+ HelpExampleCli("getbestblockhash", "")
+ HelpExampleRpc("getbestblockhash", "")
@@ -260,7 +261,7 @@ static UniValue waitforblock(const JSONRPCRequest& request)
);
int timeout = 0;
- uint256 hash = uint256S(request.params[0].get_str());
+ uint256 hash(ParseHashV(request.params[0], "blockhash"));
if (!request.params[1].isNull())
timeout = request.params[1].get_int();
@@ -508,17 +509,17 @@ static UniValue getmempoolancestors(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) {
throw std::runtime_error(
- "getmempoolancestors txid (verbose)\n"
+ "getmempoolancestors txid ( verbose )\n"
"\nIf txid is in the mempool, returns all in-mempool ancestors.\n"
"\nArguments:\n"
"1. \"txid\" (string, required) The transaction id (must be in mempool)\n"
"2. verbose (boolean, optional, default=false) True for a json object, false for array of transaction ids\n"
- "\nResult (for verbose=false):\n"
+ "\nResult (for verbose = false):\n"
"[ (json array of strings)\n"
" \"transactionid\" (string) The transaction id of an in-mempool ancestor transaction\n"
" ,...\n"
"]\n"
- "\nResult (for verbose=true):\n"
+ "\nResult (for verbose = true):\n"
"{ (json object)\n"
" \"transactionid\" : { (json object)\n"
+ EntryDescriptionString()
@@ -572,17 +573,17 @@ static UniValue getmempooldescendants(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) {
throw std::runtime_error(
- "getmempooldescendants txid (verbose)\n"
+ "getmempooldescendants txid ( verbose )\n"
"\nIf txid is in the mempool, returns all in-mempool descendants.\n"
"\nArguments:\n"
"1. \"txid\" (string, required) The transaction id (must be in mempool)\n"
"2. verbose (boolean, optional, default=false) True for a json object, false for array of transaction ids\n"
- "\nResult (for verbose=false):\n"
+ "\nResult (for verbose = false):\n"
"[ (json array of strings)\n"
" \"transactionid\" (string) The transaction id of an in-mempool descendant transaction\n"
" ,...\n"
"]\n"
- "\nResult (for verbose=true):\n"
+ "\nResult (for verbose = true):\n"
"{ (json object)\n"
" \"transactionid\" : { (json object)\n"
+ EntryDescriptionString()
@@ -699,7 +700,7 @@ static UniValue getblockheader(const JSONRPCRequest& request)
"If verbose is true, returns an Object with information about blockheader <hash>.\n"
"\nArguments:\n"
"1. \"hash\" (string, required) The block hash\n"
- "2. verbose (boolean, optional, default=true) true for a json object, false for the hex encoded data\n"
+ "2. verbose (boolean, optional, default=true) true for a json object, false for the hex-encoded data\n"
"\nResult (for verbose = true):\n"
"{\n"
" \"hash\" : \"hash\", (string) the block hash (same as provided)\n"
@@ -727,8 +728,7 @@ static UniValue getblockheader(const JSONRPCRequest& request)
LOCK(cs_main);
- std::string strHash = request.params[0].get_str();
- uint256 hash(uint256S(strHash));
+ uint256 hash(ParseHashV(request.params[0], "hash"));
bool fVerbose = true;
if (!request.params[1].isNull())
@@ -779,7 +779,7 @@ static UniValue getblock(const JSONRPCRequest& request)
"If verbosity is 2, returns an Object with information about block <hash> and information about each transaction. \n"
"\nArguments:\n"
"1. \"blockhash\" (string, required) The block hash\n"
- "2. verbosity (numeric, optional, default=1) 0 for hex encoded data, 1 for a json object, and 2 for json object with transaction data\n"
+ "2. verbosity (numeric, optional, default=1) 0 for hex-encoded data, 1 for a json object, and 2 for json object with transaction data\n"
"\nResult (for verbosity = 0):\n"
"\"data\" (string) A string that is serialized, hex-encoded data for block 'hash'.\n"
"\nResult (for verbosity = 1):\n"
@@ -822,8 +822,7 @@ static UniValue getblock(const JSONRPCRequest& request)
LOCK(cs_main);
- std::string strHash = request.params[0].get_str();
- uint256 hash(uint256S(strHash));
+ uint256 hash(ParseHashV(request.params[0], "blockhash"));
int verbosity = 1;
if (!request.params[1].isNull()) {
@@ -1047,7 +1046,7 @@ UniValue gettxout(const JSONRPCRequest& request)
+ HelpExampleCli("listunspent", "") +
"\nView the details\n"
+ HelpExampleCli("gettxout", "\"txid\" 1") +
- "\nAs a json rpc call\n"
+ "\nAs a JSON-RPC call\n"
+ HelpExampleRpc("gettxout", "\"txid\", 1")
);
@@ -1055,8 +1054,7 @@ UniValue gettxout(const JSONRPCRequest& request)
UniValue ret(UniValue::VOBJ);
- std::string strHash = request.params[0].get_str();
- uint256 hash(uint256S(strHash));
+ uint256 hash(ParseHashV(request.params[0], "txid"));
int n = request.params[1].get_int();
COutPoint out(hash, n);
bool fMempool = true;
@@ -1464,8 +1462,7 @@ static UniValue preciousblock(const JSONRPCRequest& request)
+ HelpExampleRpc("preciousblock", "\"blockhash\"")
);
- std::string strHash = request.params[0].get_str();
- uint256 hash(uint256S(strHash));
+ uint256 hash(ParseHashV(request.params[0], "blockhash"));
CBlockIndex* pblockindex;
{
@@ -1500,8 +1497,7 @@ static UniValue invalidateblock(const JSONRPCRequest& request)
+ HelpExampleRpc("invalidateblock", "\"blockhash\"")
);
- std::string strHash = request.params[0].get_str();
- uint256 hash(uint256S(strHash));
+ uint256 hash(ParseHashV(request.params[0], "blockhash"));
CValidationState state;
{
@@ -1540,8 +1536,7 @@ static UniValue reconsiderblock(const JSONRPCRequest& request)
+ HelpExampleRpc("reconsiderblock", "\"blockhash\"")
);
- std::string strHash = request.params[0].get_str();
- uint256 hash(uint256S(strHash));
+ uint256 hash(ParseHashV(request.params[0], "blockhash"));
{
LOCK(cs_main);
@@ -1594,7 +1589,7 @@ static UniValue getchaintxstats(const JSONRPCRequest& request)
LOCK(cs_main);
pindex = chainActive.Tip();
} else {
- uint256 hash = uint256S(request.params[1].get_str());
+ uint256 hash(ParseHashV(request.params[1], "blockhash"));
LOCK(cs_main);
pindex = LookupBlockIndex(hash);
if (!pindex) {
@@ -1768,8 +1763,7 @@ static UniValue getblockstats(const JSONRPCRequest& request)
pindex = chainActive[height];
} else {
- const std::string strHash = request.params[0].get_str();
- const uint256 hash(uint256S(strHash));
+ const uint256 hash(ParseHashV(request.params[0], "hash_or_height"));
pindex = LookupBlockIndex(hash);
if (!pindex) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp
index b1bea85fef..c565b9b4f9 100644
--- a/src/rpc/mining.cpp
+++ b/src/rpc/mining.cpp
@@ -24,6 +24,7 @@
#include <utilstrencodings.h>
#include <validation.h>
#include <validationinterface.h>
+#include <versionbitsinfo.h>
#include <warnings.h>
#include <memory>
@@ -247,7 +248,7 @@ static UniValue prioritisetransaction(const JSONRPCRequest& request)
LOCK(cs_main);
- uint256 hash = ParseHashStr(request.params[0].get_str(), "txid");
+ uint256 hash(ParseHashV(request.params[0], "txid"));
CAmount nAmount = request.params[2].get_int64();
if (!(request.params[1].isNull() || request.params[1].get_real() == 0)) {
@@ -361,8 +362,8 @@ static UniValue getblocktemplate(const JSONRPCRequest& request)
"}\n"
"\nExamples:\n"
- + HelpExampleCli("getblocktemplate", "")
- + HelpExampleRpc("getblocktemplate", "")
+ + HelpExampleCli("getblocktemplate", "{\"rules\": [\"segwit\"]}")
+ + HelpExampleRpc("getblocktemplate", "{\"rules\": [\"segwit\"]}")
);
LOCK(cs_main);
@@ -455,7 +456,7 @@ static UniValue getblocktemplate(const JSONRPCRequest& request)
// Format: <hashBestChain><nTransactionsUpdatedLast>
std::string lpstr = lpval.get_str();
- hashWatchedChain.SetHex(lpstr.substr(0, 64));
+ hashWatchedChain = ParseHashV(lpstr.substr(0, 64), "longpollid");
nTransactionsUpdatedLastLP = atoi64(lpstr.substr(64));
}
else
@@ -795,12 +796,6 @@ static UniValue submitheader(const JSONRPCRequest& request)
throw JSONRPCError(RPC_VERIFY_ERROR, state.GetRejectReason());
}
-static UniValue estimatefee(const JSONRPCRequest& request)
-{
- throw JSONRPCError(RPC_METHOD_DEPRECATED, "estimatefee was removed in v0.17.\n"
- "Clients should use estimatesmartfee.");
-}
-
static UniValue estimatesmartfee(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
@@ -818,7 +813,7 @@ static UniValue estimatesmartfee(const JSONRPCRequest& request)
" higher feerate and is more likely to be sufficient for the desired\n"
" target, but is not as responsive to short term drops in the\n"
" prevailing fee market. Must be one of:\n"
- " \"UNSET\" (defaults to CONSERVATIVE)\n"
+ " \"UNSET\"\n"
" \"ECONOMICAL\"\n"
" \"CONSERVATIVE\"\n"
"\nResult:\n"
@@ -978,7 +973,6 @@ static const CRPCCommand commands[] =
{ "generating", "generatetoaddress", &generatetoaddress, {"nblocks","address","maxtries"} },
- { "hidden", "estimatefee", &estimatefee, {} },
{ "util", "estimatesmartfee", &estimatesmartfee, {"conf_target", "estimate_mode"} },
{ "hidden", "estimaterawfee", &estimaterawfee, {"conf_target", "threshold"} },
diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp
index 0f3b601414..6a66998d37 100644
--- a/src/rpc/misc.cpp
+++ b/src/rpc/misc.cpp
@@ -44,7 +44,7 @@ static UniValue validateaddress(const JSONRPCRequest& request)
"{\n"
" \"isvalid\" : true|false, (boolean) If the address is valid or not. If not, this is the only property returned.\n"
" \"address\" : \"address\", (string) The bitcoin address validated\n"
- " \"scriptPubKey\" : \"hex\", (string) The hex encoded scriptPubKey generated by the address\n"
+ " \"scriptPubKey\" : \"hex\", (string) The hex-encoded scriptPubKey generated by the address\n"
" \"isscript\" : true|false, (boolean) If the key is a script\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"
@@ -99,7 +99,7 @@ static UniValue createmultisig(const JSONRPCRequest& request)
"\nExamples:\n"
"\nCreate a multisig address from 2 public keys\n"
+ HelpExampleCli("createmultisig", "2 \"[\\\"03789ed0bb717d88f7d321a368d905e7430207ebbd82bd342cf11ae157a7ace5fd\\\",\\\"03dbc6764b8884a92e871274b87583e6d5c2a58819473e17e107ef3f6aa5a61626\\\"]\"") +
- "\nAs a json rpc call\n"
+ "\nAs a JSON-RPC call\n"
+ HelpExampleRpc("createmultisig", "2, \"[\\\"03789ed0bb717d88f7d321a368d905e7430207ebbd82bd342cf11ae157a7ace5fd\\\",\\\"03dbc6764b8884a92e871274b87583e6d5c2a58819473e17e107ef3f6aa5a61626\\\"]\"")
;
throw std::runtime_error(msg);
@@ -157,7 +157,7 @@ static UniValue verifymessage(const JSONRPCRequest& request)
+ HelpExampleCli("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"my message\"") +
"\nVerify the signature\n"
+ HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"signature\" \"my message\"") +
- "\nAs json rpc\n"
+ "\nAs a JSON-RPC call\n"
+ HelpExampleRpc("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\", \"signature\", \"my message\"")
);
@@ -210,7 +210,7 @@ static UniValue signmessagewithprivkey(const JSONRPCRequest& request)
+ HelpExampleCli("signmessagewithprivkey", "\"privkey\" \"my message\"") +
"\nVerify the signature\n"
+ HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"signature\" \"my message\"") +
- "\nAs json rpc\n"
+ "\nAs a JSON-RPC call\n"
+ HelpExampleRpc("signmessagewithprivkey", "\"privkey\", \"my message\"")
);
diff --git a/src/rpc/protocol.cpp b/src/rpc/protocol.cpp
index 55bebb5662..ee178f34ce 100644
--- a/src/rpc/protocol.cpp
+++ b/src/rpc/protocol.cpp
@@ -12,8 +12,6 @@
#include <utiltime.h>
#include <version.h>
-#include <fstream>
-
/**
* JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
* but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
@@ -85,9 +83,9 @@ bool GenerateAuthCookie(std::string *cookie_out)
/** the umask determines what permissions are used to create this file -
* these are set to 077 in init.cpp unless overridden with -sysperms.
*/
- std::ofstream file;
+ fsbridge::ofstream file;
fs::path filepath_tmp = GetAuthCookieFile(true);
- file.open(filepath_tmp.string().c_str());
+ file.open(filepath_tmp);
if (!file.is_open()) {
LogPrintf("Unable to open cookie authentication file %s for writing\n", filepath_tmp.string());
return false;
@@ -109,10 +107,10 @@ bool GenerateAuthCookie(std::string *cookie_out)
bool GetAuthCookie(std::string *cookie_out)
{
- std::ifstream file;
+ fsbridge::ifstream file;
std::string cookie;
fs::path filepath = GetAuthCookieFile();
- file.open(filepath.string().c_str());
+ file.open(filepath);
if (!file.is_open())
return false;
std::getline(file, cookie);
diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp
index 798d54f35d..a2d990b51d 100644
--- a/src/rpc/rawtransaction.cpp
+++ b/src/rpc/rawtransaction.cpp
@@ -226,9 +226,7 @@ static UniValue gettxoutproof(const JSONRPCRequest& request)
UniValue txids = request.params[0].get_array();
for (unsigned int idx = 0; idx < txids.size(); idx++) {
const UniValue& txid = txids[idx];
- if (txid.get_str().length() != 64 || !IsHex(txid.get_str()))
- throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid txid ")+txid.get_str());
- uint256 hash(uint256S(txid.get_str()));
+ uint256 hash(ParseHashV(txid, "txid"));
if (setTxids.count(hash))
throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated txid: ")+txid.get_str());
setTxids.insert(hash);
@@ -239,7 +237,7 @@ static UniValue gettxoutproof(const JSONRPCRequest& request)
uint256 hashBlock;
if (!request.params[1].isNull()) {
LOCK(cs_main);
- hashBlock = uint256S(request.params[1].get_str());
+ hashBlock = ParseHashV(request.params[1], "blockhash");
pblockindex = LookupBlockIndex(hashBlock);
if (!pblockindex) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
@@ -468,13 +466,13 @@ static UniValue createrawtransaction(const JSONRPCRequest& request)
" \"address\": x.xxx, (obj, optional) A key-value pair. The key (string) is the bitcoin address, the value (float or string) is the amount in " + CURRENCY_UNIT + "\n"
" },\n"
" {\n"
- " \"data\": \"hex\" (obj, optional) A key-value pair. The key must be \"data\", the value is hex encoded data\n"
+ " \"data\": \"hex\" (obj, optional) A key-value pair. The key must be \"data\", the value is hex-encoded data\n"
" }\n"
" ,... More key-value pairs of the above form. For compatibility reasons, a dictionary, which holds the key-value pairs directly, is also\n"
" accepted as second parameter.\n"
" ]\n"
"3. locktime (numeric, optional, default=0) Raw locktime. Non-0 value also locktime-activates inputs\n"
- "4. replaceable (boolean, optional, default=false) Marks this transaction as BIP125 replaceable.\n"
+ "4. replaceable (boolean, optional, default=false) Marks this transaction as BIP125-replaceable.\n"
" Allows this transaction to be replaced by a transaction with higher fees. If provided, it is an error if explicit sequence numbers are incompatible.\n"
"\nResult:\n"
"\"transaction\" (string) hex string of the transaction\n"
@@ -583,11 +581,11 @@ static UniValue decodescript(const JSONRPCRequest& request)
"decodescript \"hexstring\"\n"
"\nDecode a hex-encoded script.\n"
"\nArguments:\n"
- "1. \"hexstring\" (string) the hex encoded script\n"
+ "1. \"hexstring\" (string) the hex-encoded script\n"
"\nResult:\n"
"{\n"
" \"asm\":\"asm\", (string) Script public key\n"
- " \"hex\":\"hex\", (string) hex encoded public key\n"
+ " \"hex\":\"hex\", (string) hex-encoded public key\n"
" \"type\":\"type\", (string) The output type\n"
" \"reqSigs\": n, (numeric) The required signatures\n"
" \"addresses\": [ (json array of string)\n"
@@ -924,7 +922,7 @@ static UniValue signrawtransactionwithkey(const JSONRPCRequest& request)
" }\n"
" ,...\n"
" ]\n"
- "4. \"sighashtype\" (string, optional, default=ALL) The signature hash type. Must be one of\n"
+ "4. \"sighashtype\" (string, optional, default=ALL) The signature hash type. Must be one of:\n"
" \"ALL\"\n"
" \"NONE\"\n"
" \"SINGLE\"\n"
@@ -1001,7 +999,7 @@ static UniValue sendrawtransaction(const JSONRPCRequest& request)
+ HelpExampleCli("signrawtransactionwithwallet", "\"myhex\"") +
"\nSend the transaction (signed hex)\n"
+ HelpExampleCli("sendrawtransaction", "\"signedhex\"") +
- "\nAs a json rpc call\n"
+ "\nAs a JSON-RPC call\n"
+ HelpExampleRpc("sendrawtransaction", "\"signedhex\"")
);
@@ -1106,7 +1104,7 @@ static UniValue testmempoolaccept(const JSONRPCRequest& request)
+ HelpExampleCli("signrawtransactionwithwallet", "\"myhex\"") +
"\nTest acceptance of the transaction (signed hex)\n"
+ HelpExampleCli("testmempoolaccept", "\"signedhex\"") +
- "\nAs a json rpc call\n"
+ "\nAs a JSON-RPC call\n"
+ HelpExampleRpc("testmempoolaccept", "[\"signedhex\"]")
// clang-format on
);
@@ -1589,7 +1587,7 @@ UniValue createpsbt(const JSONRPCRequest& request)
" \"address\": x.xxx, (obj, optional) A key-value pair. The key (string) is the bitcoin address, the value (float or string) is the amount in " + CURRENCY_UNIT + "\n"
" },\n"
" {\n"
- " \"data\": \"hex\" (obj, optional) A key-value pair. The key must be \"data\", the value is hex encoded data\n"
+ " \"data\": \"hex\" (obj, optional) A key-value pair. The key must be \"data\", the value is hex-encoded data\n"
" }\n"
" ,... More key-value pairs of the above form. For compatibility reasons, a dictionary, which holds the key-value pairs directly, is also\n"
" accepted as second parameter.\n"
diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp
index 9eb55880b3..60bf3c28c0 100644
--- a/src/rpc/server.cpp
+++ b/src/rpc/server.cpp
@@ -116,16 +116,12 @@ CAmount AmountFromValue(const UniValue& value)
uint256 ParseHashV(const UniValue& v, std::string strName)
{
- std::string strHex;
- if (v.isStr())
- strHex = v.get_str();
+ std::string strHex(v.get_str());
+ if (64 != strHex.length())
+ throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("%s must be of length %d (not %d, for '%s')", strName, 64, strHex.length(), strHex));
if (!IsHex(strHex)) // Note: IsHex("") is false
throw JSONRPCError(RPC_INVALID_PARAMETER, strName+" must be hexadecimal string (not '"+strHex+"')");
- if (64 != strHex.length())
- throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("%s must be of length %d (not %d)", strName, 64, strHex.length()));
- uint256 result;
- result.SetHex(strHex);
- return result;
+ return uint256S(strHex);
}
uint256 ParseHashO(const UniValue& o, std::string strKey)
{
diff --git a/src/script/ismine.cpp b/src/script/ismine.cpp
index 1433ebf42f..51bd2d6e9f 100644
--- a/src/script/ismine.cpp
+++ b/src/script/ismine.cpp
@@ -23,9 +23,9 @@ namespace {
*/
enum class IsMineSigVersion
{
- TOP = 0, //! scriptPubKey execution
- P2SH = 1, //! P2SH redeemScript
- WITNESS_V0 = 2 //! P2WSH witness script execution
+ TOP = 0, //!< scriptPubKey execution
+ P2SH = 1, //!< P2SH redeemScript
+ WITNESS_V0 = 2, //!< P2WSH witness script execution
};
/**
@@ -35,10 +35,10 @@ enum class IsMineSigVersion
*/
enum class IsMineResult
{
- NO = 0, //! Not ours
- WATCH_ONLY = 1, //! Included in watch-only balance
- SPENDABLE = 2, //! Included in all balances
- INVALID = 3, //! Not spendable by anyone (uncompressed pubkey in segwit, P2SH inside P2SH or witness, witness inside witness)
+ NO = 0, //!< Not ours
+ WATCH_ONLY = 1, //!< Included in watch-only balance
+ SPENDABLE = 2, //!< Included in all balances
+ INVALID = 3, //!< Not spendable by anyone (uncompressed pubkey in segwit, P2SH inside P2SH or witness, witness inside witness)
};
bool PermitsUncompressed(IsMineSigVersion sigversion)
diff --git a/src/script/sign.cpp b/src/script/sign.cpp
index d779910425..0042f35e2e 100644
--- a/src/script/sign.cpp
+++ b/src/script/sign.cpp
@@ -73,15 +73,18 @@ static bool GetPubKey(const SigningProvider& provider, SignatureData& sigdata, c
return false;
}
-static bool CreateSig(const BaseSignatureCreator& creator, SignatureData& sigdata, const SigningProvider& provider, std::vector<unsigned char>& sig_out, const CKeyID& keyid, const CScript& scriptcode, SigVersion sigversion)
+static bool CreateSig(const BaseSignatureCreator& creator, SignatureData& sigdata, const SigningProvider& provider, std::vector<unsigned char>& sig_out, const CPubKey& pubkey, const CScript& scriptcode, SigVersion sigversion)
{
+ CKeyID keyid = pubkey.GetID();
const auto it = sigdata.signatures.find(keyid);
if (it != sigdata.signatures.end()) {
sig_out = it->second.second;
return true;
}
- CPubKey pubkey;
- GetPubKey(provider, sigdata, keyid, pubkey);
+ KeyOriginInfo info;
+ if (provider.GetKeyOrigin(keyid, info)) {
+ sigdata.misc_pubkeys.emplace(keyid, std::make_pair(pubkey, std::move(info)));
+ }
if (creator.CreateSig(provider, sig_out, keyid, scriptcode, sigversion)) {
auto i = sigdata.signatures.emplace(keyid, SigPair(pubkey, sig_out));
assert(i.second);
@@ -114,15 +117,15 @@ static bool SignStep(const SigningProvider& provider, const BaseSignatureCreator
case TX_WITNESS_UNKNOWN:
return false;
case TX_PUBKEY:
- if (!CreateSig(creator, sigdata, provider, sig, CPubKey(vSolutions[0]).GetID(), scriptPubKey, sigversion)) return false;
+ if (!CreateSig(creator, sigdata, provider, sig, CPubKey(vSolutions[0]), scriptPubKey, sigversion)) return false;
ret.push_back(std::move(sig));
return true;
case TX_PUBKEYHASH: {
CKeyID keyID = CKeyID(uint160(vSolutions[0]));
- if (!CreateSig(creator, sigdata, provider, sig, keyID, scriptPubKey, sigversion)) return false;
- ret.push_back(std::move(sig));
CPubKey pubkey;
GetPubKey(provider, sigdata, keyID, pubkey);
+ if (!CreateSig(creator, sigdata, provider, sig, pubkey, scriptPubKey, sigversion)) return false;
+ ret.push_back(std::move(sig));
ret.push_back(ToByteVector(pubkey));
return true;
}
@@ -138,7 +141,7 @@ static bool SignStep(const SigningProvider& provider, const BaseSignatureCreator
ret.push_back(valtype()); // workaround CHECKMULTISIG bug
for (size_t i = 1; i < vSolutions.size() - 1; ++i) {
CPubKey pubkey = CPubKey(vSolutions[i]);
- if (ret.size() < required + 1 && CreateSig(creator, sigdata, provider, sig, pubkey.GetID(), scriptPubKey, sigversion)) {
+ if (ret.size() < required + 1 && CreateSig(creator, sigdata, provider, sig, pubkey, scriptPubKey, sigversion)) {
ret.push_back(std::move(sig));
}
}
diff --git a/src/test/addrman_tests.cpp b/src/test/addrman_tests.cpp
index f57d0c6d79..8c2873d916 100644
--- a/src/test/addrman_tests.cpp
+++ b/src/test/addrman_tests.cpp
@@ -40,22 +40,26 @@ public:
CAddrInfo* Find(const CNetAddr& addr, int* pnId = nullptr)
{
+ LOCK(cs);
return CAddrMan::Find(addr, pnId);
}
CAddrInfo* Create(const CAddress& addr, const CNetAddr& addrSource, int* pnId = nullptr)
{
+ LOCK(cs);
return CAddrMan::Create(addr, addrSource, pnId);
}
void Delete(int nId)
{
+ LOCK(cs);
CAddrMan::Delete(nId);
}
// Simulates connection failure so that we can test eviction of offline nodes
void SimConnFail(CService& addr)
{
+ LOCK(cs);
int64_t nLastSuccess = 1;
Good_(addr, true, nLastSuccess); // Set last good connection in the deep past.
diff --git a/src/test/blockfilter_tests.cpp b/src/test/blockfilter_tests.cpp
index 773de343ea..4941ebd483 100644
--- a/src/test/blockfilter_tests.cpp
+++ b/src/test/blockfilter_tests.cpp
@@ -114,7 +114,8 @@ BOOST_AUTO_TEST_CASE(blockfilters_json_test)
unsigned int pos = 0;
/*int block_height =*/ test[pos++].get_int();
- /*uint256 block_hash =*/ ParseHashStr(test[pos++].get_str(), "block_hash");
+ uint256 block_hash;
+ BOOST_CHECK(ParseHashStr(test[pos++].get_str(), block_hash));
CBlock block;
BOOST_REQUIRE(DecodeHexBlk(block, test[pos++].get_str()));
@@ -129,9 +130,11 @@ BOOST_AUTO_TEST_CASE(blockfilters_json_test)
tx_undo.vprevout.emplace_back(txout, 0, false);
}
- uint256 prev_filter_header_basic = ParseHashStr(test[pos++].get_str(), "prev_filter_header_basic");
+ uint256 prev_filter_header_basic;
+ BOOST_CHECK(ParseHashStr(test[pos++].get_str(), prev_filter_header_basic));
std::vector<unsigned char> filter_basic = ParseHex(test[pos++].get_str());
- uint256 filter_header_basic = ParseHashStr(test[pos++].get_str(), "filter_header_basic");
+ uint256 filter_header_basic;
+ BOOST_CHECK(ParseHashStr(test[pos++].get_str(), filter_header_basic));
BlockFilter computed_filter_basic(BlockFilterType::BASIC, block, block_undo);
BOOST_CHECK(computed_filter_basic.GetFilter().GetEncoded() == filter_basic);
diff --git a/src/test/fs_tests.cpp b/src/test/fs_tests.cpp
new file mode 100644
index 0000000000..93aee10bb7
--- /dev/null
+++ b/src/test/fs_tests.cpp
@@ -0,0 +1,56 @@
+// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+//
+#include <fs.h>
+#include <test/test_bitcoin.h>
+
+#include <boost/test/unit_test.hpp>
+
+BOOST_FIXTURE_TEST_SUITE(fs_tests, BasicTestingSetup)
+
+BOOST_AUTO_TEST_CASE(fsbridge_fstream)
+{
+ fs::path tmpfolder = SetDataDir("fsbridge_fstream");
+ // tmpfile1 should be the same as tmpfile2
+ fs::path tmpfile1 = tmpfolder / "fs_tests_₿_🏃";
+ fs::path tmpfile2 = tmpfolder / L"fs_tests_₿_🏃";
+ {
+ fsbridge::ofstream file(tmpfile1);
+ file << "bitcoin";
+ }
+ {
+ fsbridge::ifstream file(tmpfile2);
+ std::string input_buffer;
+ file >> input_buffer;
+ BOOST_CHECK_EQUAL(input_buffer, "bitcoin");
+ }
+ {
+ fsbridge::ifstream file(tmpfile1, std::ios_base::in | std::ios_base::ate);
+ std::string input_buffer;
+ file >> input_buffer;
+ BOOST_CHECK_EQUAL(input_buffer, "");
+ }
+ {
+ fsbridge::ofstream file(tmpfile2, std::ios_base::out | std::ios_base::app);
+ file << "tests";
+ }
+ {
+ fsbridge::ifstream file(tmpfile1);
+ std::string input_buffer;
+ file >> input_buffer;
+ BOOST_CHECK_EQUAL(input_buffer, "bitcointests");
+ }
+ {
+ fsbridge::ofstream file(tmpfile2, std::ios_base::out | std::ios_base::trunc);
+ file << "bitcoin";
+ }
+ {
+ fsbridge::ifstream file(tmpfile1);
+ std::string input_buffer;
+ file >> input_buffer;
+ BOOST_CHECK_EQUAL(input_buffer, "bitcoin");
+ }
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp
index 67c377778f..7fbf37e7fb 100644
--- a/src/test/script_tests.cpp
+++ b/src/test/script_tests.cpp
@@ -1013,21 +1013,21 @@ BOOST_AUTO_TEST_CASE(script_PushData)
ScriptError err;
std::vector<std::vector<unsigned char> > directStack;
- BOOST_CHECK(EvalScript(directStack, CScript(&direct[0], &direct[sizeof(direct)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SigVersion::BASE, &err));
+ BOOST_CHECK(EvalScript(directStack, CScript(direct, direct + sizeof(direct)), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SigVersion::BASE, &err));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
std::vector<std::vector<unsigned char> > pushdata1Stack;
- BOOST_CHECK(EvalScript(pushdata1Stack, CScript(&pushdata1[0], &pushdata1[sizeof(pushdata1)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SigVersion::BASE, &err));
+ BOOST_CHECK(EvalScript(pushdata1Stack, CScript(pushdata1, pushdata1 + sizeof(pushdata1)), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SigVersion::BASE, &err));
BOOST_CHECK(pushdata1Stack == directStack);
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
std::vector<std::vector<unsigned char> > pushdata2Stack;
- BOOST_CHECK(EvalScript(pushdata2Stack, CScript(&pushdata2[0], &pushdata2[sizeof(pushdata2)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SigVersion::BASE, &err));
+ BOOST_CHECK(EvalScript(pushdata2Stack, CScript(pushdata2, pushdata2 + sizeof(pushdata2)), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SigVersion::BASE, &err));
BOOST_CHECK(pushdata2Stack == directStack);
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
std::vector<std::vector<unsigned char> > pushdata4Stack;
- BOOST_CHECK(EvalScript(pushdata4Stack, CScript(&pushdata4[0], &pushdata4[sizeof(pushdata4)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SigVersion::BASE, &err));
+ BOOST_CHECK(EvalScript(pushdata4Stack, CScript(pushdata4, pushdata4 + sizeof(pushdata4)), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SigVersion::BASE, &err));
BOOST_CHECK(pushdata4Stack == directStack);
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
}
diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp
index 766e34e5b5..f7874e6882 100644
--- a/src/test/test_bitcoin.cpp
+++ b/src/test/test_bitcoin.cpp
@@ -6,6 +6,7 @@
#include <chainparams.h>
#include <consensus/consensus.h>
+#include <consensus/params.h>
#include <consensus/validation.h>
#include <crypto/sha256.h>
#include <miner.h>
@@ -58,6 +59,9 @@ BasicTestingSetup::BasicTestingSetup(const std::string& chainName)
InitSignatureCache();
InitScriptExecutionCache();
fCheckBlockIndex = true;
+ // CreateAndProcessBlock() does not support building SegWit blocks, so don't activate in these tests.
+ // TODO: fix the code to support SegWit blocks.
+ gArgs.ForceSetArg("-vbparams", strprintf("segwit:0:%d", (int64_t)Consensus::BIP9Deployment::NO_TIMEOUT));
SelectParams(chainName);
noui_connect();
}
@@ -128,9 +132,6 @@ TestingSetup::~TestingSetup()
TestChain100Setup::TestChain100Setup() : TestingSetup(CBaseChainParams::REGTEST)
{
- // CreateAndProcessBlock() does not support building SegWit blocks, so don't activate in these tests.
- // TODO: fix the code to support SegWit blocks.
- UpdateVersionBitsParameters(Consensus::DEPLOYMENT_SEGWIT, 0, Consensus::BIP9Deployment::NO_TIMEOUT);
// Generate a 100-block chain:
coinbaseKey.MakeNewKey(true);
CScript scriptPubKey = CScript() << ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG;
diff --git a/src/test/test_bitcoin.h b/src/test/test_bitcoin.h
index b87d9bea5d..3872767133 100644
--- a/src/test/test_bitcoin.h
+++ b/src/test/test_bitcoin.h
@@ -37,6 +37,8 @@ static inline uint64_t InsecureRandBits(int bits) { return insecure_rand_ctx.ran
static inline uint64_t InsecureRandRange(uint64_t range) { return insecure_rand_ctx.randrange(range); }
static inline bool InsecureRandBool() { return insecure_rand_ctx.randbool(); }
+static constexpr CAmount CENT{1000000};
+
/** Basic testing setup.
* This just configures logging and chain parameters.
*/
diff --git a/src/txmempool.h b/src/txmempool.h
index 913501fd66..cda78ea90c 100644
--- a/src/txmempool.h
+++ b/src/txmempool.h
@@ -343,13 +343,13 @@ struct TxMempoolInfo
* this is passed to the notification signal.
*/
enum class MemPoolRemovalReason {
- UNKNOWN = 0, //! Manually removed or unknown reason
- EXPIRY, //! Expired from mempool
- SIZELIMIT, //! Removed in size limiting
- REORG, //! Removed for reorganization
- BLOCK, //! Removed for block
- CONFLICT, //! Removed for conflict with in-block transaction
- REPLACED //! Removed for replacement
+ UNKNOWN = 0, //!< Manually removed or unknown reason
+ EXPIRY, //!< Expired from mempool
+ SIZELIMIT, //!< Removed in size limiting
+ REORG, //!< Removed for reorganization
+ BLOCK, //!< Removed for block
+ CONFLICT, //!< Removed for conflict with in-block transaction
+ REPLACED, //!< Removed for replacement
};
class SaltedTxidHasher
diff --git a/src/util.cpp b/src/util.cpp
index 75a387d7ec..6479b9b9ce 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -61,6 +61,7 @@
#include <codecvt>
#include <io.h> /* for _commit */
+#include <shellapi.h>
#include <shlobj.h>
#endif
@@ -891,7 +892,7 @@ bool ArgsManager::ReadConfigFiles(std::string& error, bool ignore_invalid_keys)
}
const std::string confPath = GetArg("-conf", BITCOIN_CONF_FILENAME);
- fs::ifstream stream(GetConfigFile(confPath));
+ fsbridge::ifstream stream(GetConfigFile(confPath));
// ok to not have a config file
if (stream.good()) {
@@ -924,7 +925,7 @@ bool ArgsManager::ReadConfigFiles(std::string& error, bool ignore_invalid_keys)
}
for (const std::string& to_include : includeconf) {
- fs::ifstream include_config(GetConfigFile(to_include));
+ fsbridge::ifstream include_config(GetConfigFile(to_include));
if (include_config.good()) {
if (!ReadConfigStream(include_config, error, ignore_invalid_keys)) {
return false;
@@ -1200,13 +1201,21 @@ void SetupEnvironment()
} catch (const std::runtime_error&) {
setenv("LC_ALL", "C", 1);
}
+#elif defined(WIN32)
+ // Set the default input/output charset is utf-8
+ SetConsoleCP(CP_UTF8);
+ SetConsoleOutputCP(CP_UTF8);
#endif
// The path locale is lazy initialized and to avoid deinitialization errors
// in multithreading environments, it is set explicitly by the main thread.
// A dummy locale is used to extract the internal default locale, used by
// fs::path, which is then used to explicitly imbue the path.
std::locale loc = fs::path::imbue(std::locale::classic());
+#ifndef WIN32
fs::path::imbue(loc);
+#else
+ fs::path::imbue(std::locale(loc, new std::codecvt_utf8_utf16<wchar_t>()));
+#endif
}
bool SetupNetworking()
@@ -1261,3 +1270,30 @@ int ScheduleBatchPriority()
return 1;
#endif
}
+
+namespace util {
+#ifdef WIN32
+WinCmdLineArgs::WinCmdLineArgs()
+{
+ wchar_t** wargv = CommandLineToArgvW(GetCommandLineW(), &argc);
+ std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> utf8_cvt;
+ argv = new char*[argc];
+ args.resize(argc);
+ for (int i = 0; i < argc; i++) {
+ args[i] = utf8_cvt.to_bytes(wargv[i]);
+ argv[i] = &*args[i].begin();
+ }
+ LocalFree(wargv);
+}
+
+WinCmdLineArgs::~WinCmdLineArgs()
+{
+ delete[] argv;
+}
+
+std::pair<int, char**> WinCmdLineArgs::get()
+{
+ return std::make_pair(argc, argv);
+}
+#endif
+} // namespace util
diff --git a/src/util.h b/src/util.h
index f119385e48..fa6d2cd489 100644
--- a/src/util.h
+++ b/src/util.h
@@ -29,6 +29,7 @@
#include <stdint.h>
#include <string>
#include <unordered_set>
+#include <utility>
#include <vector>
#include <boost/thread/condition_variable.hpp> // for boost::thread_interrupted
@@ -361,6 +362,21 @@ inline void insert(std::set<TsetT>& dst, const Tsrc& src) {
dst.insert(src.begin(), src.end());
}
+#ifdef WIN32
+class WinCmdLineArgs
+{
+public:
+ WinCmdLineArgs();
+ ~WinCmdLineArgs();
+ std::pair<int, char**> get();
+
+private:
+ int argc;
+ char** argv;
+ std::vector<std::string> args;
+};
+#endif
+
} // namespace util
#endif // BITCOIN_UTIL_H
diff --git a/src/utilmoneystr.cpp b/src/utilmoneystr.cpp
index a9af59a11d..326ef9b27a 100644
--- a/src/utilmoneystr.cpp
+++ b/src/utilmoneystr.cpp
@@ -48,7 +48,7 @@ bool ParseMoney(const char* pszIn, CAmount& nRet)
if (*p == '.')
{
p++;
- int64_t nMult = CENT*10;
+ int64_t nMult = COIN / 10;
while (isdigit(*p) && (nMult > 0))
{
nUnits += nMult * (*p++ - '0');
diff --git a/src/versionbits.cpp b/src/versionbits.cpp
index b0d2bc8a14..3f297c0ebb 100644
--- a/src/versionbits.cpp
+++ b/src/versionbits.cpp
@@ -5,21 +5,6 @@
#include <versionbits.h>
#include <consensus/params.h>
-const struct VBDeploymentInfo VersionBitsDeploymentInfo[Consensus::MAX_VERSION_BITS_DEPLOYMENTS] = {
- {
- /*.name =*/ "testdummy",
- /*.gbt_force =*/ true,
- },
- {
- /*.name =*/ "csv",
- /*.gbt_force =*/ true,
- },
- {
- /*.name =*/ "segwit",
- /*.gbt_force =*/ true,
- }
-};
-
ThresholdState AbstractThresholdConditionChecker::GetStateFor(const CBlockIndex* pindexPrev, const Consensus::Params& params, ThresholdConditionCache& cache) const
{
int nPeriod = Period(params);
diff --git a/src/versionbits.h b/src/versionbits.h
index e4bf9cb9be..cdc947cd9e 100644
--- a/src/versionbits.h
+++ b/src/versionbits.h
@@ -30,13 +30,6 @@ enum class ThresholdState {
// will either be nullptr or a block with (height + 1) % Period() == 0.
typedef std::map<const CBlockIndex*, ThresholdState> ThresholdConditionCache;
-struct VBDeploymentInfo {
- /** Deployment name */
- const char *name;
- /** Whether GBT clients can safely ignore this rule in simplified usage */
- bool gbt_force;
-};
-
struct BIP9Stats {
int period;
int threshold;
@@ -45,8 +38,6 @@ struct BIP9Stats {
bool possible;
};
-extern const struct VBDeploymentInfo VersionBitsDeploymentInfo[];
-
/**
* Abstract class that implements BIP9-style threshold logic, and caches results.
*/
diff --git a/src/versionbitsinfo.cpp b/src/versionbitsinfo.cpp
new file mode 100644
index 0000000000..ecf3482927
--- /dev/null
+++ b/src/versionbitsinfo.cpp
@@ -0,0 +1,22 @@
+// Copyright (c) 2016-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <versionbitsinfo.h>
+
+#include <consensus/params.h>
+
+const struct VBDeploymentInfo VersionBitsDeploymentInfo[Consensus::MAX_VERSION_BITS_DEPLOYMENTS] = {
+ {
+ /*.name =*/ "testdummy",
+ /*.gbt_force =*/ true,
+ },
+ {
+ /*.name =*/ "csv",
+ /*.gbt_force =*/ true,
+ },
+ {
+ /*.name =*/ "segwit",
+ /*.gbt_force =*/ true,
+ }
+};
diff --git a/src/versionbitsinfo.h b/src/versionbitsinfo.h
new file mode 100644
index 0000000000..a7822bc747
--- /dev/null
+++ b/src/versionbitsinfo.h
@@ -0,0 +1,17 @@
+// Copyright (c) 2016-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_VERSIONBITSINFO_H
+#define BITCOIN_VERSIONBITSINFO_H
+
+struct VBDeploymentInfo {
+ /** Deployment name */
+ const char *name;
+ /** Whether GBT clients can safely ignore this rule in simplified usage */
+ bool gbt_force;
+};
+
+extern const struct VBDeploymentInfo VersionBitsDeploymentInfo[];
+
+#endif // BITCOIN_VERSIONBITSINFO_H
diff --git a/src/wallet/coinselection.h b/src/wallet/coinselection.h
index 6d755d0969..5348401f45 100644
--- a/src/wallet/coinselection.h
+++ b/src/wallet/coinselection.h
@@ -10,7 +10,7 @@
#include <random.h>
//! target minimum change amount
-static const CAmount MIN_CHANGE = CENT;
+static constexpr CAmount MIN_CHANGE{COIN / 100};
//! final minimum change amount after paying for fees
static const CAmount MIN_FINAL_CHANGE = MIN_CHANGE/2;
diff --git a/src/wallet/init.cpp b/src/wallet/init.cpp
index a299a4ee44..46983642f0 100644
--- a/src/wallet/init.cpp
+++ b/src/wallet/init.cpp
@@ -182,13 +182,18 @@ bool WalletInit::Verify() const
if (gArgs.IsArgSet("-walletdir")) {
fs::path wallet_dir = gArgs.GetArg("-walletdir", "");
- if (!fs::exists(wallet_dir)) {
+ boost::system::error_code error;
+ // The canonical path cleans the path, preventing >1 Berkeley environment instances for the same directory
+ fs::path canonical_wallet_dir = fs::canonical(wallet_dir, error);
+ if (error || !fs::exists(wallet_dir)) {
return InitError(strprintf(_("Specified -walletdir \"%s\" does not exist"), wallet_dir.string()));
} else if (!fs::is_directory(wallet_dir)) {
return InitError(strprintf(_("Specified -walletdir \"%s\" is not a directory"), wallet_dir.string()));
+ // The canonical path transforms relative paths into absolute ones, so we check the non-canonical version
} else if (!wallet_dir.is_absolute()) {
return InitError(strprintf(_("Specified -walletdir \"%s\" is a relative path"), wallet_dir.string()));
}
+ gArgs.ForceSetArg("-walletdir", canonical_wallet_dir.string());
}
LogPrintf("Using wallet directory %s\n", GetWalletDir().string());
diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp
index c82d0e97d4..92457c4644 100644
--- a/src/wallet/rpcdump.cpp
+++ b/src/wallet/rpcdump.cpp
@@ -17,7 +17,6 @@
#include <wallet/rpcwallet.h>
-#include <fstream>
#include <stdint.h>
#include <boost/algorithm/string.hpp>
@@ -415,8 +414,7 @@ UniValue removeprunedfunds(const JSONRPCRequest& request)
LOCK2(cs_main, pwallet->cs_wallet);
- uint256 hash;
- hash.SetHex(request.params[0].get_str());
+ uint256 hash(ParseHashV(request.params[0], "txid"));
std::vector<uint256> vHash;
vHash.push_back(hash);
std::vector<uint256> vHashOut;
@@ -541,8 +539,8 @@ UniValue importwallet(const JSONRPCRequest& request)
EnsureWalletIsUnlocked(pwallet);
- std::ifstream file;
- file.open(request.params[0].get_str().c_str(), std::ios::in | std::ios::ate);
+ fsbridge::ifstream file;
+ file.open(request.params[0].get_str(), std::ios::in | std::ios::ate);
if (!file.is_open()) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot open wallet dump file");
}
@@ -718,8 +716,8 @@ UniValue dumpwallet(const JSONRPCRequest& request)
throw JSONRPCError(RPC_INVALID_PARAMETER, filepath.string() + " already exists. If you are sure this is what you want, move it out of the way first");
}
- std::ofstream file;
- file.open(filepath.string().c_str());
+ fsbridge::ofstream file;
+ file.open(filepath);
if (!file.is_open())
throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot open wallet dump file");
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index 9fe1424d7d..a3f5f8b211 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -504,7 +504,7 @@ static UniValue signmessage(const JSONRPCRequest& request)
+ HelpExampleCli("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"my message\"") +
"\nVerify the signature\n"
+ HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"signature\" \"my message\"") +
- "\nAs json rpc\n"
+ "\nAs a JSON-RPC call\n"
+ HelpExampleRpc("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\", \"my message\"")
);
@@ -566,7 +566,7 @@ static UniValue getreceivedbyaddress(const JSONRPCRequest& request)
+ HelpExampleCli("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" 0") +
"\nThe amount with at least 6 confirmations\n"
+ HelpExampleCli("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" 6") +
- "\nAs a json rpc call\n"
+ "\nAs a JSON-RPC call\n"
+ HelpExampleRpc("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\", 6")
);
@@ -633,7 +633,7 @@ static UniValue getreceivedbylabel(const JSONRPCRequest& request)
+ HelpExampleCli("getreceivedbylabel", "\"tabby\" 0") +
"\nThe amount with at least 6 confirmations\n"
+ HelpExampleCli("getreceivedbylabel", "\"tabby\" 6") +
- "\nAs a json rpc call\n"
+ "\nAs a JSON-RPC call\n"
+ HelpExampleRpc("getreceivedbylabel", "\"tabby\", 6")
);
@@ -699,7 +699,7 @@ static UniValue getbalance(const JSONRPCRequest& request)
+ HelpExampleCli("getbalance", "") +
"\nThe total amount in the wallet at least 6 blocks confirmed\n"
+ HelpExampleCli("getbalance", "\"*\" 6") +
- "\nAs a json rpc call\n"
+ "\nAs a JSON-RPC call\n"
+ HelpExampleRpc("getbalance", "\"*\", 6")
);
@@ -798,7 +798,7 @@ static UniValue sendmany(const JSONRPCRequest& request)
+ HelpExampleCli("sendmany", "\"\" \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\" 6 \"testing\"") +
"\nSend two amounts to two different addresses, subtract fee from amount:\n"
+ HelpExampleCli("sendmany", "\"\" \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\" 1 \"\" \"[\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\\\",\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\"]\"") +
- "\nAs a json rpc call\n"
+ "\nAs a JSON-RPC call\n"
+ HelpExampleRpc("sendmany", "\"\", {\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\":0.01,\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\":0.02}, 6, \"testing\"")
);
@@ -939,7 +939,7 @@ static UniValue addmultisigaddress(const JSONRPCRequest& request)
"\nExamples:\n"
"\nAdd a multisig address from 2 addresses\n"
+ HelpExampleCli("addmultisigaddress", "2 \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"") +
- "\nAs json rpc call\n"
+ "\nAs a JSON-RPC call\n"
+ HelpExampleRpc("addmultisigaddress", "2, \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"")
;
throw std::runtime_error(msg);
@@ -1500,7 +1500,7 @@ UniValue listtransactions(const JSONRPCRequest& request)
+ HelpExampleCli("listtransactions", "") +
"\nList transactions 100 to 120\n"
+ HelpExampleCli("listtransactions", "\"*\" 20 100") +
- "\nAs a json rpc call\n"
+ "\nAs a JSON-RPC call\n"
+ HelpExampleRpc("listtransactions", "\"*\", 20, 100")
);
@@ -1638,9 +1638,8 @@ static UniValue listsinceblock(const JSONRPCRequest& request)
isminefilter filter = ISMINE_SPENDABLE;
if (!request.params[0].isNull() && !request.params[0].get_str().empty()) {
- uint256 blockId;
+ uint256 blockId(ParseHashV(request.params[0], "blockhash"));
- blockId.SetHex(request.params[0].get_str());
paltindex = pindex = LookupBlockIndex(blockId);
if (!pindex) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
@@ -1768,8 +1767,7 @@ static UniValue gettransaction(const JSONRPCRequest& request)
LOCK2(cs_main, pwallet->cs_wallet);
- uint256 hash;
- hash.SetHex(request.params[0].get_str());
+ uint256 hash(ParseHashV(request.params[0], "txid"));
isminefilter filter = ISMINE_SPENDABLE;
if(!request.params[1].isNull())
@@ -1836,8 +1834,7 @@ static UniValue abandontransaction(const JSONRPCRequest& request)
LOCK2(cs_main, pwallet->cs_wallet);
- uint256 hash;
- hash.SetHex(request.params[0].get_str());
+ uint256 hash(ParseHashV(request.params[0], "txid"));
if (!pwallet->mapWallet.count(hash)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id");
@@ -1963,7 +1960,7 @@ static UniValue walletpassphrase(const JSONRPCRequest& request)
+ HelpExampleCli("walletpassphrase", "\"my pass phrase\" 60") +
"\nLock the wallet again (before 60 seconds)\n"
+ HelpExampleCli("walletlock", "") +
- "\nAs json rpc call\n"
+ "\nAs a JSON-RPC call\n"
+ HelpExampleRpc("walletpassphrase", "\"my pass phrase\", 60")
);
}
@@ -2086,7 +2083,7 @@ static UniValue walletlock(const JSONRPCRequest& request)
+ HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 1.0") +
"\nClear the passphrase since we are done before 2 minutes is up\n"
+ HelpExampleCli("walletlock", "") +
- "\nAs json rpc call\n"
+ "\nAs a JSON-RPC call\n"
+ HelpExampleRpc("walletlock", "")
);
}
@@ -2132,7 +2129,7 @@ static UniValue encryptwallet(const JSONRPCRequest& request)
+ HelpExampleCli("signmessage", "\"address\" \"test message\"") +
"\nNow lock the wallet again by removing the passphrase\n"
+ HelpExampleCli("walletlock", "") +
- "\nAs a json rpc call\n"
+ "\nAs a JSON-RPC call\n"
+ HelpExampleRpc("encryptwallet", "\"my pass phrase\"")
);
}
@@ -2203,7 +2200,7 @@ static UniValue lockunspent(const JSONRPCRequest& request)
+ HelpExampleCli("listlockunspent", "") +
"\nUnlock the transaction again\n"
+ HelpExampleCli("lockunspent", "true \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
- "\nAs a json rpc call\n"
+ "\nAs a JSON-RPC call\n"
+ HelpExampleRpc("lockunspent", "false, \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"")
);
@@ -2241,17 +2238,13 @@ static UniValue lockunspent(const JSONRPCRequest& request)
{"vout", UniValueType(UniValue::VNUM)},
});
- const std::string& txid = find_value(o, "txid").get_str();
- if (!IsHex(txid)) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected hex txid");
- }
-
+ const uint256 txid(ParseHashO(o, "txid"));
const int nOutput = find_value(o, "vout").get_int();
if (nOutput < 0) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout must be positive");
}
- const COutPoint outpt(uint256S(txid), nOutput);
+ const COutPoint outpt(txid, nOutput);
const auto it = pwallet->mapWallet.find(outpt.hash);
if (it == pwallet->mapWallet.end()) {
@@ -2321,7 +2314,7 @@ static UniValue listlockunspent(const JSONRPCRequest& request)
+ HelpExampleCli("listlockunspent", "") +
"\nUnlock the transaction again\n"
+ HelpExampleCli("lockunspent", "true \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
- "\nAs a json rpc call\n"
+ "\nAs a JSON-RPC call\n"
+ HelpExampleRpc("listlockunspent", "")
);
@@ -3148,6 +3141,8 @@ UniValue signrawtransactionwithwallet(const JSONRPCRequest& request)
// Sign the transaction
LOCK2(cs_main, pwallet->cs_wallet);
+ EnsureWalletIsUnlocked(pwallet);
+
return SignTransaction(mtx, request.params[1], pwallet, false, request.params[2]);
}
@@ -3208,8 +3203,7 @@ static UniValue bumpfee(const JSONRPCRequest& request)
}
RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VOBJ});
- uint256 hash;
- hash.SetHex(request.params[0].get_str());
+ uint256 hash(ParseHashV(request.params[0], "txid"));
// optional parameters
CAmount totalFee = 0;
@@ -3574,7 +3568,7 @@ UniValue getaddressinfo(const JSONRPCRequest& request)
"\nResult:\n"
"{\n"
" \"address\" : \"address\", (string) The bitcoin address validated\n"
- " \"scriptPubKey\" : \"hex\", (string) The hex encoded scriptPubKey generated by the address\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"
" \"isscript\" : true|false, (boolean) If the key is a script\n"
@@ -3743,7 +3737,7 @@ static UniValue listlabels(const JSONRPCRequest& request)
+ HelpExampleCli("listlabels", "receive") +
"\nList labels that have sending addresses\n"
+ HelpExampleCli("listlabels", "send") +
- "\nAs json rpc call\n"
+ "\nAs a JSON-RPC call\n"
+ HelpExampleRpc("listlabels", "receive")
);
@@ -3997,7 +3991,7 @@ UniValue walletcreatefundedpsbt(const JSONRPCRequest& request)
" \"address\": x.xxx, (obj, optional) A key-value pair. The key (string) is the bitcoin address, the value (float or string) is the amount in " + CURRENCY_UNIT + "\n"
" },\n"
" {\n"
- " \"data\": \"hex\" (obj, optional) A key-value pair. The key must be \"data\", the value is hex encoded data\n"
+ " \"data\": \"hex\" (obj, optional) A key-value pair. The key must be \"data\", the value is hex-encoded data\n"
" }\n"
" ,... More key-value pairs of the above form. For compatibility reasons, a dictionary, which holds the key-value pairs directly, is also\n"
" accepted as second parameter.\n"
diff --git a/src/wallet/test/init_test_fixture.cpp b/src/wallet/test/init_test_fixture.cpp
new file mode 100644
index 0000000000..1453029c9c
--- /dev/null
+++ b/src/wallet/test/init_test_fixture.cpp
@@ -0,0 +1,42 @@
+// Copyright (c) 2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <fs.h>
+
+#include <wallet/test/init_test_fixture.h>
+
+InitWalletDirTestingSetup::InitWalletDirTestingSetup(const std::string& chainName): BasicTestingSetup(chainName)
+{
+ std::string sep;
+ sep += fs::path::preferred_separator;
+
+ m_datadir = SetDataDir("tempdir");
+ m_cwd = fs::current_path();
+
+ m_walletdir_path_cases["default"] = m_datadir / "wallets";
+ m_walletdir_path_cases["custom"] = m_datadir / "my_wallets";
+ m_walletdir_path_cases["nonexistent"] = m_datadir / "path_does_not_exist";
+ m_walletdir_path_cases["file"] = m_datadir / "not_a_directory.dat";
+ m_walletdir_path_cases["trailing"] = m_datadir / "wallets" / sep;
+ m_walletdir_path_cases["trailing2"] = m_datadir / "wallets" / sep / sep;
+
+ fs::current_path(m_datadir);
+ m_walletdir_path_cases["relative"] = "wallets";
+
+ fs::create_directories(m_walletdir_path_cases["default"]);
+ fs::create_directories(m_walletdir_path_cases["custom"]);
+ fs::create_directories(m_walletdir_path_cases["relative"]);
+ std::ofstream f(m_walletdir_path_cases["file"].BOOST_FILESYSTEM_C_STR);
+ f.close();
+}
+
+InitWalletDirTestingSetup::~InitWalletDirTestingSetup()
+{
+ fs::current_path(m_cwd);
+}
+
+void InitWalletDirTestingSetup::SetWalletDir(const fs::path& walletdir_path)
+{
+ gArgs.ForceSetArg("-walletdir", walletdir_path.string());
+} \ No newline at end of file
diff --git a/src/wallet/test/init_test_fixture.h b/src/wallet/test/init_test_fixture.h
new file mode 100644
index 0000000000..5684adbece
--- /dev/null
+++ b/src/wallet/test/init_test_fixture.h
@@ -0,0 +1,21 @@
+// Copyright (c) 2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_WALLET_TEST_INIT_TEST_FIXTURE_H
+#define BITCOIN_WALLET_TEST_INIT_TEST_FIXTURE_H
+
+#include <test/test_bitcoin.h>
+
+
+struct InitWalletDirTestingSetup: public BasicTestingSetup {
+ explicit InitWalletDirTestingSetup(const std::string& chainName = CBaseChainParams::MAIN);
+ ~InitWalletDirTestingSetup();
+ void SetWalletDir(const fs::path& walletdir_path);
+
+ fs::path m_datadir;
+ fs::path m_cwd;
+ std::map<std::string, fs::path> m_walletdir_path_cases;
+};
+
+#endif // BITCOIN_WALLET_TEST_INIT_TEST_FIXTURE_H
diff --git a/src/wallet/test/init_tests.cpp b/src/wallet/test/init_tests.cpp
new file mode 100644
index 0000000000..7048547b2b
--- /dev/null
+++ b/src/wallet/test/init_tests.cpp
@@ -0,0 +1,78 @@
+// Copyright (c) 2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <boost/test/unit_test.hpp>
+
+#include <test/test_bitcoin.h>
+#include <wallet/test/init_test_fixture.h>
+
+#include <init.h>
+#include <walletinitinterface.h>
+#include <wallet/wallet.h>
+
+
+BOOST_FIXTURE_TEST_SUITE(init_tests, InitWalletDirTestingSetup)
+
+BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_default)
+{
+ SetWalletDir(m_walletdir_path_cases["default"]);
+ bool result = g_wallet_init_interface.Verify();
+ BOOST_CHECK(result == true);
+ fs::path walletdir = gArgs.GetArg("-walletdir", "");
+ fs::path expected_path = fs::canonical(m_walletdir_path_cases["default"]);
+ BOOST_CHECK(walletdir == expected_path);
+}
+
+BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_custom)
+{
+ SetWalletDir(m_walletdir_path_cases["custom"]);
+ bool result = g_wallet_init_interface.Verify();
+ BOOST_CHECK(result == true);
+ fs::path walletdir = gArgs.GetArg("-walletdir", "");
+ fs::path expected_path = fs::canonical(m_walletdir_path_cases["custom"]);
+ BOOST_CHECK(walletdir == expected_path);
+}
+
+BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_does_not_exist)
+{
+ SetWalletDir(m_walletdir_path_cases["nonexistent"]);
+ bool result = g_wallet_init_interface.Verify();
+ BOOST_CHECK(result == false);
+}
+
+BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_is_not_directory)
+{
+ SetWalletDir(m_walletdir_path_cases["file"]);
+ bool result = g_wallet_init_interface.Verify();
+ BOOST_CHECK(result == false);
+}
+
+BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_is_not_relative)
+{
+ SetWalletDir(m_walletdir_path_cases["relative"]);
+ bool result = g_wallet_init_interface.Verify();
+ BOOST_CHECK(result == false);
+}
+
+BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_no_trailing)
+{
+ SetWalletDir(m_walletdir_path_cases["trailing"]);
+ bool result = g_wallet_init_interface.Verify();
+ BOOST_CHECK(result == true);
+ fs::path walletdir = gArgs.GetArg("-walletdir", "");
+ fs::path expected_path = fs::canonical(m_walletdir_path_cases["default"]);
+ BOOST_CHECK(walletdir == expected_path);
+}
+
+BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_no_trailing2)
+{
+ SetWalletDir(m_walletdir_path_cases["trailing2"]);
+ bool result = g_wallet_init_interface.Verify();
+ BOOST_CHECK(result == true);
+ fs::path walletdir = gArgs.GetArg("-walletdir", "");
+ fs::path expected_path = fs::canonical(m_walletdir_path_cases["default"]);
+ BOOST_CHECK(walletdir == expected_path);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 7f7a88e986..afe47d986e 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -2743,6 +2743,8 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CTransac
return false;
}
}
+ } else {
+ bnb_used = false;
}
const CAmount nChange = nValueIn - nValueToSelect;
@@ -3987,10 +3989,6 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(const std::string& name,
if (fFirstRun)
{
// ensure this wallet.dat can only be opened by clients supporting HD with chain split and expects no default key
- if (!gArgs.GetBoolArg("-usehd", true)) {
- InitError(strprintf(_("Error creating %s: You can't create non-HD wallets with this version."), walletFile));
- return nullptr;
- }
walletInstance->SetMinVersion(FEATURE_LATEST);
if ((wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
@@ -4018,16 +4016,6 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(const std::string& name,
if (!walletInstance->mapKeys.empty() || !walletInstance->mapCryptedKeys.empty()) {
InitWarning(strprintf(_("Warning: Private keys detected in wallet {%s} with disabled private keys"), walletFile));
}
- } else if (gArgs.IsArgSet("-usehd")) {
- bool useHD = gArgs.GetBoolArg("-usehd", true);
- if (walletInstance->IsHDEnabled() && !useHD) {
- InitError(strprintf(_("Error loading %s: You can't disable HD on an already existing HD wallet"), walletFile));
- return nullptr;
- }
- if (!walletInstance->IsHDEnabled() && useHD) {
- InitError(strprintf(_("Error loading %s: You can't enable HD on an already existing non-HD wallet"), walletFile));
- return nullptr;
- }
}
if (!gArgs.GetArg("-addresstype", "").empty() && !ParseOutputType(gArgs.GetArg("-addresstype", ""), walletInstance->m_default_address_type)) {
diff --git a/test/config.ini.in b/test/config.ini.in
index a1119dc739..28abee2a3d 100644
--- a/test/config.ini.in
+++ b/test/config.ini.in
@@ -14,6 +14,6 @@ RPCAUTH=@abs_top_srcdir@/share/rpcauth/rpcauth.py
[components]
# Which components are enabled. These are commented out by `configure` if they were disabled when running config.
@ENABLE_WALLET_TRUE@ENABLE_WALLET=true
-@BUILD_BITCOIN_UTILS_TRUE@ENABLE_UTILS=true
+@BUILD_BITCOIN_CLI_TRUE@ENABLE_CLI=true
@BUILD_BITCOIND_TRUE@ENABLE_BITCOIND=true
@ENABLE_ZMQ_TRUE@ENABLE_ZMQ=true
diff --git a/test/functional/README.md b/test/functional/README.md
index 6929ab5991..d40052ac93 100644
--- a/test/functional/README.md
+++ b/test/functional/README.md
@@ -60,6 +60,11 @@ don't have test cases for.
- When calling RPCs with lots of arguments, consider using named keyword
arguments instead of positional arguments to make the intent of the call
clear to readers.
+- Many of the core test framework classes such as `CBlock` and `CTransaction`
+ don't allow new attributes to be added to their objects at runtime like
+ typical Python objects allow. This helps prevent unpredictable side effects
+ from typographical errors or usage of the objects outside of their intended
+ purpose.
#### RPC and P2P definitions
@@ -72,7 +77,7 @@ P2P messages. These can be found in the following source files:
#### Using the P2P interface
-- `mininode.py` contains all the definitions for objects that pass
+- `messages.py` contains all the definitions for objects that pass
over the network (`CBlock`, `CTransaction`, etc, along with the network-level
wrappers for them, `msg_block`, `msg_tx`, etc).
diff --git a/test/functional/combine_logs.py b/test/functional/combine_logs.py
index 3759913e44..3230d5cb6b 100755
--- a/test/functional/combine_logs.py
+++ b/test/functional/combine_logs.py
@@ -25,10 +25,6 @@ def main():
parser.add_argument('--html', dest='html', action='store_true', help='outputs the combined log as html. Requires jinja2. pip install jinja2')
args, unknown_args = parser.parse_known_args()
- if args.color and os.name != 'posix':
- print("Color output requires posix terminal colors.")
- sys.exit(1)
-
if args.html and args.color:
print("Only one out of --color or --html should be specified")
sys.exit(1)
diff --git a/test/functional/feature_block.py b/test/functional/feature_block.py
index 71c3a396c1..628cefb76d 100755
--- a/test/functional/feature_block.py
+++ b/test/functional/feature_block.py
@@ -824,7 +824,7 @@ class FullBlockTest(BitcoinTestFramework):
tx.vin.append(CTxIn(COutPoint(b64a.vtx[1].sha256, 0)))
b64a = self.update_block("64a", [tx])
assert_equal(len(b64a.serialize()), MAX_BLOCK_BASE_SIZE + 8)
- self.sync_blocks([b64a], success=False, reject_reason='non-canonical ReadCompactSize(): iostream error')
+ self.sync_blocks([b64a], success=False, reject_reason='non-canonical ReadCompactSize():')
# bitcoind doesn't disconnect us for sending a bloated block, but if we subsequently
# resend the header message, it won't send us the getdata message again. Just
diff --git a/test/functional/feature_config_args.py b/test/functional/feature_config_args.py
index 1124119e2b..492772d5e3 100755
--- a/test/functional/feature_config_args.py
+++ b/test/functional/feature_config_args.py
@@ -14,9 +14,6 @@ class ConfArgsTest(BitcoinTestFramework):
self.setup_clean_chain = True
self.num_nodes = 1
- def skip_test_if_missing_module(self):
- self.skip_if_no_wallet()
-
def test_config_file_parser(self):
# Assume node is stopped
@@ -68,13 +65,18 @@ class ConfArgsTest(BitcoinTestFramework):
# Temporarily disabled, because this test would access the user's home dir (~/.bitcoin)
#self.start_node(0, ['-conf='+conf_file, '-wallet=w1'])
#self.stop_node(0)
+ #assert os.path.exists(os.path.join(new_data_dir, 'regtest', 'blocks'))
+ #if self.is_wallet_compiled():
#assert os.path.exists(os.path.join(new_data_dir, 'regtest', 'wallets', 'w1'))
# Ensure command line argument overrides datadir in conf
os.mkdir(new_data_dir_2)
self.nodes[0].datadir = new_data_dir_2
self.start_node(0, ['-datadir='+new_data_dir_2, '-conf='+conf_file, '-wallet=w2'])
- assert os.path.exists(os.path.join(new_data_dir_2, 'regtest', 'wallets', 'w2'))
+ assert os.path.exists(os.path.join(new_data_dir_2, 'regtest', 'blocks'))
+ if self.is_wallet_compiled():
+ assert os.path.exists(os.path.join(new_data_dir_2, 'regtest', 'wallets', 'w2'))
+
if __name__ == '__main__':
ConfArgsTest().main()
diff --git a/test/functional/feature_notifications.py b/test/functional/feature_notifications.py
index 25a7329a0d..90dc4c8e2b 100755
--- a/test/functional/feature_notifications.py
+++ b/test/functional/feature_notifications.py
@@ -5,85 +5,83 @@
"""Test the -alertnotify, -blocknotify and -walletnotify options."""
import os
+from test_framework.address import ADDRESS_BCRT1_UNSPENDABLE
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal, wait_until, connect_nodes_bi
+
class NotificationsTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 2
self.setup_clean_chain = True
- def skip_test_if_missing_module(self):
- self.skip_if_no_wallet()
-
def setup_network(self):
- self.alert_filename = os.path.join(self.options.tmpdir, "alert.txt")
- self.block_filename = os.path.join(self.options.tmpdir, "blocks.txt")
- self.tx_filename = os.path.join(self.options.tmpdir, "transactions.txt")
+ self.alertnotify_dir = os.path.join(self.options.tmpdir, "alertnotify")
+ self.blocknotify_dir = os.path.join(self.options.tmpdir, "blocknotify")
+ self.walletnotify_dir = os.path.join(self.options.tmpdir, "walletnotify")
+ os.mkdir(self.alertnotify_dir)
+ os.mkdir(self.blocknotify_dir)
+ os.mkdir(self.walletnotify_dir)
# -alertnotify and -blocknotify on node0, walletnotify on node1
- self.extra_args = [["-blockversion=2",
- "-alertnotify=echo %%s >> %s" % self.alert_filename,
- "-blocknotify=echo %%s >> %s" % self.block_filename],
+ self.extra_args = [[
+ "-alertnotify=echo > {}".format(os.path.join(self.alertnotify_dir, '%s')),
+ "-blocknotify=echo > {}".format(os.path.join(self.blocknotify_dir, '%s'))],
["-blockversion=211",
"-rescan",
- "-walletnotify=echo %%s >> %s" % self.tx_filename]]
+ "-walletnotify=echo > {}".format(os.path.join(self.walletnotify_dir, '%s'))]]
super().setup_network()
def run_test(self):
self.log.info("test -blocknotify")
block_count = 10
- blocks = self.nodes[1].generate(block_count)
+ blocks = self.nodes[1].generatetoaddress(block_count, self.nodes[1].getnewaddress() if self.is_wallet_compiled() else ADDRESS_BCRT1_UNSPENDABLE)
- # wait at most 10 seconds for expected file size before reading the content
- wait_until(lambda: os.path.isfile(self.block_filename) and os.stat(self.block_filename).st_size >= (block_count * 65), timeout=10)
+ # wait at most 10 seconds for expected number of files before reading the content
+ wait_until(lambda: len(os.listdir(self.blocknotify_dir)) == block_count, timeout=10)
- # file content should equal the generated blocks hashes
- with open(self.block_filename, 'r', encoding="utf-8") as f:
- assert_equal(sorted(blocks), sorted(l.strip() for l in f.read().splitlines()))
+ # directory content should equal the generated blocks hashes
+ assert_equal(sorted(blocks), sorted(os.listdir(self.blocknotify_dir)))
- self.log.info("test -walletnotify")
- # wait at most 10 seconds for expected file size before reading the content
- wait_until(lambda: os.path.isfile(self.tx_filename) and os.stat(self.tx_filename).st_size >= (block_count * 65), timeout=10)
+ if self.is_wallet_compiled():
+ self.log.info("test -walletnotify")
+ # wait at most 10 seconds for expected number of files before reading the content
+ wait_until(lambda: len(os.listdir(self.walletnotify_dir)) == block_count, timeout=10)
- # file content should equal the generated transaction hashes
- txids_rpc = list(map(lambda t: t['txid'], self.nodes[1].listtransactions("*", block_count)))
- with open(self.tx_filename, 'r', encoding="ascii") as f:
- assert_equal(sorted(txids_rpc), sorted(l.strip() for l in f.read().splitlines()))
- os.remove(self.tx_filename)
+ # directory content should equal the generated transaction hashes
+ txids_rpc = list(map(lambda t: t['txid'], self.nodes[1].listtransactions("*", block_count)))
+ assert_equal(sorted(txids_rpc), sorted(os.listdir(self.walletnotify_dir)))
+ for tx_file in os.listdir(self.walletnotify_dir):
+ os.remove(os.path.join(self.walletnotify_dir, tx_file))
- self.log.info("test -walletnotify after rescan")
- # restart node to rescan to force wallet notifications
- self.restart_node(1)
- connect_nodes_bi(self.nodes, 0, 1)
+ self.log.info("test -walletnotify after rescan")
+ # restart node to rescan to force wallet notifications
+ self.restart_node(1)
+ connect_nodes_bi(self.nodes, 0, 1)
- wait_until(lambda: os.path.isfile(self.tx_filename) and os.stat(self.tx_filename).st_size >= (block_count * 65), timeout=10)
+ wait_until(lambda: len(os.listdir(self.walletnotify_dir)) == block_count, timeout=10)
- # file content should equal the generated transaction hashes
- txids_rpc = list(map(lambda t: t['txid'], self.nodes[1].listtransactions("*", block_count)))
- with open(self.tx_filename, 'r', encoding="ascii") as f:
- assert_equal(sorted(txids_rpc), sorted(l.strip() for l in f.read().splitlines()))
+ # directory content should equal the generated transaction hashes
+ txids_rpc = list(map(lambda t: t['txid'], self.nodes[1].listtransactions("*", block_count)))
+ assert_equal(sorted(txids_rpc), sorted(os.listdir(self.walletnotify_dir)))
# Mine another 41 up-version blocks. -alertnotify should trigger on the 51st.
self.log.info("test -alertnotify")
- self.nodes[1].generate(41)
+ self.nodes[1].generatetoaddress(41, ADDRESS_BCRT1_UNSPENDABLE)
self.sync_all()
# Give bitcoind 10 seconds to write the alert notification
- wait_until(lambda: os.path.isfile(self.alert_filename) and os.path.getsize(self.alert_filename), timeout=10)
+ wait_until(lambda: len(os.listdir(self.alertnotify_dir)), timeout=10)
- with open(self.alert_filename, 'r', encoding='utf8') as f:
- alert_text = f.read()
+ for notify_file in os.listdir(self.alertnotify_dir):
+ os.remove(os.path.join(self.alertnotify_dir, notify_file))
# Mine more up-version blocks, should not get more alerts:
- self.nodes[1].generate(2)
+ self.nodes[1].generatetoaddress(2, ADDRESS_BCRT1_UNSPENDABLE)
self.sync_all()
- with open(self.alert_filename, 'r', encoding='utf8') as f:
- alert_text2 = f.read()
-
self.log.info("-alertnotify should not continue notifying for more unknown version blocks")
- assert_equal(alert_text, alert_text2)
+ assert_equal(len(os.listdir(self.alertnotify_dir)), 0)
if __name__ == '__main__':
NotificationsTest().main()
diff --git a/test/functional/feature_uacomment.py b/test/functional/feature_uacomment.py
index 691a39b825..fb4ad21359 100755
--- a/test/functional/feature_uacomment.py
+++ b/test/functional/feature_uacomment.py
@@ -31,7 +31,7 @@ class UacommentTest(BitcoinTestFramework):
self.nodes[0].assert_start_raises_init_error(["-uacomment=" + 'a' * 256], expected, match=ErrorMatch.FULL_REGEX)
self.log.info("test -uacomment unsafe characters")
- for unsafe_char in ['/', ':', '(', ')']:
+ for unsafe_char in ['/', ':', '(', ')', '₿', '🏃']:
expected = "Error: User Agent comment \(" + re.escape(unsafe_char) + "\) contains unsafe characters."
self.nodes[0].assert_start_raises_init_error(["-uacomment=" + unsafe_char], expected, match=ErrorMatch.FULL_REGEX)
diff --git a/test/functional/interface_bitcoin_cli.py b/test/functional/interface_bitcoin_cli.py
index f311858bee..58cdaf861f 100755
--- a/test/functional/interface_bitcoin_cli.py
+++ b/test/functional/interface_bitcoin_cli.py
@@ -12,9 +12,6 @@ class TestBitcoinCli(BitcoinTestFramework):
self.setup_clean_chain = True
self.num_nodes = 1
- def skip_test_if_missing_module(self):
- self.skip_if_no_wallet()
-
def run_test(self):
"""Main test logic"""
@@ -22,9 +19,10 @@ class TestBitcoinCli(BitcoinTestFramework):
assert("Bitcoin Core RPC client version" in cli_response)
self.log.info("Compare responses from gewalletinfo RPC and `bitcoin-cli getwalletinfo`")
- cli_response = self.nodes[0].cli.getwalletinfo()
- rpc_response = self.nodes[0].getwalletinfo()
- assert_equal(cli_response, rpc_response)
+ if self.is_wallet_compiled():
+ cli_response = self.nodes[0].cli.getwalletinfo()
+ rpc_response = self.nodes[0].getwalletinfo()
+ assert_equal(cli_response, rpc_response)
self.log.info("Compare responses from getblockchaininfo RPC and `bitcoin-cli getblockchaininfo`")
cli_response = self.nodes[0].cli.getblockchaininfo()
@@ -52,26 +50,30 @@ class TestBitcoinCli(BitcoinTestFramework):
self.log.info("Compare responses from `bitcoin-cli -getinfo` and the RPCs data is retrieved from.")
cli_get_info = self.nodes[0].cli('-getinfo').send_cli()
- wallet_info = self.nodes[0].getwalletinfo()
+ if self.is_wallet_compiled():
+ wallet_info = self.nodes[0].getwalletinfo()
network_info = self.nodes[0].getnetworkinfo()
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['walletversion'], wallet_info['walletversion'])
- assert_equal(cli_get_info['balance'], wallet_info['balance'])
+ 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['blocks'], blockchain_info['blocks'])
assert_equal(cli_get_info['timeoffset'], network_info['timeoffset'])
assert_equal(cli_get_info['connections'], network_info['connections'])
assert_equal(cli_get_info['proxy'], network_info['networks'][0]['proxy'])
assert_equal(cli_get_info['difficulty'], blockchain_info['difficulty'])
assert_equal(cli_get_info['testnet'], blockchain_info['chain'] == "test")
- 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'])
- # unlocked_until is not tested because the wallet is not encrypted
+ if self.is_wallet_compiled():
+ 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'])
+ # unlocked_until is not tested because the wallet is not encrypted
+
if __name__ == '__main__':
TestBitcoinCli().main()
diff --git a/test/functional/interface_zmq.py b/test/functional/interface_zmq.py
index 1c518eab75..48136a0108 100755
--- a/test/functional/interface_zmq.py
+++ b/test/functional/interface_zmq.py
@@ -5,6 +5,7 @@
"""Test the ZMQ notification interface."""
import struct
+from test_framework.address import ADDRESS_BCRT1_UNSPENDABLE
from test_framework.test_framework import BitcoinTestFramework
from test_framework.messages import CTransaction
from test_framework.util import (
@@ -14,6 +15,7 @@ from test_framework.util import (
)
from io import BytesIO
+ADDRESS = "tcp://127.0.0.1:28332"
class ZMQSubscriber:
def __init__(self, socket, topic):
@@ -41,7 +43,6 @@ class ZMQTest (BitcoinTestFramework):
def skip_test_if_missing_module(self):
self.skip_if_no_py3_zmq()
self.skip_if_no_bitcoind_zmq()
- self.skip_if_no_wallet()
def setup_nodes(self):
import zmq
@@ -51,11 +52,10 @@ class ZMQTest (BitcoinTestFramework):
# that this test fails if the publishing order changes.
# Note that the publishing order is not defined in the documentation and
# is subject to change.
- address = "tcp://127.0.0.1:28332"
self.zmq_context = zmq.Context()
socket = self.zmq_context.socket(zmq.SUB)
socket.set(zmq.RCVTIMEO, 60000)
- socket.connect(address)
+ socket.connect(ADDRESS)
# Subscribe to all available topics.
self.hashblock = ZMQSubscriber(socket, b"hashblock")
@@ -64,7 +64,7 @@ class ZMQTest (BitcoinTestFramework):
self.rawtx = ZMQSubscriber(socket, b"rawtx")
self.extra_args = [
- ["-zmqpub%s=%s" % (sub.topic.decode(), address) for sub in [self.hashblock, self.hashtx, self.rawblock, self.rawtx]],
+ ["-zmqpub%s=%s" % (sub.topic.decode(), ADDRESS) for sub in [self.hashblock, self.hashtx, self.rawblock, self.rawtx]],
[],
]
self.add_nodes(self.num_nodes, self.extra_args)
@@ -81,7 +81,7 @@ class ZMQTest (BitcoinTestFramework):
def _zmq_test(self):
num_blocks = 5
self.log.info("Generate %(n)d blocks (and %(n)d coinbase txes)" % {"n": num_blocks})
- genhashes = self.nodes[0].generate(num_blocks)
+ genhashes = self.nodes[0].generatetoaddress(num_blocks, ADDRESS_BCRT1_UNSPENDABLE)
self.sync_all()
for x in range(num_blocks):
@@ -105,17 +105,29 @@ class ZMQTest (BitcoinTestFramework):
block = self.rawblock.receive()
assert_equal(genhashes[x], bytes_to_hex_str(hash256(block[:80])))
- self.log.info("Wait for tx from second node")
- payment_txid = self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), 1.0)
- self.sync_all()
+ if self.is_wallet_compiled():
+ self.log.info("Wait for tx from second node")
+ payment_txid = self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), 1.0)
+ self.sync_all()
+
+ # Should receive the broadcasted txid.
+ txid = self.hashtx.receive()
+ assert_equal(payment_txid, bytes_to_hex_str(txid))
+
+ # Should receive the broadcasted raw transaction.
+ hex = self.rawtx.receive()
+ assert_equal(payment_txid, bytes_to_hex_str(hash256(hex)))
+
- # Should receive the broadcasted txid.
- txid = self.hashtx.receive()
- assert_equal(payment_txid, bytes_to_hex_str(txid))
+ self.log.info("Test the getzmqnotifications RPC")
+ assert_equal(self.nodes[0].getzmqnotifications(), [
+ {"type": "pubhashblock", "address": ADDRESS},
+ {"type": "pubhashtx", "address": ADDRESS},
+ {"type": "pubrawblock", "address": ADDRESS},
+ {"type": "pubrawtx", "address": ADDRESS},
+ ])
- # Should receive the broadcasted raw transaction.
- hex = self.rawtx.receive()
- assert_equal(payment_txid, bytes_to_hex_str(hash256(hex)))
+ assert_equal(self.nodes[1].getzmqnotifications(), [])
if __name__ == '__main__':
ZMQTest().main()
diff --git a/test/functional/mining_prioritisetransaction.py b/test/functional/mining_prioritisetransaction.py
index 92590717f3..c5ddee56f1 100755
--- a/test/functional/mining_prioritisetransaction.py
+++ b/test/functional/mining_prioritisetransaction.py
@@ -29,7 +29,8 @@ class PrioritiseTransactionTest(BitcoinTestFramework):
assert_raises_rpc_error(-1, "prioritisetransaction", self.nodes[0].prioritisetransaction, '', 0, 0, 0)
# Test `prioritisetransaction` invalid `txid`
- assert_raises_rpc_error(-1, "txid must be hexadecimal string", self.nodes[0].prioritisetransaction, txid='foo', fee_delta=0)
+ assert_raises_rpc_error(-8, "txid must be of length 64 (not 3, for 'foo')", self.nodes[0].prioritisetransaction, txid='foo', fee_delta=0)
+ assert_raises_rpc_error(-8, "txid must be hexadecimal string (not 'Zd1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000')", self.nodes[0].prioritisetransaction, txid='Zd1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000', fee_delta=0)
# Test `prioritisetransaction` invalid `dummy`
txid = '1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000'
diff --git a/test/functional/p2p_compactblocks.py b/test/functional/p2p_compactblocks.py
index 3a5bdf806b..fafc27d16a 100755
--- a/test/functional/p2p_compactblocks.py
+++ b/test/functional/p2p_compactblocks.py
@@ -293,7 +293,7 @@ class CompactBlocksTest(BitcoinTestFramework):
block_hash = int(node.generate(1)[0], 16)
# Store the raw block in our internal format.
- block = FromHex(CBlock(), node.getblock("%02x" % block_hash, False))
+ block = FromHex(CBlock(), node.getblock("%064x" % block_hash, False))
for tx in block.vtx:
tx.calc_sha256()
block.rehash()
diff --git a/test/functional/p2p_segwit.py b/test/functional/p2p_segwit.py
index de12ab1ed6..afbbfa8992 100755
--- a/test/functional/p2p_segwit.py
+++ b/test/functional/p2p_segwit.py
@@ -205,7 +205,7 @@ class SegWitTest(BitcoinTestFramework):
height = self.nodes[0].getblockcount() + 1
block_time = self.nodes[0].getblockheader(tip)["mediantime"] + 1
block = create_block(int(tip, 16), create_coinbase(height), block_time)
- block.version = version
+ block.nVersion = version
block.rehash()
return block
@@ -769,12 +769,16 @@ class SegWitTest(BitcoinTestFramework):
# will require a witness to spend a witness program regardless of
# segwit activation. Note that older bitcoind's that are not
# segwit-aware would also reject this for failing CLEANSTACK.
- test_transaction_acceptance(self.nodes[0], self.test_node, spend_tx, with_witness=False, accepted=False)
+ with self.nodes[0].assert_debug_log(
+ expected_msgs=(spend_tx.hash, 'was not accepted: non-mandatory-script-verify-flag (Witness program was passed an empty witness)')):
+ test_transaction_acceptance(self.nodes[0], self.test_node, spend_tx, with_witness=False, accepted=False)
- # Try to put the witness script in the script_sig, should also fail.
- spend_tx.vin[0].script_sig = CScript([p2wsh_pubkey, b'a'])
+ # Try to put the witness script in the scriptSig, should also fail.
+ spend_tx.vin[0].scriptSig = CScript([p2wsh_pubkey, b'a'])
spend_tx.rehash()
- test_transaction_acceptance(self.nodes[0], self.test_node, spend_tx, with_witness=False, accepted=False)
+ with self.nodes[0].assert_debug_log(
+ expected_msgs=('Not relaying invalid transaction {}'.format(spend_tx.hash), 'was not accepted: mandatory-script-verify-flag-failed (Script evaluated without error but finished with a false/empty top stack element)')):
+ test_transaction_acceptance(self.nodes[0], self.test_node, spend_tx, with_witness=False, accepted=False)
# Now put the witness script in the witness, should succeed after
# segwit activates.
diff --git a/test/functional/p2p_sendheaders.py b/test/functional/p2p_sendheaders.py
index d5e8dd4721..c7ae57de86 100755
--- a/test/functional/p2p_sendheaders.py
+++ b/test/functional/p2p_sendheaders.py
@@ -402,7 +402,7 @@ class SendHeadersTest(BitcoinTestFramework):
block_time += 9
- fork_point = self.nodes[0].getblock("%02x" % new_block_hashes[0])["previousblockhash"]
+ fork_point = self.nodes[0].getblock("%064x" % new_block_hashes[0])["previousblockhash"]
fork_point = int(fork_point, 16)
# Use getblocks/getdata
diff --git a/test/functional/rpc_blockchain.py b/test/functional/rpc_blockchain.py
index f67ecc247c..92b690176d 100755
--- a/test/functional/rpc_blockchain.py
+++ b/test/functional/rpc_blockchain.py
@@ -125,7 +125,9 @@ class BlockchainTest(BitcoinTestFramework):
# Test `getchaintxstats` invalid `blockhash`
assert_raises_rpc_error(-1, "JSON value is not a string as expected", self.nodes[0].getchaintxstats, blockhash=0)
- assert_raises_rpc_error(-5, "Block not found", self.nodes[0].getchaintxstats, blockhash='0')
+ assert_raises_rpc_error(-8, "blockhash must be of length 64 (not 1, for '0')", self.nodes[0].getchaintxstats, blockhash='0')
+ assert_raises_rpc_error(-8, "blockhash must be hexadecimal string (not 'ZZZ0000000000000000000000000000000000000000000000000000000000000')", self.nodes[0].getchaintxstats, blockhash='ZZZ0000000000000000000000000000000000000000000000000000000000000')
+ assert_raises_rpc_error(-5, "Block not found", self.nodes[0].getchaintxstats, blockhash='0000000000000000000000000000000000000000000000000000000000000000')
blockhash = self.nodes[0].getblockhash(200)
self.nodes[0].invalidateblock(blockhash)
assert_raises_rpc_error(-8, "Block is not in main chain", self.nodes[0].getchaintxstats, blockhash=blockhash)
@@ -203,7 +205,9 @@ class BlockchainTest(BitcoinTestFramework):
def _test_getblockheader(self):
node = self.nodes[0]
- assert_raises_rpc_error(-5, "Block not found", node.getblockheader, "nonsense")
+ assert_raises_rpc_error(-8, "hash must be of length 64 (not 8, for 'nonsense')", node.getblockheader, "nonsense")
+ assert_raises_rpc_error(-8, "hash must be hexadecimal string (not 'ZZZ7bb8b1697ea987f3b223ba7819250cae33efacb068d23dc24859824a77844')", node.getblockheader, "ZZZ7bb8b1697ea987f3b223ba7819250cae33efacb068d23dc24859824a77844")
+ assert_raises_rpc_error(-5, "Block not found", node.getblockheader, "0cf7bb8b1697ea987f3b223ba7819250cae33efacb068d23dc24859824a77844")
besthash = node.getbestblockhash()
secondbesthash = node.getblockhash(199)
diff --git a/test/functional/rpc_rawtransaction.py b/test/functional/rpc_rawtransaction.py
index d86b546c7d..8ed490f552 100755
--- a/test/functional/rpc_rawtransaction.py
+++ b/test/functional/rpc_rawtransaction.py
@@ -80,8 +80,9 @@ class RawTransactionsTest(BitcoinTestFramework):
txid = '1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000'
assert_raises_rpc_error(-3, "Expected type array", self.nodes[0].createrawtransaction, 'foo', {})
assert_raises_rpc_error(-1, "JSON value is not an object as expected", self.nodes[0].createrawtransaction, ['foo'], {})
- assert_raises_rpc_error(-8, "txid must be hexadecimal string", self.nodes[0].createrawtransaction, [{}], {})
- assert_raises_rpc_error(-8, "txid must be hexadecimal string", self.nodes[0].createrawtransaction, [{'txid': 'foo'}], {})
+ assert_raises_rpc_error(-1, "JSON value is not a string as expected", self.nodes[0].createrawtransaction, [{}], {})
+ assert_raises_rpc_error(-8, "txid must be of length 64 (not 3, for 'foo')", self.nodes[0].createrawtransaction, [{'txid': 'foo'}], {})
+ assert_raises_rpc_error(-8, "txid must be hexadecimal string (not 'ZZZ7bb8b1697ea987f3b223ba7819250cae33efacb068d23dc24859824a77844')", self.nodes[0].createrawtransaction, [{'txid': 'ZZZ7bb8b1697ea987f3b223ba7819250cae33efacb068d23dc24859824a77844'}], {})
assert_raises_rpc_error(-8, "Invalid parameter, missing vout key", self.nodes[0].createrawtransaction, [{'txid': txid}], {})
assert_raises_rpc_error(-8, "Invalid parameter, missing vout key", self.nodes[0].createrawtransaction, [{'txid': txid, 'vout': 'foo'}], {})
assert_raises_rpc_error(-8, "Invalid parameter, vout must be positive", self.nodes[0].createrawtransaction, [{'txid': txid, 'vout': -1}], {})
@@ -224,9 +225,10 @@ class RawTransactionsTest(BitcoinTestFramework):
# We should not get the tx if we provide an unrelated block
assert_raises_rpc_error(-5, "No such transaction found", self.nodes[0].getrawtransaction, tx, True, block2)
# An invalid block hash should raise the correct errors
- assert_raises_rpc_error(-8, "parameter 3 must be hexadecimal", self.nodes[0].getrawtransaction, tx, True, True)
- assert_raises_rpc_error(-8, "parameter 3 must be hexadecimal", self.nodes[0].getrawtransaction, tx, True, "foobar")
- assert_raises_rpc_error(-8, "parameter 3 must be of length 64", self.nodes[0].getrawtransaction, tx, True, "abcd1234")
+ assert_raises_rpc_error(-1, "JSON value is not a string as expected", self.nodes[0].getrawtransaction, tx, True, True)
+ assert_raises_rpc_error(-8, "parameter 3 must be of length 64 (not 6, for 'foobar')", self.nodes[0].getrawtransaction, tx, True, "foobar")
+ assert_raises_rpc_error(-8, "parameter 3 must be of length 64 (not 8, for 'abcd1234')", self.nodes[0].getrawtransaction, tx, True, "abcd1234")
+ assert_raises_rpc_error(-8, "parameter 3 must be hexadecimal string (not 'ZZZ0000000000000000000000000000000000000000000000000000000000000')", self.nodes[0].getrawtransaction, tx, True, "ZZZ0000000000000000000000000000000000000000000000000000000000000")
assert_raises_rpc_error(-5, "Block hash not found", self.nodes[0].getrawtransaction, tx, True, "0000000000000000000000000000000000000000000000000000000000000000")
# Undo the blocks and check in_active_chain
self.nodes[0].invalidateblock(block1)
diff --git a/test/functional/rpc_signrawtransaction.py b/test/functional/rpc_signrawtransaction.py
index 5c07f2ccae..291538df64 100755
--- a/test/functional/rpc_signrawtransaction.py
+++ b/test/functional/rpc_signrawtransaction.py
@@ -45,6 +45,14 @@ class SignRawTransactionsTest(BitcoinTestFramework):
# 2) No script verification error occurred
assert 'errors' not in rawTxSigned
+ def test_with_lock_outputs(self):
+ """Test correct error reporting when trying to sign a locked output"""
+ self.nodes[0].encryptwallet("password")
+
+ rawTx = '020000000156b958f78e3f24e0b2f4e4db1255426b0902027cb37e3ddadb52e37c3557dddb0000000000ffffffff01c0a6b929010000001600149a2ee8c77140a053f36018ac8124a6ececc1668a00000000'
+
+ assert_raises_rpc_error(-13, "Please enter the wallet passphrase with walletpassphrase first", self.nodes[0].signrawtransactionwithwallet, rawTx)
+
def script_verification_error_test(self):
"""Create and sign a raw transaction with valid (vin 0), invalid (vin 1) and one missing (vin 2) input script.
@@ -138,6 +146,7 @@ class SignRawTransactionsTest(BitcoinTestFramework):
def run_test(self):
self.successful_signing_test()
self.script_verification_error_test()
+ self.test_with_lock_outputs()
if __name__ == '__main__':
diff --git a/test/functional/rpc_txoutproof.py b/test/functional/rpc_txoutproof.py
index 867ba25022..8913b8698d 100755
--- a/test/functional/rpc_txoutproof.py
+++ b/test/functional/rpc_txoutproof.py
@@ -66,12 +66,18 @@ class MerkleBlockTest(BitcoinTestFramework):
txid_spent = txin_spent["txid"]
txid_unspent = txid1 if txin_spent["txid"] != txid1 else txid2
+ # Invalid txids
+ assert_raises_rpc_error(-8, "txid must be of length 64 (not 32, for '00000000000000000000000000000000')", self.nodes[2].gettxoutproof, ["00000000000000000000000000000000"], blockhash)
+ assert_raises_rpc_error(-8, "txid must be hexadecimal string (not 'ZZZ0000000000000000000000000000000000000000000000000000000000000')", self.nodes[2].gettxoutproof, ["ZZZ0000000000000000000000000000000000000000000000000000000000000"], blockhash)
+ # Invalid blockhashes
+ assert_raises_rpc_error(-8, "blockhash must be of length 64 (not 32, for '00000000000000000000000000000000')", self.nodes[2].gettxoutproof, [txid_spent], "00000000000000000000000000000000")
+ assert_raises_rpc_error(-8, "blockhash must be hexadecimal string (not 'ZZZ0000000000000000000000000000000000000000000000000000000000000')", self.nodes[2].gettxoutproof, [txid_spent], "ZZZ0000000000000000000000000000000000000000000000000000000000000")
# We can't find the block from a fully-spent tx
assert_raises_rpc_error(-5, "Transaction not yet in block", self.nodes[2].gettxoutproof, [txid_spent])
# We can get the proof if we specify the block
assert_equal(self.nodes[2].verifytxoutproof(self.nodes[2].gettxoutproof([txid_spent], blockhash)), [txid_spent])
# We can't get the proof if we specify a non-existent block
- assert_raises_rpc_error(-5, "Block not found", self.nodes[2].gettxoutproof, [txid_spent], "00000000000000000000000000000000")
+ assert_raises_rpc_error(-5, "Block not found", self.nodes[2].gettxoutproof, [txid_spent], "0000000000000000000000000000000000000000000000000000000000000000")
# We can get the proof if the transaction is unspent
assert_equal(self.nodes[2].verifytxoutproof(self.nodes[2].gettxoutproof([txid_unspent])), [txid_unspent])
# We can get the proof if we provide a list of transactions and one of them is unspent. The ordering of the list should not matter.
diff --git a/test/functional/rpc_zmq.py b/test/functional/rpc_zmq.py
deleted file mode 100755
index bfa6b06f67..0000000000
--- a/test/functional/rpc_zmq.py
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (c) 2018 The Bitcoin Core developers
-# Distributed under the MIT software license, see the accompanying
-# file COPYING or http://www.opensource.org/licenses/mit-license.php.
-"""Test for the ZMQ RPC methods."""
-
-from test_framework.test_framework import BitcoinTestFramework
-from test_framework.util import assert_equal
-
-
-class RPCZMQTest(BitcoinTestFramework):
-
- address = "tcp://127.0.0.1:28332"
-
- def set_test_params(self):
- self.num_nodes = 1
- self.setup_clean_chain = True
-
- def skip_test_if_missing_module(self):
- self.skip_if_no_py3_zmq()
- self.skip_if_no_bitcoind_zmq()
-
- def run_test(self):
- self._test_getzmqnotifications()
-
- def _test_getzmqnotifications(self):
- self.restart_node(0, extra_args=[])
- assert_equal(self.nodes[0].getzmqnotifications(), [])
-
- self.restart_node(0, extra_args=["-zmqpubhashtx=%s" % self.address])
- assert_equal(self.nodes[0].getzmqnotifications(), [
- {"type": "pubhashtx", "address": self.address},
- ])
-
-
-if __name__ == '__main__':
- RPCZMQTest().main()
diff --git a/test/functional/test_framework/address.py b/test/functional/test_framework/address.py
index d1fb97b024..456d43aa2e 100644
--- a/test/functional/test_framework/address.py
+++ b/test/functional/test_framework/address.py
@@ -9,8 +9,11 @@ from .util import bytes_to_hex_str, hex_str_to_bytes
from . import segwit_addr
+ADDRESS_BCRT1_UNSPENDABLE = 'bcrt1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq3xueyj'
+
chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
+
def byte_to_base58(b, version):
result = ''
str = bytes_to_hex_str(b)
diff --git a/test/functional/test_framework/authproxy.py b/test/functional/test_framework/authproxy.py
index 900090bb66..1140fe9b3e 100644
--- a/test/functional/test_framework/authproxy.py
+++ b/test/functional/test_framework/authproxy.py
@@ -38,6 +38,7 @@ import decimal
import http.client
import json
import logging
+import os
import socket
import time
import urllib.parse
@@ -71,19 +72,12 @@ class AuthServiceProxy():
self._service_name = service_name
self.ensure_ascii = ensure_ascii # can be toggled on the fly by tests
self.__url = urllib.parse.urlparse(service_url)
- port = 80 if self.__url.port is None else self.__url.port
user = None if self.__url.username is None else self.__url.username.encode('utf8')
passwd = None if self.__url.password is None else self.__url.password.encode('utf8')
authpair = user + b':' + passwd
self.__auth_header = b'Basic ' + base64.b64encode(authpair)
-
- if connection:
- # Callables re-use the connection of the original proxy
- self.__conn = connection
- elif self.__url.scheme == 'https':
- self.__conn = http.client.HTTPSConnection(self.__url.hostname, port, timeout=timeout)
- else:
- self.__conn = http.client.HTTPConnection(self.__url.hostname, port, timeout=timeout)
+ self.timeout = timeout
+ self._set_conn(connection)
def __getattr__(self, name):
if name.startswith('__') and name.endswith('__'):
@@ -102,6 +96,10 @@ class AuthServiceProxy():
'User-Agent': USER_AGENT,
'Authorization': self.__auth_header,
'Content-type': 'application/json'}
+ if os.name == 'nt':
+ # Windows somehow does not like to re-use connections
+ # TODO: Find out why the connection would disconnect occasionally and make it reusable on Windows
+ self._set_conn()
try:
self.__conn.request(method, path, postdata, headers)
return self._get_response()
@@ -178,3 +176,13 @@ class AuthServiceProxy():
def __truediv__(self, relative_uri):
return AuthServiceProxy("{}/{}".format(self.__service_url, relative_uri), self._service_name, connection=self.__conn)
+
+ def _set_conn(self, connection=None):
+ port = 80 if self.__url.port is None else self.__url.port
+ if connection:
+ self.__conn = connection
+ self.timeout = connection.timeout
+ elif self.__url.scheme == 'https':
+ self.__conn = http.client.HTTPSConnection(self.__url.hostname, port, timeout=self.timeout)
+ else:
+ self.__conn = http.client.HTTPConnection(self.__url.hostname, port, timeout=self.timeout)
diff --git a/test/functional/test_framework/messages.py b/test/functional/test_framework/messages.py
index 0a3907cba4..8e9372767d 100755
--- a/test/functional/test_framework/messages.py
+++ b/test/functional/test_framework/messages.py
@@ -13,7 +13,11 @@ CBlock, CTransaction, CBlockHeader, CTxIn, CTxOut, etc....:
msg_block, msg_tx, msg_headers, etc.:
data structures that represent network messages
-ser_*, deser_*: functions that handle serialization/deserialization."""
+ser_*, deser_*: functions that handle serialization/deserialization.
+
+Classes use __slots__ to ensure extraneous attributes aren't accidentally added
+by tests, compromising their intended effect.
+"""
from codecs import encode
import copy
import hashlib
@@ -185,7 +189,10 @@ def ToHex(obj):
# Objects that map to bitcoind objects, which can be serialized/deserialized
-class CAddress():
+
+class CAddress:
+ __slots__ = ("ip", "nServices", "pchReserved", "port", "time")
+
def __init__(self):
self.time = 0
self.nServices = 1
@@ -215,7 +222,10 @@ class CAddress():
return "CAddress(nServices=%i ip=%s port=%i)" % (self.nServices,
self.ip, self.port)
-class CInv():
+
+class CInv:
+ __slots__ = ("hash", "type")
+
typemap = {
0: "Error",
1: "TX",
@@ -244,7 +254,9 @@ class CInv():
% (self.typemap[self.type], self.hash)
-class CBlockLocator():
+class CBlockLocator:
+ __slots__ = ("nVersion", "vHave")
+
def __init__(self):
self.nVersion = MY_VERSION
self.vHave = []
@@ -264,7 +276,9 @@ class CBlockLocator():
% (self.nVersion, repr(self.vHave))
-class COutPoint():
+class COutPoint:
+ __slots__ = ("hash", "n")
+
def __init__(self, hash=0, n=0):
self.hash = hash
self.n = n
@@ -283,7 +297,9 @@ class COutPoint():
return "COutPoint(hash=%064x n=%i)" % (self.hash, self.n)
-class CTxIn():
+class CTxIn:
+ __slots__ = ("nSequence", "prevout", "scriptSig")
+
def __init__(self, outpoint=None, scriptSig=b"", nSequence=0):
if outpoint is None:
self.prevout = COutPoint()
@@ -311,7 +327,9 @@ class CTxIn():
self.nSequence)
-class CTxOut():
+class CTxOut:
+ __slots__ = ("nValue", "scriptPubKey")
+
def __init__(self, nValue=0, scriptPubKey=b""):
self.nValue = nValue
self.scriptPubKey = scriptPubKey
@@ -332,7 +350,9 @@ class CTxOut():
bytes_to_hex_str(self.scriptPubKey))
-class CScriptWitness():
+class CScriptWitness:
+ __slots__ = ("stack",)
+
def __init__(self):
# stack is a vector of strings
self.stack = []
@@ -347,7 +367,9 @@ class CScriptWitness():
return True
-class CTxInWitness():
+class CTxInWitness:
+ __slots__ = ("scriptWitness",)
+
def __init__(self):
self.scriptWitness = CScriptWitness()
@@ -364,7 +386,9 @@ class CTxInWitness():
return self.scriptWitness.is_null()
-class CTxWitness():
+class CTxWitness:
+ __slots__ = ("vtxinwit",)
+
def __init__(self):
self.vtxinwit = []
@@ -392,7 +416,10 @@ class CTxWitness():
return True
-class CTransaction():
+class CTransaction:
+ __slots__ = ("hash", "nLockTime", "nVersion", "sha256", "vin", "vout",
+ "wit")
+
def __init__(self, tx=None):
if tx is None:
self.nVersion = 1
@@ -496,7 +523,10 @@ class CTransaction():
% (self.nVersion, repr(self.vin), repr(self.vout), repr(self.wit), self.nLockTime)
-class CBlockHeader():
+class CBlockHeader:
+ __slots__ = ("hash", "hashMerkleRoot", "hashPrevBlock", "nBits", "nNonce",
+ "nTime", "nVersion", "sha256")
+
def __init__(self, header=None):
if header is None:
self.set_null()
@@ -565,6 +595,8 @@ class CBlockHeader():
class CBlock(CBlockHeader):
+ __slots__ = ("vtx",)
+
def __init__(self, header=None):
super(CBlock, self).__init__(header)
self.vtx = []
@@ -636,7 +668,9 @@ class CBlock(CBlockHeader):
time.ctime(self.nTime), self.nBits, self.nNonce, repr(self.vtx))
-class PrefilledTransaction():
+class PrefilledTransaction:
+ __slots__ = ("index", "tx")
+
def __init__(self, index=0, tx = None):
self.index = index
self.tx = tx
@@ -664,8 +698,12 @@ class PrefilledTransaction():
def __repr__(self):
return "PrefilledTransaction(index=%d, tx=%s)" % (self.index, repr(self.tx))
+
# This is what we send on the wire, in a cmpctblock message.
-class P2PHeaderAndShortIDs():
+class P2PHeaderAndShortIDs:
+ __slots__ = ("header", "nonce", "prefilled_txn", "prefilled_txn_length",
+ "shortids", "shortids_length")
+
def __init__(self):
self.header = CBlockHeader()
self.nonce = 0
@@ -703,9 +741,11 @@ class P2PHeaderAndShortIDs():
def __repr__(self):
return "P2PHeaderAndShortIDs(header=%s, nonce=%d, shortids_length=%d, shortids=%s, prefilled_txn_length=%d, prefilledtxn=%s" % (repr(self.header), self.nonce, self.shortids_length, repr(self.shortids), self.prefilled_txn_length, repr(self.prefilled_txn))
+
# P2P version of the above that will use witness serialization (for compact
# block version 2)
class P2PHeaderAndShortWitnessIDs(P2PHeaderAndShortIDs):
+ __slots__ = ()
def serialize(self):
return super(P2PHeaderAndShortWitnessIDs, self).serialize(with_witness=True)
@@ -715,9 +755,12 @@ def calculate_shortid(k0, k1, tx_hash):
expected_shortid &= 0x0000ffffffffffff
return expected_shortid
+
# This version gets rid of the array lengths, and reinterprets the differential
# encoding into indices that can be used for lookup.
-class HeaderAndShortIDs():
+class HeaderAndShortIDs:
+ __slots__ = ("header", "nonce", "prefilled_txn", "shortids", "use_witness")
+
def __init__(self, p2pheaders_and_shortids = None):
self.header = CBlockHeader()
self.nonce = 0
@@ -778,7 +821,8 @@ class HeaderAndShortIDs():
return "HeaderAndShortIDs(header=%s, nonce=%d, shortids=%s, prefilledtxn=%s" % (repr(self.header), self.nonce, repr(self.shortids), repr(self.prefilled_txn))
-class BlockTransactionsRequest():
+class BlockTransactionsRequest:
+ __slots__ = ("blockhash", "indexes")
def __init__(self, blockhash=0, indexes = None):
self.blockhash = blockhash
@@ -818,7 +862,8 @@ class BlockTransactionsRequest():
return "BlockTransactionsRequest(hash=%064x indexes=%s)" % (self.blockhash, repr(self.indexes))
-class BlockTransactions():
+class BlockTransactions:
+ __slots__ = ("blockhash", "transactions")
def __init__(self, blockhash=0, transactions = None):
self.blockhash = blockhash
@@ -840,7 +885,10 @@ class BlockTransactions():
def __repr__(self):
return "BlockTransactions(hash=%064x transactions=%s)" % (self.blockhash, repr(self.transactions))
-class CPartialMerkleTree():
+
+class CPartialMerkleTree:
+ __slots__ = ("fBad", "nTransactions", "vBits", "vHash")
+
def __init__(self):
self.nTransactions = 0
self.vHash = []
@@ -868,7 +916,10 @@ class CPartialMerkleTree():
def __repr__(self):
return "CPartialMerkleTree(nTransactions=%d, vHash=%s, vBits=%s)" % (self.nTransactions, repr(self.vHash), repr(self.vBits))
-class CMerkleBlock():
+
+class CMerkleBlock:
+ __slots__ = ("header", "txn")
+
def __init__(self):
self.header = CBlockHeader()
self.txn = CPartialMerkleTree()
@@ -888,7 +939,9 @@ class CMerkleBlock():
# Objects that correspond to messages on the wire
-class msg_version():
+class msg_version:
+ __slots__ = ("addrFrom", "addrTo", "nNonce", "nRelay", "nServices",
+ "nStartingHeight", "nTime", "nVersion", "strSubVer")
command = b"version"
def __init__(self):
@@ -945,7 +998,8 @@ class msg_version():
self.strSubVer, self.nStartingHeight, self.nRelay)
-class msg_verack():
+class msg_verack:
+ __slots__ = ()
command = b"verack"
def __init__(self):
@@ -961,7 +1015,8 @@ class msg_verack():
return "msg_verack()"
-class msg_addr():
+class msg_addr:
+ __slots__ = ("addrs",)
command = b"addr"
def __init__(self):
@@ -977,7 +1032,8 @@ class msg_addr():
return "msg_addr(addrs=%s)" % (repr(self.addrs))
-class msg_inv():
+class msg_inv:
+ __slots__ = ("inv",)
command = b"inv"
def __init__(self, inv=None):
@@ -996,7 +1052,8 @@ class msg_inv():
return "msg_inv(inv=%s)" % (repr(self.inv))
-class msg_getdata():
+class msg_getdata:
+ __slots__ = ("inv",)
command = b"getdata"
def __init__(self, inv=None):
@@ -1012,7 +1069,8 @@ class msg_getdata():
return "msg_getdata(inv=%s)" % (repr(self.inv))
-class msg_getblocks():
+class msg_getblocks:
+ __slots__ = ("locator", "hashstop")
command = b"getblocks"
def __init__(self):
@@ -1035,7 +1093,8 @@ class msg_getblocks():
% (repr(self.locator), self.hashstop)
-class msg_tx():
+class msg_tx:
+ __slots__ = ("tx",)
command = b"tx"
def __init__(self, tx=CTransaction()):
@@ -1050,13 +1109,16 @@ class msg_tx():
def __repr__(self):
return "msg_tx(tx=%s)" % (repr(self.tx))
+
class msg_witness_tx(msg_tx):
+ __slots__ = ()
def serialize(self):
return self.tx.serialize_with_witness()
-class msg_block():
+class msg_block:
+ __slots__ = ("block",)
command = b"block"
def __init__(self, block=None):
@@ -1074,9 +1136,12 @@ class msg_block():
def __repr__(self):
return "msg_block(block=%s)" % (repr(self.block))
+
# for cases where a user needs tighter control over what is sent over the wire
# note that the user must supply the name of the command, and the data
-class msg_generic():
+class msg_generic:
+ __slots__ = ("command", "data")
+
def __init__(self, command, data=None):
self.command = command
self.data = data
@@ -1087,13 +1152,16 @@ class msg_generic():
def __repr__(self):
return "msg_generic()"
-class msg_witness_block(msg_block):
+class msg_witness_block(msg_block):
+ __slots__ = ()
def serialize(self):
r = self.block.serialize(with_witness=True)
return r
-class msg_getaddr():
+
+class msg_getaddr:
+ __slots__ = ()
command = b"getaddr"
def __init__(self):
@@ -1109,7 +1177,8 @@ class msg_getaddr():
return "msg_getaddr()"
-class msg_ping():
+class msg_ping:
+ __slots__ = ("nonce",)
command = b"ping"
def __init__(self, nonce=0):
@@ -1127,7 +1196,8 @@ class msg_ping():
return "msg_ping(nonce=%08x)" % self.nonce
-class msg_pong():
+class msg_pong:
+ __slots__ = ("nonce",)
command = b"pong"
def __init__(self, nonce=0):
@@ -1145,7 +1215,8 @@ class msg_pong():
return "msg_pong(nonce=%08x)" % self.nonce
-class msg_mempool():
+class msg_mempool:
+ __slots__ = ()
command = b"mempool"
def __init__(self):
@@ -1160,7 +1231,9 @@ class msg_mempool():
def __repr__(self):
return "msg_mempool()"
-class msg_sendheaders():
+
+class msg_sendheaders:
+ __slots__ = ()
command = b"sendheaders"
def __init__(self):
@@ -1180,7 +1253,8 @@ class msg_sendheaders():
# number of entries
# vector of hashes
# hash_stop (hash of last desired block header, 0 to get as many as possible)
-class msg_getheaders():
+class msg_getheaders:
+ __slots__ = ("hashstop", "locator",)
command = b"getheaders"
def __init__(self):
@@ -1205,7 +1279,8 @@ class msg_getheaders():
# headers message has
# <count> <vector of block headers>
-class msg_headers():
+class msg_headers:
+ __slots__ = ("headers",)
command = b"headers"
def __init__(self, headers=None):
@@ -1225,7 +1300,8 @@ class msg_headers():
return "msg_headers(headers=%s)" % repr(self.headers)
-class msg_reject():
+class msg_reject:
+ __slots__ = ("code", "data", "message", "reason")
command = b"reject"
REJECT_MALFORMED = 1
@@ -1256,7 +1332,9 @@ class msg_reject():
return "msg_reject: %s %d %s [%064x]" \
% (self.message, self.code, self.reason, self.data)
-class msg_feefilter():
+
+class msg_feefilter:
+ __slots__ = ("feerate",)
command = b"feefilter"
def __init__(self, feerate=0):
@@ -1273,7 +1351,9 @@ class msg_feefilter():
def __repr__(self):
return "msg_feefilter(feerate=%08x)" % self.feerate
-class msg_sendcmpct():
+
+class msg_sendcmpct:
+ __slots__ = ("announce", "version")
command = b"sendcmpct"
def __init__(self):
@@ -1293,7 +1373,9 @@ class msg_sendcmpct():
def __repr__(self):
return "msg_sendcmpct(announce=%s, version=%lu)" % (self.announce, self.version)
-class msg_cmpctblock():
+
+class msg_cmpctblock:
+ __slots__ = ("header_and_shortids",)
command = b"cmpctblock"
def __init__(self, header_and_shortids = None):
@@ -1311,7 +1393,9 @@ class msg_cmpctblock():
def __repr__(self):
return "msg_cmpctblock(HeaderAndShortIDs=%s)" % repr(self.header_and_shortids)
-class msg_getblocktxn():
+
+class msg_getblocktxn:
+ __slots__ = ("block_txn_request",)
command = b"getblocktxn"
def __init__(self):
@@ -1329,7 +1413,9 @@ class msg_getblocktxn():
def __repr__(self):
return "msg_getblocktxn(block_txn_request=%s)" % (repr(self.block_txn_request))
-class msg_blocktxn():
+
+class msg_blocktxn:
+ __slots__ = ("block_transactions",)
command = b"blocktxn"
def __init__(self):
@@ -1346,7 +1432,10 @@ class msg_blocktxn():
def __repr__(self):
return "msg_blocktxn(block_transactions=%s)" % (repr(self.block_transactions))
+
class msg_witness_blocktxn(msg_blocktxn):
+ __slots__ = ()
+
def serialize(self):
r = b""
r += self.block_transactions.serialize(with_witness=True)
diff --git a/test/functional/test_framework/script.py b/test/functional/test_framework/script.py
index 375d6334f7..2fe44010ba 100644
--- a/test/functional/test_framework/script.py
+++ b/test/functional/test_framework/script.py
@@ -26,7 +26,7 @@ def hash160(s):
_opcode_instances = []
class CScriptOp(int):
"""A single script opcode"""
- __slots__ = []
+ __slots__ = ()
@staticmethod
def encode_op_pushdata(d):
@@ -361,8 +361,11 @@ class CScriptTruncatedPushDataError(CScriptInvalidError):
self.data = data
super(CScriptTruncatedPushDataError, self).__init__(msg)
+
# This is used, eg, for blockchain heights in coinbase scripts (bip34)
-class CScriptNum():
+class CScriptNum:
+ __slots__ = ("value",)
+
def __init__(self, d=0):
self.value = d
@@ -393,6 +396,8 @@ class CScript(bytes):
iter(script) however does iterate by opcode.
"""
+ __slots__ = ()
+
@classmethod
def __coerce_instance(cls, other):
# Coerce other into bytes
diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py
index 9a589240a8..7e2ec673df 100755
--- a/test/functional/test_framework/test_framework.py
+++ b/test/functional/test_framework/test_framework.py
@@ -161,8 +161,10 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
success = TestStatus.FAILED
try:
- if self.options.usecli and not self.supports_cli:
- raise SkipTest("--usecli specified but test does not support using CLI")
+ if self.options.usecli:
+ if not self.supports_cli:
+ raise SkipTest("--usecli specified but test does not support using CLI")
+ self.skip_if_no_cli()
self.skip_test_if_missing_module()
self.setup_chain()
self.setup_network()
@@ -525,7 +527,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
config = configparser.ConfigParser()
config.read_file(open(self.options.configfile))
- return config["components"].getboolean("ENABLE_UTILS")
+ return config["components"].getboolean("ENABLE_CLI")
def is_wallet_compiled(self):
"""Checks whether the wallet module was compiled."""
diff --git a/test/functional/test_framework/test_node.py b/test/functional/test_framework/test_node.py
index 7ab7fcfcb4..c05988c661 100755
--- a/test/functional/test_framework/test_node.py
+++ b/test/functional/test_framework/test_node.py
@@ -187,7 +187,9 @@ class TestNode():
if e.errno != errno.ECONNREFUSED: # Port not yet open?
raise # unknown IO error
except JSONRPCException as e: # Initialization phase
- if e.error['code'] != -28: # RPC in warmup?
+ # -28 RPC in warmup
+ # -342 Service unavailable, RPC server started but is shutting down due to error
+ if e.error['code'] != -28 and e.error['code'] != -342:
raise # unknown JSON RPC exception
except ValueError as e: # cookie file not found and no rpcuser or rpcassword. bitcoind still starting
if "No RPC credentials" not in str(e):
diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py
index 37a3c1c602..c6d1574201 100755
--- a/test/functional/test_runner.py
+++ b/test/functional/test_runner.py
@@ -29,7 +29,7 @@ import re
import logging
# Formatting. Default colors to empty strings.
-BOLD, BLUE, RED, GREY = ("", ""), ("", ""), ("", ""), ("", "")
+BOLD, GREEN, RED, GREY = ("", ""), ("", ""), ("", ""), ("", "")
try:
# Make sure python thinks it can write unicode to its stdout
"\u2713".encode("utf_8").decode(sys.stdout.encoding)
@@ -41,11 +41,27 @@ except UnicodeDecodeError:
CROSS = "x "
CIRCLE = "o "
-if os.name == 'posix':
+if os.name != 'nt' or sys.getwindowsversion() >= (10, 0, 14393):
+ if os.name == 'nt':
+ import ctypes
+ kernel32 = ctypes.windll.kernel32
+ ENABLE_VIRTUAL_TERMINAL_PROCESSING = 4
+ STD_OUTPUT_HANDLE = -11
+ STD_ERROR_HANDLE = -12
+ # Enable ascii color control to stdout
+ stdout = kernel32.GetStdHandle(STD_OUTPUT_HANDLE)
+ stdout_mode = ctypes.c_int32()
+ kernel32.GetConsoleMode(stdout, ctypes.byref(stdout_mode))
+ kernel32.SetConsoleMode(stdout, stdout_mode.value | ENABLE_VIRTUAL_TERMINAL_PROCESSING)
+ # Enable ascii color control to stderr
+ stderr = kernel32.GetStdHandle(STD_ERROR_HANDLE)
+ stderr_mode = ctypes.c_int32()
+ kernel32.GetConsoleMode(stderr, ctypes.byref(stderr_mode))
+ kernel32.SetConsoleMode(stderr, stderr_mode.value | ENABLE_VIRTUAL_TERMINAL_PROCESSING)
# primitive formatting on supported
# terminal via ANSI escape sequences:
BOLD = ('\033[0m', '\033[1m')
- BLUE = ('\033[0m', '\033[0;34m')
+ GREEN = ('\033[0m', '\033[0;32m')
RED = ('\033[0m', '\033[0;31m')
GREY = ('\033[0m', '\033[1;30m')
@@ -136,7 +152,6 @@ BASE_SCRIPTS = [
'feature_versionbits_warning.py',
'rpc_preciousblock.py',
'wallet_importprunedfunds.py',
- 'rpc_zmq.py',
'rpc_signmessage.py',
'feature_nulldummy.py',
'mempool_accept.py',
@@ -227,6 +242,11 @@ def main():
# Create base test directory
tmpdir = "%s/test_runner_₿_🏃_%s" % (args.tmpdirprefix, datetime.datetime.now().strftime("%Y%m%d_%H%M%S"))
+
+ # If we fixed the command-line and filename encoding issue on Windows, these two lines could be removed
+ if config["environment"]["EXEEXT"] == ".exe":
+ tmpdir = "%s/test_runner_%s" % (args.tmpdirprefix, datetime.datetime.now().strftime("%Y%m%d_%H%M%S"))
+
os.makedirs(tmpdir)
logging.debug("Temporary test directory at %s" % tmpdir)
@@ -264,11 +284,13 @@ def main():
# Remove the test cases that the user has explicitly asked to exclude.
if args.exclude:
- exclude_tests = [re.sub("\.py$", "", test) + ".py" for test in args.exclude.split(',')]
+ exclude_tests = [test.split('.py')[0] for test in args.exclude.split(',')]
for exclude_test in exclude_tests:
- if exclude_test in test_list:
- test_list.remove(exclude_test)
- else:
+ # Remove <test_name>.py and <test_name>.py --arg from the test list
+ exclude_list = [test for test in test_list if test.split('.py')[0] == exclude_test]
+ for exclude_item in exclude_list:
+ test_list.remove(exclude_item)
+ if not exclude_list:
print("{}WARNING!{} Test '{}' not found in current test list.".format(BOLD[1], BOLD[0], exclude_test))
if not test_list:
@@ -359,7 +381,10 @@ def run_tests(test_list, src_dir, build_dir, tmpdir, jobs=1, enable_coverage=Fal
print('\n============')
print('{}Combined log for {}:{}'.format(BOLD[1], testdir, BOLD[0]))
print('============\n')
- combined_logs, _ = subprocess.Popen([sys.executable, os.path.join(tests_dir, 'combine_logs.py'), '-c', testdir], universal_newlines=True, stdout=subprocess.PIPE).communicate()
+ combined_logs_args = [sys.executable, os.path.join(tests_dir, 'combine_logs.py'), testdir]
+ if BOLD[0]:
+ combined_logs_args += ['--color']
+ combined_logs, _ = subprocess.Popen(combined_logs_args, universal_newlines=True, stdout=subprocess.PIPE).communicate()
print("\n".join(deque(combined_logs.splitlines(), combined_logs_len)))
if failfast:
@@ -498,7 +523,7 @@ class TestResult():
def __repr__(self):
if self.status == "Passed":
- color = BLUE
+ color = GREEN
glyph = TICK
elif self.status == "Failed":
color = RED
diff --git a/test/functional/wallet_basic.py b/test/functional/wallet_basic.py
index 4079d05491..8bbff7f7ef 100755
--- a/test/functional/wallet_basic.py
+++ b/test/functional/wallet_basic.py
@@ -134,9 +134,15 @@ class WalletTest(BitcoinTestFramework):
assert_equal([unspent_0], self.nodes[2].listlockunspent())
self.nodes[2].lockunspent(True, [unspent_0])
assert_equal(len(self.nodes[2].listlockunspent()), 0)
- assert_raises_rpc_error(-8, "Invalid parameter, unknown transaction",
+ assert_raises_rpc_error(-8, "txid must be of length 64 (not 34, for '0000000000000000000000000000000000')",
self.nodes[2].lockunspent, False,
[{"txid": "0000000000000000000000000000000000", "vout": 0}])
+ assert_raises_rpc_error(-8, "txid must be hexadecimal string (not 'ZZZ0000000000000000000000000000000000000000000000000000000000000')",
+ self.nodes[2].lockunspent, False,
+ [{"txid": "ZZZ0000000000000000000000000000000000000000000000000000000000000", "vout": 0}])
+ assert_raises_rpc_error(-8, "Invalid parameter, unknown transaction",
+ self.nodes[2].lockunspent, False,
+ [{"txid": "0000000000000000000000000000000000000000000000000000000000000000", "vout": 0}])
assert_raises_rpc_error(-8, "Invalid parameter, vout index out of bounds",
self.nodes[2].lockunspent, False,
[{"txid": unspent_0["txid"], "vout": 999}])
diff --git a/test/functional/wallet_hd.py b/test/functional/wallet_hd.py
index 48e71f6c40..eb42531693 100755
--- a/test/functional/wallet_hd.py
+++ b/test/functional/wallet_hd.py
@@ -25,12 +25,6 @@ class WalletHDTest(BitcoinTestFramework):
self.skip_if_no_wallet()
def run_test(self):
- # Make sure can't switch off usehd after wallet creation
- self.stop_node(1)
- self.nodes[1].assert_start_raises_init_error(['-usehd=0'], "Error: Error loading : You can't disable HD on an already existing HD wallet")
- self.start_node(1)
- connect_nodes_bi(self.nodes, 0, 1)
-
# Make sure we use hd, keep masterkeyid
masterkeyid = self.nodes[1].getwalletinfo()['hdseedid']
assert_equal(masterkeyid, self.nodes[1].getwalletinfo()['hdmasterkeyid'])
diff --git a/test/functional/wallet_listsinceblock.py b/test/functional/wallet_listsinceblock.py
index 53e671cd3b..25ab222375 100755
--- a/test/functional/wallet_listsinceblock.py
+++ b/test/functional/wallet_listsinceblock.py
@@ -53,8 +53,10 @@ class ListSinceBlockTest (BitcoinTestFramework):
"42759cde25462784395a337460bde75f58e73d3f08bd31fdc3507cbac856a2c4")
assert_raises_rpc_error(-5, "Block not found", self.nodes[0].listsinceblock,
"0000000000000000000000000000000000000000000000000000000000000000")
- assert_raises_rpc_error(-5, "Block not found", self.nodes[0].listsinceblock,
+ assert_raises_rpc_error(-8, "blockhash must be of length 64 (not 11, for 'invalid-hex')", self.nodes[0].listsinceblock,
"invalid-hex")
+ assert_raises_rpc_error(-8, "blockhash must be hexadecimal string (not 'Z000000000000000000000000000000000000000000000000000000000000000')", self.nodes[0].listsinceblock,
+ "Z000000000000000000000000000000000000000000000000000000000000000")
def test_reorg(self):
'''
diff --git a/test/functional/wallet_multiwallet.py b/test/functional/wallet_multiwallet.py
index aca84477f6..7d7c77638e 100755
--- a/test/functional/wallet_multiwallet.py
+++ b/test/functional/wallet_multiwallet.py
@@ -46,8 +46,9 @@ class MultiWalletTest(BitcoinTestFramework):
# create symlink to verify wallet directory path can be referenced
# through symlink
- os.mkdir(wallet_dir('w7'))
- os.symlink('w7', wallet_dir('w7_symlink'))
+ if os.name != 'nt':
+ os.mkdir(wallet_dir('w7'))
+ os.symlink('w7', wallet_dir('w7_symlink'))
# rename wallet.dat to make sure plain wallet file paths (as opposed to
# directory paths) can be loaded
@@ -68,6 +69,8 @@ class MultiWalletTest(BitcoinTestFramework):
# w8 - to verify existing wallet file is loaded correctly
# '' - to verify default wallet file is created correctly
wallet_names = ['w1', 'w2', 'w3', 'w', 'sub/w5', os.path.join(self.options.tmpdir, 'extern/w6'), 'w7_symlink', 'w8', '']
+ if os.name == 'nt':
+ wallet_names.remove('w7_symlink')
extra_args = ['-wallet={}'.format(n) for n in wallet_names]
self.start_node(0, extra_args)
assert_equal(set(map(lambda w: w['name'], self.nodes[0].listwalletdir()['wallets'])), set(['', 'w3', 'w2', 'sub/w5', 'w7', 'w7', 'w1', 'w8', 'w']))
@@ -80,7 +83,7 @@ class MultiWalletTest(BitcoinTestFramework):
assert_equal(os.path.isfile(wallet_file(wallet_name)), True)
# should not initialize if wallet path can't be created
- exp_stderr = "boost::filesystem::create_directory: (The system cannot find the path specified|Not a directory):"
+ exp_stderr = "boost::filesystem::create_directory:"
self.nodes[0].assert_start_raises_init_error(['-wallet=wallet.dat/bad'], exp_stderr, match=ErrorMatch.PARTIAL_REGEX)
self.nodes[0].assert_start_raises_init_error(['-walletdir=wallets'], 'Error: Specified -walletdir "wallets" does not exist')
@@ -96,8 +99,9 @@ class MultiWalletTest(BitcoinTestFramework):
self.nodes[0].assert_start_raises_init_error(['-wallet=w8', '-wallet=w8_copy'], exp_stderr, match=ErrorMatch.PARTIAL_REGEX)
# should not initialize if wallet file is a symlink
- os.symlink('w8', wallet_dir('w8_symlink'))
- self.nodes[0].assert_start_raises_init_error(['-wallet=w8_symlink'], 'Error: Invalid -wallet path \'w8_symlink\'\. .*', match=ErrorMatch.FULL_REGEX)
+ if os.name != 'nt':
+ os.symlink('w8', wallet_dir('w8_symlink'))
+ self.nodes[0].assert_start_raises_init_error(['-wallet=w8_symlink'], 'Error: Invalid -wallet path \'w8_symlink\'\. .*', match=ErrorMatch.FULL_REGEX)
# should not initialize if the specified walletdir does not exist
self.nodes[0].assert_start_raises_init_error(['-walletdir=bad'], 'Error: Specified -walletdir "bad" does not exist')
@@ -226,7 +230,8 @@ class MultiWalletTest(BitcoinTestFramework):
assert_raises_rpc_error(-1, "BerkeleyBatch: Can't open database w8_copy (duplicates fileid", self.nodes[0].loadwallet, 'w8_copy')
# Fail to load if wallet file is a symlink
- assert_raises_rpc_error(-4, "Wallet file verification failed: Invalid -wallet path 'w8_symlink'", self.nodes[0].loadwallet, 'w8_symlink')
+ if os.name != 'nt':
+ assert_raises_rpc_error(-4, "Wallet file verification failed: Invalid -wallet path 'w8_symlink'", self.nodes[0].loadwallet, 'w8_symlink')
# Fail to load if a directory is specified that doesn't contain a wallet
os.mkdir(wallet_dir('empty_wallet_dir'))
diff --git a/test/lint/check-doc.py b/test/lint/check-doc.py
index 7b056dab32..b0d9f87958 100755
--- a/test/lint/check-doc.py
+++ b/test/lint/check-doc.py
@@ -22,7 +22,7 @@ CMD_ROOT_DIR = '`git rev-parse --show-toplevel`/{}'.format(FOLDER_GREP)
CMD_GREP_ARGS = r"git grep --perl-regexp '{}' -- {} ':(exclude){}'".format(REGEX_ARG, CMD_ROOT_DIR, FOLDER_TEST)
CMD_GREP_DOCS = r"git grep --perl-regexp '{}' {}".format(REGEX_DOC, CMD_ROOT_DIR)
# list unsupported, deprecated and duplicate args as they need no documentation
-SET_DOC_OPTIONAL = set(['-h', '-help', '-dbcrashratio', '-forcecompactdb', '-usehd'])
+SET_DOC_OPTIONAL = set(['-h', '-help', '-dbcrashratio', '-forcecompactdb'])
def main():
diff --git a/test/lint/lint-includes.sh b/test/lint/lint-includes.sh
index a3e7681d45..f6d0fd382b 100755
--- a/test/lint/lint-includes.sh
+++ b/test/lint/lint-includes.sh
@@ -54,7 +54,6 @@ EXPECTED_BOOST_INCLUDES=(
boost/chrono/chrono.hpp
boost/date_time/posix_time/posix_time.hpp
boost/filesystem.hpp
- boost/filesystem/detail/utf8_codecvt_facet.hpp
boost/filesystem/fstream.hpp
boost/multi_index/hashed_index.hpp
boost/multi_index/ordered_index.hpp
diff --git a/test/lint/lint-python.sh b/test/lint/lint-python.sh
index 4f4542ff0c..d44a585294 100755
--- a/test/lint/lint-python.sh
+++ b/test/lint/lint-python.sh
@@ -87,4 +87,4 @@ elif PYTHONWARNINGS="ignore" flake8 --version | grep -q "Python 2"; then
exit 0
fi
-PYTHONWARNINGS="ignore" flake8 --ignore=B,C,E,F,I,N,W --select=E101,E112,E113,E115,E116,E125,E129,E131,E133,E223,E224,E242,E266,E271,E272,E273,E274,E275,E304,E306,E401,E402,E502,E701,E702,E703,E714,E721,E741,E742,E743,E901,E902,F401,F402,F403,F404,F405,F406,F407,F601,F602,F621,F622,F631,F701,F702,F703,F704,F705,F706,F707,F811,F812,F821,F822,F823,F831,F841,W191,W291,W292,W293,W504,W601,W602,W603,W604,W605,W606 .
+PYTHONWARNINGS="ignore" flake8 --ignore=B,C,E,F,I,N,W --select=E101,E112,E113,E115,E116,E125,E129,E131,E133,E223,E224,E242,E266,E271,E272,E273,E274,E275,E304,E306,E401,E402,E502,E701,E702,E703,E714,E721,E741,E742,E743,E901,E902,F401,F402,F403,F404,F405,F406,F407,F601,F602,F621,F622,F631,F701,F702,F703,F704,F705,F706,F707,F811,F812,F821,F822,F823,F831,F841,W191,W291,W292,W293,W504,W601,W602,W603,W604,W605,W606 "${@:-.}"
diff --git a/test/lint/lint-spelling.ignore-words.txt b/test/lint/lint-spelling.ignore-words.txt
index 9a49f32271..f0415443db 100644
--- a/test/lint/lint-spelling.ignore-words.txt
+++ b/test/lint/lint-spelling.ignore-words.txt
@@ -1,6 +1,7 @@
cas
hights
mor
+mut
objext
unselect
useable
diff --git a/test/lint/lint-spelling.sh b/test/lint/lint-spelling.sh
index ebeafd7d58..5d672698a7 100755
--- a/test/lint/lint-spelling.sh
+++ b/test/lint/lint-spelling.sh
@@ -9,10 +9,7 @@
export LC_ALL=C
-EXIT_CODE=0
IGNORE_WORDS_FILE=test/lint/lint-spelling.ignore-words.txt
if ! codespell --check-filenames --disable-colors --quiet-level=7 --ignore-words=${IGNORE_WORDS_FILE} $(git ls-files -- ":(exclude)build-aux/m4/" ":(exclude)contrib/seeds/*.txt" ":(exclude)depends/" ":(exclude)doc/release-notes/" ":(exclude)src/leveldb/" ":(exclude)src/qt/locale/" ":(exclude)src/secp256k1/" ":(exclude)src/univalue/"); then
echo "^ Warning: codespell identified likely spelling errors. Any false positives? Add them to the list of ignored words in ${IGNORE_WORDS_FILE}"
- EXIT_CODE=1
fi
-exit ${EXIT_CODE}
diff --git a/test/util/data/bitcoin-util-test.json b/test/util/data/bitcoin-util-test.json
index f2213f4f2e..761923a818 100644
--- a/test/util/data/bitcoin-util-test.json
+++ b/test/util/data/bitcoin-util-test.json
@@ -105,6 +105,30 @@
{ "exec": "./bitcoin-tx",
"args":
["-create",
+ "in=Z897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0"],
+ "return_code": 1,
+ "error_txt": "error: invalid TX input txid",
+ "description": "Tests the check for an invalid txid invalid hex"
+ },
+ { "exec": "./bitcoin-tx",
+ "args":
+ ["-create",
+ "in=5897de6bd6:0"],
+ "return_code": 1,
+ "error_txt": "error: invalid TX input txid",
+ "description": "Tests the check for an invalid txid valid hex but too short"
+ },
+ { "exec": "./bitcoin-tx",
+ "args":
+ ["-create",
+ "in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f12:0"],
+ "return_code": 1,
+ "error_txt": "error: invalid TX input txid",
+ "description": "Tests the check for an invalid txid valid hex but too long"
+ },
+ { "exec": "./bitcoin-tx",
+ "args":
+ ["-create",
"in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0",
"replaceable=0foo"],
"return_code": 1,
@@ -282,6 +306,42 @@
},
{ "exec": "./bitcoin-tx",
"args":
+ ["-create",
+ "in=4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc59485:0",
+ "set=privatekeys:[\"5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAnchuDf\"]",
+ "set=prevtxs:[{\"txid\":\"Zd49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc59412\",\"vout\":0,\"scriptPubKey\":\"76a91491b24bf9f5288532960ac687abb035127b1d28a588ac\"}]",
+ "sign=ALL",
+ "outaddr=0.001:193P6LtvS4nCnkDvM9uXn1gsSRqh4aDAz7"],
+ "return_code": 1,
+ "error_txt": "error: txid must be hexadecimal string (not 'Zd49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc59412')",
+ "description": "Tests the check for invalid txid due to invalid hex"
+ },
+ { "exec": "./bitcoin-tx",
+ "args":
+ ["-create",
+ "in=4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc59485:0",
+ "set=privatekeys:[\"5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAnchuDf\"]",
+ "set=prevtxs:[{\"txid\":\"4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc594\",\"vout\":0,\"scriptPubKey\":\"76a91491b24bf9f5288532960ac687abb035127b1d28a588ac\"}]",
+ "sign=ALL",
+ "outaddr=0.001:193P6LtvS4nCnkDvM9uXn1gsSRqh4aDAz7"],
+ "return_code": 1,
+ "error_txt": "error: txid must be hexadecimal string (not '4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc594')",
+ "description": "Tests the check for invalid txid valid hex, but too short"
+ },
+ { "exec": "./bitcoin-tx",
+ "args":
+ ["-create",
+ "in=4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc59485:0",
+ "set=privatekeys:[\"5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAnchuDf\"]",
+ "set=prevtxs:[{\"txid\":\"4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc5948512\",\"vout\":0,\"scriptPubKey\":\"76a91491b24bf9f5288532960ac687abb035127b1d28a588ac\"}]",
+ "sign=ALL",
+ "outaddr=0.001:193P6LtvS4nCnkDvM9uXn1gsSRqh4aDAz7"],
+ "return_code": 1,
+ "error_txt": "error: txid must be hexadecimal string (not '4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc5948512')",
+ "description": "Tests the check for invalid txid valid hex, but too long"
+ },
+ { "exec": "./bitcoin-tx",
+ "args":
["-create", "outpubkey=0:02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397", "nversion=1"],
"output_cmp": "txcreateoutpubkey1.hex",
"description": "Creates a new transaction with a single pay-to-pubkey output"