aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cirrus.yml14
-rw-r--r--Makefile.am13
-rw-r--r--build-aux/m4/bitcoin_qt.m49
-rw-r--r--build_msvc/bitcoin_config.h3
-rw-r--r--build_msvc/common.init.vcxproj2
-rw-r--r--build_msvc/libleveldb/libleveldb.vcxproj2
-rw-r--r--build_msvc/test_bitcoin-qt/test_bitcoin-qt.vcxproj3
-rwxr-xr-xci/test/00_setup_env.sh6
-rw-r--r--ci/test/00_setup_env_android.sh25
-rwxr-xr-xci/test/05_before_script.sh9
-rwxr-xr-xci/test/06_script_a.sh8
-rw-r--r--configure.ac33
-rw-r--r--contrib/devtools/README.md3
-rwxr-xr-xcontrib/devtools/test-security-check.py11
-rwxr-xr-xcontrib/devtools/test-symbol-check.py7
-rw-r--r--contrib/init/bitcoind.service3
-rw-r--r--contrib/testgen/README.md4
-rwxr-xr-xcontrib/testgen/gen_key_io_test_vectors.py84
-rw-r--r--depends/packages/libxkbcommon.mk2
-rw-r--r--depends/packages/miniupnpc.mk10
-rw-r--r--depends/packages/qt.mk7
-rw-r--r--depends/patches/miniupnpc/dont_leak_info.patch32
-rw-r--r--depends/patches/miniupnpc/dont_use_wingen.patch26
-rw-r--r--depends/patches/qt/fix_android_pch.patch10
-rw-r--r--depends/patches/qt/fix_bigsur_drawing.patch31
-rw-r--r--doc/README.md1
-rw-r--r--doc/REST-interface.md5
-rw-r--r--doc/bips.md3
-rw-r--r--doc/build-android.md12
-rw-r--r--doc/build-osx.md330
-rw-r--r--doc/dependencies.md9
-rw-r--r--doc/release-notes-20861.md13
-rw-r--r--doc/release-notes.md23
-rw-r--r--share/qt/Info.plist.in3
-rw-r--r--src/Makefile.qt.include14
-rw-r--r--src/Makefile.qttest.include3
-rw-r--r--src/Makefile.test.include4
-rw-r--r--src/bech32.cpp52
-rw-r--r--src/bech32.h39
-rw-r--r--src/bench/bech32.cpp2
-rw-r--r--src/bitcoin-cli.cpp6
-rw-r--r--src/bitcoin-tx.cpp2
-rw-r--r--src/chainparams.h4
-rw-r--r--src/coins.h3
-rw-r--r--src/core_io.h4
-rw-r--r--src/core_write.cpp24
-rw-r--r--src/httpserver.cpp8
-rw-r--r--src/init.cpp9
-rw-r--r--src/key_io.cpp30
-rw-r--r--src/net.cpp31
-rw-r--r--src/net.h11
-rw-r--r--src/net_processing.cpp341
-rw-r--r--src/net_processing.h14
-rw-r--r--src/netbase.cpp16
-rw-r--r--src/netbase.h20
-rw-r--r--src/node/coinstats.cpp1
-rw-r--r--src/node/context.cpp1
-rw-r--r--src/node/context.h2
-rw-r--r--src/node/transaction.cpp8
-rw-r--r--src/qt/Makefile2
-rw-r--r--src/qt/android/AndroidManifest.xml38
-rw-r--r--src/qt/android/build.gradle52
-rw-r--r--src/qt/android/gradle.properties4
-rw-r--r--src/qt/android/res/drawable-hdpi/bitcoin.pngbin0 -> 4536 bytes
-rw-r--r--src/qt/android/res/drawable-ldpi/bitcoin.pngbin0 -> 1697 bytes
-rw-r--r--src/qt/android/res/drawable-mdpi/bitcoin.pngbin0 -> 2558 bytes
-rw-r--r--src/qt/android/res/drawable-xhdpi/bitcoin.pngbin0 -> 6832 bytes
-rw-r--r--src/qt/android/res/drawable-xxhdpi/bitcoin.pngbin0 -> 11479 bytes
-rw-r--r--src/qt/android/res/drawable-xxxhdpi/bitcoin.pngbin0 -> 17034 bytes
-rw-r--r--src/qt/android/src/org/bitcoincore/qt/BitcoinQtActivity.java29
-rw-r--r--src/qt/bitcoin.cpp6
-rw-r--r--src/qt/createwalletdialog.cpp6
-rw-r--r--src/qt/guiutil.cpp12
-rw-r--r--src/qt/optionsdialog.h2
-rw-r--r--src/qt/paymentserver.cpp12
-rw-r--r--src/qt/platformstyle.cpp2
-rw-r--r--src/qt/rpcconsole.cpp2
-rw-r--r--src/qt/test/compattests.cpp25
-rw-r--r--src/qt/test/compattests.h19
-rw-r--r--src/qt/test/test_main.cpp5
-rw-r--r--src/qt/trafficgraphwidget.cpp10
-rw-r--r--src/rpc/blockchain.cpp26
-rw-r--r--src/rpc/blockchain.h4
-rw-r--r--src/rpc/net.cpp8
-rw-r--r--src/rpc/rawtransaction.cpp21
-rw-r--r--src/script/standard.cpp2
-rw-r--r--src/script/standard.h2
-rw-r--r--src/test/addrman_tests.cpp2
-rw-r--r--src/test/bech32_tests.cpp58
-rw-r--r--src/test/bswap_tests.cpp1
-rw-r--r--src/test/data/key_io_invalid.json146
-rw-r--r--src/test/data/key_io_valid.json571
-rw-r--r--src/test/denialofservice_tests.cpp38
-rw-r--r--src/test/fuzz/addrman.cpp2
-rw-r--r--src/test/fuzz/asmap_direct.cpp3
-rw-r--r--src/test/fuzz/bech32.cpp32
-rw-r--r--src/test/fuzz/connman.cpp25
-rw-r--r--src/test/fuzz/cuckoocache.cpp2
-rw-r--r--src/test/fuzz/netbase_dns_lookup.cpp2
-rw-r--r--src/test/fuzz/parse_numbers.cpp3
-rw-r--r--src/test/fuzz/pow.cpp8
-rw-r--r--src/test/fuzz/process_message.cpp4
-rw-r--r--src/test/fuzz/process_messages.cpp6
-rw-r--r--src/test/fuzz/script.cpp6
-rw-r--r--src/test/fuzz/socks5.cpp3
-rw-r--r--src/test/fuzz/string.cpp3
-rw-r--r--src/test/fuzz/transaction.cpp6
-rw-r--r--src/test/fuzz/tx_pool.cpp285
-rw-r--r--src/test/fuzz/util.cpp78
-rw-r--r--src/test/fuzz/util.h22
-rw-r--r--src/test/fuzz/versionbits.cpp351
-rw-r--r--src/test/net_tests.cpp57
-rw-r--r--src/test/netbase_tests.cpp19
-rw-r--r--src/test/util/setup_common.cpp11
-rw-r--r--src/test/util_tests.cpp41
-rw-r--r--src/txmempool.cpp2
-rw-r--r--src/txmempool.h2
-rw-r--r--src/util/check.h2
-rw-r--r--src/util/strencodings.cpp32
-rw-r--r--src/util/strencodings.h9
-rw-r--r--src/validation.cpp6
-rw-r--r--src/wallet/load.cpp2
-rw-r--r--src/wallet/rpcwallet.cpp2
-rw-r--r--src/wallet/wallet.cpp2
-rwxr-xr-xtest/functional/feature_anchors.py85
-rwxr-xr-xtest/functional/feature_rbf.py7
-rwxr-xr-xtest/functional/feature_segwit.py2
-rwxr-xr-xtest/functional/feature_utxo_set_hash.py30
-rwxr-xr-xtest/functional/interface_rpc.py26
-rwxr-xr-xtest/functional/mempool_package_onemore.py2
-rwxr-xr-xtest/functional/p2p_feefilter.py14
-rwxr-xr-xtest/functional/p2p_filter.py6
-rw-r--r--test/functional/rpc_addresses_deprecation.py58
-rwxr-xr-xtest/functional/rpc_createmultisig.py2
-rwxr-xr-xtest/functional/rpc_fundrawtransaction.py10
-rwxr-xr-xtest/functional/rpc_generateblock.py8
-rwxr-xr-xtest/functional/rpc_invalid_address_message.py20
-rwxr-xr-xtest/functional/rpc_psbt.py12
-rwxr-xr-xtest/functional/test_framework/messages.py12
-rw-r--r--test/functional/test_framework/segwit_addr.py54
-rw-r--r--test/functional/test_framework/util.py2
-rw-r--r--test/functional/test_framework/wallet.py3
-rwxr-xr-xtest/functional/test_runner.py2
-rwxr-xr-xtest/functional/wallet_address_types.py2
-rwxr-xr-xtest/functional/wallet_avoidreuse.py2
-rwxr-xr-xtest/functional/wallet_basic.py2
-rwxr-xr-xtest/functional/wallet_bumpfee.py2
-rwxr-xr-xtest/functional/wallet_hd.py2
-rwxr-xr-xtest/functional/wallet_labels.py10
-rwxr-xr-xtest/functional/wallet_multiwallet.py2
-rwxr-xr-xtest/functional/wallet_send.py4
-rwxr-xr-xtest/functional/wallet_txn_clone.py4
-rw-r--r--test/util/data/tt-delin1-out.json14
-rw-r--r--test/util/data/tt-delout1-out.json7
-rw-r--r--test/util/data/tt-locktime317000-out.json14
-rw-r--r--test/util/data/txcreate1.json14
-rw-r--r--test/util/data/txcreatedata1.json7
-rw-r--r--test/util/data/txcreatedata2.json7
-rw-r--r--test/util/data/txcreatedata_seq0.json7
-rw-r--r--test/util/data/txcreatedata_seq1.json7
-rw-r--r--test/util/data/txcreatemultisig1.json8
-rw-r--r--test/util/data/txcreatemultisig2.json7
-rw-r--r--test/util/data/txcreatemultisig3.json7
-rw-r--r--test/util/data/txcreatemultisig4.json7
-rw-r--r--test/util/data/txcreatemultisig5.json7
-rw-r--r--test/util/data/txcreateoutpubkey2.json7
-rw-r--r--test/util/data/txcreateoutpubkey3.json7
-rw-r--r--test/util/data/txcreatescript2.json7
-rw-r--r--test/util/data/txcreatescript3.json7
-rw-r--r--test/util/data/txcreatescript4.json7
-rw-r--r--test/util/data/txcreatesignv1.json7
171 files changed, 2861 insertions, 1217 deletions
diff --git a/.cirrus.yml b/.cirrus.yml
index 691582239e..b3d58461e0 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -35,8 +35,6 @@ global_task_template: &GLOBAL_TASK_TEMPLATE
folder: "/tmp/cirrus-ci-build/depends/built"
depends_sdk_cache:
folder: "/tmp/cirrus-ci-build/depends/sdk-sources"
- depends_releases_cache:
- folder: "/tmp/cirrus-ci-build/releases"
ci_script:
- ./ci/test_run_all.sh
@@ -103,6 +101,8 @@ task:
# For faster CI feedback, immediately schedule a task that compiles most modules
<< : *CREDITS_TEMPLATE
<< : *GLOBAL_TASK_TEMPLATE
+ depends_releases_cache:
+ folder: "/tmp/cirrus-ci-build/releases"
container:
image: ubuntu:bionic
env:
@@ -180,3 +180,13 @@ task:
CI_USE_APT_INSTALL: "no"
PACKAGE_MANAGER_INSTALL: "echo" # Nothing to do
FILE_ENV: "./ci/test/00_setup_env_mac_host.sh"
+
+task:
+ name: 'ARM64 Android APK [focal]'
+ depends_sources_cache:
+ folder: "/tmp/cirrus-ci-build/depends/sources"
+ << : *GLOBAL_TASK_TEMPLATE
+ container:
+ image: ubuntu:focal
+ env:
+ FILE_ENV: "./ci/test/00_setup_env_android.sh"
diff --git a/Makefile.am b/Makefile.am
index 66be768277..be62c3e6a9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -78,6 +78,7 @@ COVERAGE_INFO = $(COV_TOOL_WRAPPER) baseline.info \
dist-hook:
-$(GIT) archive --format=tar HEAD -- src/clientversion.cpp | $(AMTAR) -C $(top_distdir) -xf -
+if TARGET_WINDOWS
$(BITCOIN_WIN_INSTALLER): all-recursive
$(MKDIR_P) $(top_builddir)/release
STRIPPROG="$(STRIP)" $(INSTALL_STRIP_PROGRAM) $(BITCOIND_BIN) $(top_builddir)/release
@@ -90,6 +91,10 @@ $(BITCOIN_WIN_INSTALLER): all-recursive
echo error: could not build $@
@echo built $@
+deploy: $(BITCOIN_WIN_INSTALLER)
+endif
+
+if TARGET_DARWIN
$(OSX_APP)/Contents/PkgInfo:
$(MKDIR_P) $(@D)
@echo "APPL????" > $@
@@ -133,7 +138,7 @@ $(OSX_BACKGROUND_IMAGE): $(OSX_BACKGROUND_IMAGE).png $(OSX_BACKGROUND_IMAGE)@2x.
tiffutil -cathidpicheck $^ -out $@
deploydir: $(OSX_DMG)
-else
+else !BUILD_DARWIN
APP_DIST_DIR=$(top_builddir)/dist
APP_DIST_EXTRAS=$(APP_DIST_DIR)/.background/$(OSX_BACKGROUND_IMAGE) $(APP_DIST_DIR)/.DS_Store $(APP_DIST_DIR)/Applications
@@ -160,15 +165,11 @@ $(APP_DIST_DIR)/$(OSX_APP)/Contents/MacOS/Bitcoin-Qt: $(OSX_APP_BUILT) $(OSX_PAC
INSTALLNAMETOOL=$(INSTALLNAMETOOL) OTOOL=$(OTOOL) STRIP=$(STRIP) $(PYTHON) $(OSX_DEPLOY_SCRIPT) $(OSX_APP) $(OSX_VOLNAME) -translations-dir=$(QT_TRANSLATION_DIR)
deploydir: $(APP_DIST_EXTRAS)
-endif
+endif !BUILD_DARWIN
-if TARGET_DARWIN
appbundle: $(OSX_APP_BUILT)
deploy: $(OSX_DMG)
endif
-if TARGET_WINDOWS
-deploy: $(BITCOIN_WIN_INSTALLER)
-endif
$(BITCOIN_QT_BIN): FORCE
$(MAKE) -C src qt/$(@F)
diff --git a/build-aux/m4/bitcoin_qt.m4 b/build-aux/m4/bitcoin_qt.m4
index 1fd88db08f..cce06e2fff 100644
--- a/build-aux/m4/bitcoin_qt.m4
+++ b/build-aux/m4/bitcoin_qt.m4
@@ -123,7 +123,12 @@ AC_DEFUN([BITCOIN_QT_CONFIGURE],[
_BITCOIN_QT_CHECK_STATIC_LIBS
if test "x$qt_plugin_path" != x; then
- QT_LIBS="$QT_LIBS -L$qt_plugin_path/platforms -L$qt_plugin_path/styles"
+ if test -d "$qt_plugin_path/platforms"; then
+ QT_LIBS="$QT_LIBS -L$qt_plugin_path/platforms"
+ fi
+ if test -d "$qt_plugin_path/styles"; then
+ QT_LIBS="$QT_LIBS -L$qt_plugin_path/styles"
+ fi
if test -d "$qt_plugin_path/accessible"; then
QT_LIBS="$QT_LIBS -L$qt_plugin_path/accessible"
fi
@@ -146,7 +151,7 @@ AC_DEFUN([BITCOIN_QT_CONFIGURE],[
elif test "x$TARGET_OS" = xlinux; then
dnl workaround for https://bugreports.qt.io/browse/QTBUG-74874
AX_CHECK_LINK_FLAG([-lxcb-shm], [QT_LIBS="-lxcb-shm $QT_LIBS"], [AC_MSG_ERROR([could not link against -lxcb-shm])])
- _BITCOIN_QT_CHECK_STATIC_PLUGIN([QXcbIntegrationPlugin], [-lqxcb -lxcb-static])
+ _BITCOIN_QT_CHECK_STATIC_PLUGIN([QXcbIntegrationPlugin], [-lqxcb])
AC_DEFINE(QT_QPA_PLATFORM_XCB, 1, [Define this symbol if the qt platform is xcb])
elif test "x$TARGET_OS" = xdarwin; then
AX_CHECK_LINK_FLAG([[-framework Carbon]],[QT_LIBS="$QT_LIBS -framework Carbon"],[AC_MSG_ERROR(could not link against Carbon framework)])
diff --git a/build_msvc/bitcoin_config.h b/build_msvc/bitcoin_config.h
index dd01cb29eb..aba5607eb6 100644
--- a/build_msvc/bitcoin_config.h
+++ b/build_msvc/bitcoin_config.h
@@ -181,9 +181,6 @@
/* Define to 1 if you have the <miniupnpc/miniupnpc.h> header file. */
#define HAVE_MINIUPNPC_MINIUPNPC_H 1
-/* Define to 1 if you have the <miniupnpc/miniwget.h> header file. */
-#define HAVE_MINIUPNPC_MINIWGET_H 1
-
/* Define to 1 if you have the <miniupnpc/upnpcommands.h> header file. */
#define HAVE_MINIUPNPC_UPNPCOMMANDS_H 1
diff --git a/build_msvc/common.init.vcxproj b/build_msvc/common.init.vcxproj
index a3487c7a0d..f195d3d451 100644
--- a/build_msvc/common.init.vcxproj
+++ b/build_msvc/common.init.vcxproj
@@ -97,7 +97,7 @@
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<AdditionalOptions>/utf-8 /Zc:__cplusplus /std:c++17 %(AdditionalOptions)</AdditionalOptions>
- <DisableSpecificWarnings>4018;4221;4244;4267;4334;4715;4805;4834</DisableSpecificWarnings>
+ <DisableSpecificWarnings>4018;4244;4267;4334;4715;4805;4834</DisableSpecificWarnings>
<TreatWarningAsError>true</TreatWarningAsError>
<PreprocessorDefinitions>_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;_SILENCE_CXX17_OLD_ALLOCATOR_MEMBERS_DEPRECATION_WARNING;ZMQ_STATIC;NOMINMAX;WIN32;HAVE_CONFIG_H;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;_CONSOLE;_WIN32_WINNT=0x0601;_WIN32_IE=0x0501;WIN32_LEAN_AND_MEAN;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..\..\src;..\..\src\univalue\include;..\..\src\secp256k1\include;..\..\src\leveldb\include;..\..\src\leveldb\helpers\memenv;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
diff --git a/build_msvc/libleveldb/libleveldb.vcxproj b/build_msvc/libleveldb/libleveldb.vcxproj
index 1610ae7d86..009be30dec 100644
--- a/build_msvc/libleveldb/libleveldb.vcxproj
+++ b/build_msvc/libleveldb/libleveldb.vcxproj
@@ -51,7 +51,7 @@
<ItemDefinitionGroup>
<ClCompile>
<PreprocessorDefinitions>HAVE_CRC32C=0;HAVE_SNAPPY=0;__STDC_LIMIT_MACROS;LEVELDB_IS_BIG_ENDIAN=0;_UNICODE;UNICODE;_CRT_NONSTDC_NO_DEPRECATE;LEVELDB_PLATFORM_WINDOWS;LEVELDB_ATOMIC_PRESENT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <DisableSpecificWarnings>4244;4267;4312;4722;</DisableSpecificWarnings>
+ <DisableSpecificWarnings>4244;4267</DisableSpecificWarnings>
<AdditionalIncludeDirectories>..\..\src\leveldb;..\..\src\leveldb\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
diff --git a/build_msvc/test_bitcoin-qt/test_bitcoin-qt.vcxproj b/build_msvc/test_bitcoin-qt/test_bitcoin-qt.vcxproj
index 1ddd62edf2..1d2c86b7ac 100644
--- a/build_msvc/test_bitcoin-qt/test_bitcoin-qt.vcxproj
+++ b/build_msvc/test_bitcoin-qt/test_bitcoin-qt.vcxproj
@@ -11,7 +11,6 @@
<ClCompile Include="..\..\src\test\util\setup_common.cpp" />
<ClCompile Include="..\..\src\qt\test\addressbooktests.cpp" />
<ClCompile Include="..\..\src\qt\test\apptests.cpp" />
- <ClCompile Include="..\..\src\qt\test\compattests.cpp" />
<ClCompile Include="..\..\src\qt\test\rpcnestedtests.cpp" />
<ClCompile Include="..\..\src\qt\test\test_main.cpp" />
<ClCompile Include="..\..\src\qt\test\uritests.cpp" />
@@ -20,7 +19,6 @@
<ClCompile Include="..\..\src\wallet\test\wallet_test_fixture.cpp" />
<ClCompile Include="$(GeneratedFilesOutDir)\moc\moc_addressbooktests.cpp" />
<ClCompile Include="$(GeneratedFilesOutDir)\moc\moc_apptests.cpp" />
- <ClCompile Include="$(GeneratedFilesOutDir)\moc\moc_compattests.cpp" />
<ClCompile Include="$(GeneratedFilesOutDir)\moc\moc_rpcnestedtests.cpp" />
<ClCompile Include="$(GeneratedFilesOutDir)\moc\moc_uritests.cpp" />
<ClCompile Include="$(GeneratedFilesOutDir)\moc\moc_wallettests.cpp" />
@@ -89,7 +87,6 @@
<ItemGroup>
<MocTestFiles Include="..\..\src\qt\test\addressbooktests.h" />
<MocTestFiles Include="..\..\src\qt\test\apptests.h" />
- <MocTestFiles Include="..\..\src\qt\test\compattests.h" />
<MocTestFiles Include="..\..\src\qt\test\rpcnestedtests.h" />
<MocTestFiles Include="..\..\src\qt\test\uritests.h" />
<MocTestFiles Include="..\..\src\qt\test\wallettests.h" />
diff --git a/ci/test/00_setup_env.sh b/ci/test/00_setup_env.sh
index 87cf8538f6..e6aec723bc 100755
--- a/ci/test/00_setup_env.sh
+++ b/ci/test/00_setup_env.sh
@@ -11,6 +11,9 @@ export LC_ALL=C.UTF-8
# This is where the depends build is done.
BASE_ROOT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )"/../../ >/dev/null 2>&1 && pwd )
export BASE_ROOT_DIR
+# The depends dir.
+# This folder exists on the ci host and ci guest. Changes are propagated back and forth.
+export DEPENDS_DIR=${DEPENDS_DIR:-$BASE_ROOT_DIR/depends}
echo "Setting specific values in env"
if [ -n "${FILE_ENV}" ]; then
@@ -56,9 +59,6 @@ export CCACHE_COMPRESS=${CCACHE_COMPRESS:-1}
# The cache dir.
# This folder exists on the ci host and ci guest. Changes are propagated back and forth.
export CCACHE_DIR=${CCACHE_DIR:-$BASE_SCRATCH_DIR/.ccache}
-# The depends dir.
-# This folder exists on the ci host and ci guest. Changes are propagated back and forth.
-export DEPENDS_DIR=${DEPENDS_DIR:-$BASE_ROOT_DIR/depends}
# Folder where the build result is put (bin and lib).
export BASE_OUTDIR=${BASE_OUTDIR:-$BASE_SCRATCH_DIR/out/$HOST}
# Folder where the build is done (dist and out-of-tree build).
diff --git a/ci/test/00_setup_env_android.sh b/ci/test/00_setup_env_android.sh
new file mode 100644
index 0000000000..f78a84eeac
--- /dev/null
+++ b/ci/test/00_setup_env_android.sh
@@ -0,0 +1,25 @@
+#!/usr/bin/env bash
+#
+# Copyright (c) 2019-2020 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+export LC_ALL=C.UTF-8
+
+export HOST=aarch64-linux-android
+export PACKAGES="clang llvm unzip openjdk-8-jdk gradle"
+export CONTAINER_NAME=ci_android
+export DOCKER_NAME_TAG="ubuntu:focal"
+
+export RUN_UNIT_TESTS=false
+export RUN_FUNCTIONAL_TESTS=false
+
+export ANDROID_API_LEVEL=28
+export ANDROID_BUILD_TOOLS_VERSION=28.0.3
+export ANDROID_NDK_VERSION=21.1.6352462
+export ANDROID_TOOLS_URL=https://dl.google.com/android/repository/commandlinetools-linux-6609375_latest.zip
+export ANDROID_HOME="${DEPENDS_DIR}/SDKs/android"
+export ANDROID_NDK_HOME="${ANDROID_HOME}/ndk/${ANDROID_NDK_VERSION}"
+export DEP_OPTS="ANDROID_SDK=${ANDROID_HOME} ANDROID_NDK=${ANDROID_NDK_HOME} ANDROID_API_LEVEL=${ANDROID_API_LEVEL} ANDROID_TOOLCHAIN_BIN=${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/bin/"
+
+export BITCOIN_CONFIG="--disable-ccache"
diff --git a/ci/test/05_before_script.sh b/ci/test/05_before_script.sh
index f69afd8a26..8dd489d7f8 100755
--- a/ci/test/05_before_script.sh
+++ b/ci/test/05_before_script.sh
@@ -22,6 +22,15 @@ if [ -n "$XCODE_VERSION" ] && [ ! -f "$OSX_SDK_PATH" ]; then
DOCKER_EXEC curl --location --fail "${SDK_URL}/${OSX_SDK_BASENAME}" -o "$OSX_SDK_PATH"
fi
+if [ -n "$ANDROID_TOOLS_URL" ]; then
+ ANDROID_TOOLS_PATH=$DEPENDS_DIR/sdk-sources/android-tools.zip
+
+ DOCKER_EXEC curl --location --fail "${ANDROID_TOOLS_URL}" -o "$ANDROID_TOOLS_PATH"
+ DOCKER_EXEC mkdir -p "${ANDROID_HOME}/cmdline-tools"
+ DOCKER_EXEC unzip -o "$ANDROID_TOOLS_PATH" -d "${ANDROID_HOME}/cmdline-tools"
+ DOCKER_EXEC "yes | ${ANDROID_HOME}/cmdline-tools/tools/bin/sdkmanager --install \"build-tools;${ANDROID_BUILD_TOOLS_VERSION}\" \"platform-tools\" \"platforms;android-${ANDROID_API_LEVEL}\" \"ndk;${ANDROID_NDK_VERSION}\""
+fi
+
if [[ ${USE_MEMORY_SANITIZER} == "true" ]]; then
# Use BDB compiled using install_db4.sh script to work around linking issue when using BDB
# from depends. See https://github.com/bitcoin/bitcoin/pull/18288#discussion_r433189350 for
diff --git a/ci/test/06_script_a.sh b/ci/test/06_script_a.sh
index 7986f7665a..a42cd6cee1 100755
--- a/ci/test/06_script_a.sh
+++ b/ci/test/06_script_a.sh
@@ -6,6 +6,14 @@
export LC_ALL=C.UTF-8
+if [ -n "$ANDROID_TOOLS_URL" ]; then
+ DOCKER_EXEC make distclean || true
+ DOCKER_EXEC ./autogen.sh
+ DOCKER_EXEC ./configure $BITCOIN_CONFIG --prefix=$DEPENDS_DIR/aarch64-linux-android || ( (DOCKER_EXEC cat config.log) && false)
+ DOCKER_EXEC "cd src/qt && make $MAKEJOBS && ANDROID_HOME=${ANDROID_HOME} ANDROID_NDK_HOME=${ANDROID_NDK_HOME} make apk"
+ exit 0
+fi
+
BITCOIN_CONFIG_ALL="--enable-suppress-external-warnings --disable-dependency-tracking --prefix=$DEPENDS_DIR/$HOST --bindir=$BASE_OUTDIR/bin --libdir=$BASE_OUTDIR/lib"
if [ -z "$NO_WERROR" ]; then
BITCOIN_CONFIG_ALL="${BITCOIN_CONFIG_ALL} --enable-werror"
diff --git a/configure.ac b/configure.ac
index 0b176e6039..9ac2643374 100644
--- a/configure.ac
+++ b/configure.ac
@@ -734,6 +734,21 @@ case $host in
*android*)
dnl make sure android stays above linux for hosts like *linux-android*
TARGET_OS=android
+ case $host in
+ *x86_64*)
+ ANDROID_ARCH=x86_64
+ ;;
+ *aarch64*)
+ ANDROID_ARCH=arm64-v8a
+ ;;
+ *armv7a*)
+ ANDROID_ARCH=armeabi-v7a
+ ;;
+ *i686*)
+ ANDROID_ARCH=i686
+ ;;
+ *) AC_MSG_ERROR("Could not determine Android arch") ;;
+ esac
;;
*linux*)
TARGET_OS=linux
@@ -866,11 +881,16 @@ if test x$use_hardening != xno; then
dnl Use CHECK_LINK_FLAG & --fatal-warnings to ensure we won't use the flag in this case.
AX_CHECK_LINK_FLAG([-fcf-protection=full],[HARDENED_CXXFLAGS="$HARDENED_CXXFLAGS -fcf-protection=full"],, [[$LDFLAG_WERROR]])
- dnl stack-clash-protection does not work properly when building for Windows.
- dnl We use the test case from https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90458
- dnl to determine if it can be enabled.
- AX_CHECK_COMPILE_FLAG([-fstack-clash-protection],[HARDENED_CXXFLAGS="$HARDENED_CXXFLAGS -fstack-clash-protection"],[],["-O0"],
- [AC_LANG_SOURCE([[class D {public: unsigned char buf[32768];}; int main() {D d; return 0;}]])])
+ case $host in
+ *mingw*)
+ dnl stack-clash-protection doesn't currently work, and likely should just be skipped for Windows.
+ dnl See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90458 for more details.
+ ;;
+ *)
+ AX_CHECK_COMPILE_FLAG([-fstack-clash-protection],[HARDENED_CXXFLAGS="$HARDENED_CXXFLAGS -fstack-clash-protection"])
+ ;;
+ esac
+
dnl When enable_debug is yes, all optimizations are disabled.
dnl However, FORTIFY_SOURCE requires that there is some level of optimization, otherwise it does nothing and just creates a compiler warning.
@@ -1346,7 +1366,7 @@ fi
dnl Check for libminiupnpc (optional)
if test x$use_upnp != xno; then
AC_CHECK_HEADERS(
- [miniupnpc/miniwget.h miniupnpc/miniupnpc.h miniupnpc/upnpcommands.h miniupnpc/upnperrors.h],
+ [miniupnpc/miniupnpc.h miniupnpc/upnpcommands.h miniupnpc/upnperrors.h],
[AC_CHECK_LIB([miniupnpc], [upnpDiscover], [MINIUPNPC_LIBS=-lminiupnpc], [have_miniupnpc=no])],
[have_miniupnpc=no]
)
@@ -1844,6 +1864,7 @@ AC_SUBST(HAVE_BUILTIN_PREFETCH)
AC_SUBST(HAVE_MM_PREFETCH)
AC_SUBST(HAVE_STRONG_GETAUXVAL)
AC_SUBST(HAVE_WEAK_GETAUXVAL)
+AC_SUBST(ANDROID_ARCH)
AC_CONFIG_FILES([Makefile src/Makefile doc/man/Makefile share/setup.nsi share/qt/Info.plist test/config.ini])
AC_CONFIG_FILES([contrib/devtools/split-debug.sh],[chmod +x contrib/devtools/split-debug.sh])
AM_COND_IF([HAVE_DOXYGEN], [AC_CONFIG_FILES([doc/Doxyfile])])
diff --git a/contrib/devtools/README.md b/contrib/devtools/README.md
index bdff7a84b0..1fa850af1a 100644
--- a/contrib/devtools/README.md
+++ b/contrib/devtools/README.md
@@ -7,7 +7,8 @@ clang-format-diff.py
A script to format unified git diffs according to [.clang-format](../../src/.clang-format).
-Requires `clang-format`, installed e.g. via `brew install clang-format` on macOS.
+Requires `clang-format`, installed e.g. via `brew install clang-format` on macOS,
+or `sudo apt install clang-format` on Debian/Ubuntu.
For instance, to format the last commit with 0 lines of context,
the script should be called from the git root folder as follows.
diff --git a/contrib/devtools/test-security-check.py b/contrib/devtools/test-security-check.py
index ec2d886653..28b5f57489 100755
--- a/contrib/devtools/test-security-check.py
+++ b/contrib/devtools/test-security-check.py
@@ -5,6 +5,7 @@
'''
Test script for security-check.py
'''
+import os
import subprocess
import unittest
@@ -19,6 +20,10 @@ def write_testcode(filename):
}
''')
+def clean_files(source, executable):
+ os.remove(source)
+ os.remove(executable)
+
def call_security_check(cc, source, executable, options):
subprocess.run([cc,source,'-o',executable] + options, check=True)
p = subprocess.run(['./contrib/devtools/security-check.py',executable], stdout=subprocess.PIPE, universal_newlines=True)
@@ -44,6 +49,8 @@ class TestSecurityChecks(unittest.TestCase):
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-znoexecstack','-fstack-protector-all','-Wl,-zrelro','-Wl,-z,now','-pie','-fPIE', '-Wl,-z,separate-code']),
(0, ''))
+ clean_files(source, executable)
+
def test_PE(self):
source = 'test1.c'
executable = 'test1.exe'
@@ -61,6 +68,8 @@ class TestSecurityChecks(unittest.TestCase):
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,--nxcompat','-Wl,--dynamicbase','-Wl,--high-entropy-va','-pie','-fPIE']),
(0, ''))
+ clean_files(source, executable)
+
def test_MACHO(self):
source = 'test1.c'
executable = 'test1'
@@ -80,6 +89,8 @@ class TestSecurityChecks(unittest.TestCase):
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-pie','-Wl,-bind_at_load','-fstack-protector-all']),
(0, ''))
+ clean_files(source, executable)
+
if __name__ == '__main__':
unittest.main()
diff --git a/contrib/devtools/test-symbol-check.py b/contrib/devtools/test-symbol-check.py
index ee7bfc9805..106dfd2c5a 100755
--- a/contrib/devtools/test-symbol-check.py
+++ b/contrib/devtools/test-symbol-check.py
@@ -5,18 +5,17 @@
'''
Test script for symbol-check.py
'''
+import os
import subprocess
import unittest
def call_symbol_check(cc, source, executable, options):
subprocess.run([cc,source,'-o',executable] + options, check=True)
p = subprocess.run(['./contrib/devtools/symbol-check.py',executable], stdout=subprocess.PIPE, universal_newlines=True)
+ os.remove(source)
+ os.remove(executable)
return (p.returncode, p.stdout.rstrip())
-def get_machine(cc):
- p = subprocess.run([cc,'-dumpmachine'], stdout=subprocess.PIPE, universal_newlines=True)
- return p.stdout.rstrip()
-
class TestSymbolChecks(unittest.TestCase):
def test_ELF(self):
source = 'test1.c'
diff --git a/contrib/init/bitcoind.service b/contrib/init/bitcoind.service
index 5999928aa4..93de353bb4 100644
--- a/contrib/init/bitcoind.service
+++ b/contrib/init/bitcoind.service
@@ -18,7 +18,7 @@ After=network-online.target
Wants=network-online.target
[Service]
-ExecStart=/usr/bin/bitcoind -daemon \
+ExecStart=/usr/bin/bitcoind -daemonwait \
-pid=/run/bitcoind/bitcoind.pid \
-conf=/etc/bitcoin/bitcoin.conf \
-datadir=/var/lib/bitcoind
@@ -33,6 +33,7 @@ ExecStartPre=/bin/chgrp bitcoin /etc/bitcoin
Type=forking
PIDFile=/run/bitcoind/bitcoind.pid
Restart=on-failure
+TimeoutStartSec=infinity
TimeoutStopSec=600
# Directory creation and permissions
diff --git a/contrib/testgen/README.md b/contrib/testgen/README.md
index eaca473b40..fcc5a378e2 100644
--- a/contrib/testgen/README.md
+++ b/contrib/testgen/README.md
@@ -4,5 +4,5 @@ Utilities to generate test vectors for the data-driven Bitcoin tests.
Usage:
- PYTHONPATH=../../test/functional/test_framework ./gen_key_io_test_vectors.py valid 50 > ../../src/test/data/key_io_valid.json
- PYTHONPATH=../../test/functional/test_framework ./gen_key_io_test_vectors.py invalid 50 > ../../src/test/data/key_io_invalid.json
+ PYTHONPATH=../../test/functional/test_framework ./gen_key_io_test_vectors.py valid 70 > ../../src/test/data/key_io_valid.json
+ PYTHONPATH=../../test/functional/test_framework ./gen_key_io_test_vectors.py invalid 70 > ../../src/test/data/key_io_invalid.json
diff --git a/contrib/testgen/gen_key_io_test_vectors.py b/contrib/testgen/gen_key_io_test_vectors.py
index 8a3918da6b..74918cfb04 100755
--- a/contrib/testgen/gen_key_io_test_vectors.py
+++ b/contrib/testgen/gen_key_io_test_vectors.py
@@ -3,11 +3,11 @@
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
'''
-Generate valid and invalid base58 address and private key test vectors.
+Generate valid and invalid base58/bech32(m) address and private key test vectors.
Usage:
- PYTHONPATH=../../test/functional/test_framework ./gen_key_io_test_vectors.py valid 50 > ../../src/test/data/key_io_valid.json
- PYTHONPATH=../../test/functional/test_framework ./gen_key_io_test_vectors.py invalid 50 > ../../src/test/data/key_io_invalid.json
+ PYTHONPATH=../../test/functional/test_framework ./gen_key_io_test_vectors.py valid 70 > ../../src/test/data/key_io_valid.json
+ PYTHONPATH=../../test/functional/test_framework ./gen_key_io_test_vectors.py invalid 70 > ../../src/test/data/key_io_invalid.json
'''
# 2012 Wladimir J. van der Laan
# Released under MIT License
@@ -15,7 +15,7 @@ import os
from itertools import islice
from base58 import b58encode_chk, b58decode_chk, b58chars
import random
-from segwit_addr import bech32_encode, decode_segwit_address, convertbits, CHARSET
+from segwit_addr import bech32_encode, decode_segwit_address, convertbits, CHARSET, Encoding
# key types
PUBKEY_ADDRESS = 0
@@ -32,6 +32,7 @@ PRIVKEY_REGTEST = 239
OP_0 = 0x00
OP_1 = 0x51
OP_2 = 0x52
+OP_3 = 0x53
OP_16 = 0x60
OP_DUP = 0x76
OP_EQUAL = 0x87
@@ -44,6 +45,7 @@ script_prefix = (OP_HASH160, 20)
script_suffix = (OP_EQUAL,)
p2wpkh_prefix = (OP_0, 20)
p2wsh_prefix = (OP_0, 32)
+p2tr_prefix = (OP_1, 32)
metadata_keys = ['isPrivkey', 'chain', 'isCompressed', 'tryCaseFlip']
# templates for valid sequences
@@ -54,40 +56,58 @@ templates = [
((SCRIPT_ADDRESS,), 20, (), (False, 'main', None, None), script_prefix, script_suffix),
((PUBKEY_ADDRESS_TEST,), 20, (), (False, 'test', None, None), pubkey_prefix, pubkey_suffix),
((SCRIPT_ADDRESS_TEST,), 20, (), (False, 'test', None, None), script_prefix, script_suffix),
+ ((PUBKEY_ADDRESS_TEST,), 20, (), (False, 'signet', None, None), pubkey_prefix, pubkey_suffix),
+ ((SCRIPT_ADDRESS_TEST,), 20, (), (False, 'signet', None, None), script_prefix, script_suffix),
((PUBKEY_ADDRESS_REGTEST,), 20, (), (False, 'regtest', None, None), pubkey_prefix, pubkey_suffix),
((SCRIPT_ADDRESS_REGTEST,), 20, (), (False, 'regtest', None, None), script_prefix, script_suffix),
((PRIVKEY,), 32, (), (True, 'main', False, None), (), ()),
((PRIVKEY,), 32, (1,), (True, 'main', True, None), (), ()),
((PRIVKEY_TEST,), 32, (), (True, 'test', False, None), (), ()),
((PRIVKEY_TEST,), 32, (1,), (True, 'test', True, None), (), ()),
+ ((PRIVKEY_TEST,), 32, (), (True, 'signet', False, None), (), ()),
+ ((PRIVKEY_TEST,), 32, (1,), (True, 'signet', True, None), (), ()),
((PRIVKEY_REGTEST,), 32, (), (True, 'regtest', False, None), (), ()),
((PRIVKEY_REGTEST,), 32, (1,), (True, 'regtest', True, None), (), ())
]
# templates for valid bech32 sequences
bech32_templates = [
- # hrp, version, witprog_size, metadata, output_prefix
- ('bc', 0, 20, (False, 'main', None, True), p2wpkh_prefix),
- ('bc', 0, 32, (False, 'main', None, True), p2wsh_prefix),
- ('bc', 1, 2, (False, 'main', None, True), (OP_1, 2)),
- ('tb', 0, 20, (False, 'test', None, True), p2wpkh_prefix),
- ('tb', 0, 32, (False, 'test', None, True), p2wsh_prefix),
- ('tb', 2, 16, (False, 'test', None, True), (OP_2, 16)),
- ('bcrt', 0, 20, (False, 'regtest', None, True), p2wpkh_prefix),
- ('bcrt', 0, 32, (False, 'regtest', None, True), p2wsh_prefix),
- ('bcrt', 16, 40, (False, 'regtest', None, True), (OP_16, 40))
+ # hrp, version, witprog_size, metadata, encoding, output_prefix
+ ('bc', 0, 20, (False, 'main', None, True), Encoding.BECH32, p2wpkh_prefix),
+ ('bc', 0, 32, (False, 'main', None, True), Encoding.BECH32, p2wsh_prefix),
+ ('bc', 1, 32, (False, 'main', None, True), Encoding.BECH32M, p2tr_prefix),
+ ('bc', 2, 2, (False, 'main', None, True), Encoding.BECH32M, (OP_2, 2)),
+ ('tb', 0, 20, (False, 'test', None, True), Encoding.BECH32, p2wpkh_prefix),
+ ('tb', 0, 32, (False, 'test', None, True), Encoding.BECH32, p2wsh_prefix),
+ ('tb', 1, 32, (False, 'test', None, True), Encoding.BECH32M, p2tr_prefix),
+ ('tb', 3, 16, (False, 'test', None, True), Encoding.BECH32M, (OP_3, 16)),
+ ('tb', 0, 20, (False, 'signet', None, True), Encoding.BECH32, p2wpkh_prefix),
+ ('tb', 0, 32, (False, 'signet', None, True), Encoding.BECH32, p2wsh_prefix),
+ ('tb', 1, 32, (False, 'signet', None, True), Encoding.BECH32M, p2tr_prefix),
+ ('tb', 3, 32, (False, 'signet', None, True), Encoding.BECH32M, (OP_3, 32)),
+ ('bcrt', 0, 20, (False, 'regtest', None, True), Encoding.BECH32, p2wpkh_prefix),
+ ('bcrt', 0, 32, (False, 'regtest', None, True), Encoding.BECH32, p2wsh_prefix),
+ ('bcrt', 1, 32, (False, 'regtest', None, True), Encoding.BECH32M, p2tr_prefix),
+ ('bcrt', 16, 40, (False, 'regtest', None, True), Encoding.BECH32M, (OP_16, 40))
]
# templates for invalid bech32 sequences
bech32_ng_templates = [
- # hrp, version, witprog_size, invalid_bech32, invalid_checksum, invalid_char
- ('tc', 0, 20, False, False, False),
- ('tb', 17, 32, False, False, False),
- ('bcrt', 3, 1, False, False, False),
- ('bc', 15, 41, False, False, False),
- ('tb', 0, 16, False, False, False),
- ('bcrt', 0, 32, True, False, False),
- ('bc', 0, 16, True, False, False),
- ('tb', 0, 32, False, True, False),
- ('bcrt', 0, 20, False, False, True)
+ # hrp, version, witprog_size, encoding, invalid_bech32, invalid_checksum, invalid_char
+ ('tc', 0, 20, Encoding.BECH32, False, False, False),
+ ('bt', 1, 32, Encoding.BECH32M, False, False, False),
+ ('tb', 17, 32, Encoding.BECH32M, False, False, False),
+ ('bcrt', 3, 1, Encoding.BECH32M, False, False, False),
+ ('bc', 15, 41, Encoding.BECH32M, False, False, False),
+ ('tb', 0, 16, Encoding.BECH32, False, False, False),
+ ('bcrt', 0, 32, Encoding.BECH32, True, False, False),
+ ('bc', 0, 16, Encoding.BECH32, True, False, False),
+ ('tb', 0, 32, Encoding.BECH32, False, True, False),
+ ('bcrt', 0, 20, Encoding.BECH32, False, False, True),
+ ('bc', 0, 20, Encoding.BECH32M, False, False, False),
+ ('tb', 0, 32, Encoding.BECH32M, False, False, False),
+ ('bcrt', 0, 20, Encoding.BECH32M, False, False, False),
+ ('bc', 1, 32, Encoding.BECH32, False, False, False),
+ ('tb', 2, 16, Encoding.BECH32, False, False, False),
+ ('bcrt', 16, 20, Encoding.BECH32, False, False, False),
]
def is_valid(v):
@@ -127,8 +147,9 @@ def gen_valid_bech32_vector(template):
hrp = template[0]
witver = template[1]
witprog = bytearray(os.urandom(template[2]))
- dst_prefix = bytearray(template[4])
- rv = bech32_encode(hrp, [witver] + convertbits(witprog, 8, 5))
+ encoding = template[4]
+ dst_prefix = bytearray(template[5])
+ rv = bech32_encode(encoding, hrp, [witver] + convertbits(witprog, 8, 5))
return rv, dst_prefix + witprog
def gen_valid_vectors():
@@ -186,22 +207,23 @@ def gen_invalid_bech32_vector(template):
hrp = template[0]
witver = template[1]
witprog = bytearray(os.urandom(template[2]))
+ encoding = template[3]
if no_data:
- rv = bech32_encode(hrp, [])
+ rv = bech32_encode(encoding, hrp, [])
else:
data = [witver] + convertbits(witprog, 8, 5)
- if template[3] and not no_data:
+ if template[4] and not no_data:
if template[2] % 5 in {2, 4}:
data[-1] |= 1
else:
data.append(0)
- rv = bech32_encode(hrp, data)
+ rv = bech32_encode(encoding, hrp, data)
- if template[4]:
+ if template[5]:
i = len(rv) - random.randrange(1, 7)
rv = rv[:i] + random.choice(CHARSET.replace(rv[i], '')) + rv[i + 1:]
- if template[5]:
+ if template[6]:
i = len(hrp) + 1 + random.randrange(0, len(rv) - len(hrp) - 4)
rv = rv[:i] + rv[i:i + 4].upper() + rv[i + 4:]
diff --git a/depends/packages/libxkbcommon.mk b/depends/packages/libxkbcommon.mk
index cdd5af194b..8c6c56545f 100644
--- a/depends/packages/libxkbcommon.mk
+++ b/depends/packages/libxkbcommon.mk
@@ -27,6 +27,6 @@ define $(package)_stage_cmds
endef
define $(package)_postprocess_cmds
- rm -rf share/man share/doc lib/*.la
+ rm lib/*.la
endef
diff --git a/depends/packages/miniupnpc.mk b/depends/packages/miniupnpc.mk
index 49a584e462..99f5b0a8db 100644
--- a/depends/packages/miniupnpc.mk
+++ b/depends/packages/miniupnpc.mk
@@ -1,9 +1,9 @@
package=miniupnpc
-$(package)_version=2.0.20180203
+$(package)_version=2.2.2
$(package)_download_path=https://miniupnp.tuxfamily.org/files/
$(package)_file_name=$(package)-$($(package)_version).tar.gz
-$(package)_sha256_hash=90dda8c7563ca6cd4a83e23b3c66dbbea89603a1675bfdb852897c2c9cc220b7
-$(package)_patches=dont_use_wingen.patch
+$(package)_sha256_hash=888fb0976ba61518276fe1eda988589c700a3f2a69d71089260d75562afd3687
+$(package)_patches=dont_leak_info.patch
define $(package)_set_vars
$(package)_build_opts=CC="$($(package)_cc)"
@@ -13,9 +13,7 @@ $(package)_build_env+=CFLAGS="$($(package)_cflags) $($(package)_cppflags)" AR="$
endef
define $(package)_preprocess_cmds
- mkdir dll && \
- sed -e 's|MINIUPNPC_VERSION_STRING \"version\"|MINIUPNPC_VERSION_STRING \"$($(package)_version)\"|' -e 's|OS/version|$(host)|' miniupnpcstrings.h.in > miniupnpcstrings.h && \
- patch -p1 < $($(package)_patch_dir)/dont_use_wingen.patch
+ patch -p1 < $($(package)_patch_dir)/dont_leak_info.patch
endef
define $(package)_build_cmds
diff --git a/depends/packages/qt.mk b/depends/packages/qt.mk
index 0ac6f496c4..ee6796e2ad 100644
--- a/depends/packages/qt.mk
+++ b/depends/packages/qt.mk
@@ -9,7 +9,8 @@ $(package)_qt_libs=corelib network widgets gui plugins testlib
$(package)_patches=fix_qt_pkgconfig.patch mac-qmake.conf fix_no_printer.patch no-xlib.patch
$(package)_patches+= fix_android_qmake_conf.patch fix_android_jni_static.patch dont_hardcode_pwd.patch
$(package)_patches+= drop_lrelease_dependency.patch no_sdk_version_check.patch
-$(package)_patches+= fix_qpainter_non_determinism.patch fix_lib_paths.patch
+$(package)_patches+= fix_qpainter_non_determinism.patch fix_lib_paths.patch fix_android_pch.patch
+$(package)_patches+= fix_bigsur_drawing.patch
$(package)_qttranslations_file_name=qttranslations-$($(package)_suffix)
$(package)_qttranslations_sha256_hash=e1de58ed108b7e0a138815ea60fd46a2c4e1fc31396a707e5630e92de79c53de
@@ -111,6 +112,7 @@ $(package)_config_opts += -no-feature-xml
$(package)_config_opts_darwin = -no-dbus
$(package)_config_opts_darwin += -no-opengl
$(package)_config_opts_darwin += -pch
+$(package)_config_opts_darwin += -no-feature-corewlan
$(package)_config_opts_darwin += -device-option QMAKE_MACOSX_DEPLOYMENT_TARGET=$(OSX_MIN_VERSION)
ifneq ($(build_os),darwin)
@@ -164,6 +166,7 @@ $(package)_config_opts_android += -no-fontconfig
$(package)_config_opts_android += -L $(host_prefix)/lib
$(package)_config_opts_android += -I $(host_prefix)/include
$(package)_config_opts_android += -pch
+$(package)_config_opts_android += -no-feature-vulkan
$(package)_config_opts_aarch64_android += -android-arch arm64-v8a
$(package)_config_opts_armv7a_android += -android-arch armeabi-v7a
@@ -223,10 +226,12 @@ define $(package)_preprocess_cmds
patch -p1 -i $($(package)_patch_dir)/fix_no_printer.patch && \
patch -p1 -i $($(package)_patch_dir)/fix_android_qmake_conf.patch && \
patch -p1 -i $($(package)_patch_dir)/fix_android_jni_static.patch && \
+ patch -p1 -i $($(package)_patch_dir)/fix_android_pch.patch && \
patch -p1 -i $($(package)_patch_dir)/no-xlib.patch && \
patch -p1 -i $($(package)_patch_dir)/fix_qpainter_non_determinism.patch &&\
patch -p1 -i $($(package)_patch_dir)/no_sdk_version_check.patch && \
patch -p1 -i $($(package)_patch_dir)/fix_lib_paths.patch && \
+ patch -p1 -i $($(package)_patch_dir)/fix_bigsur_drawing.patch && \
sed -i.old "s|updateqm.commands = \$$$$\$$$$LRELEASE|updateqm.commands = $($(package)_extract_dir)/qttools/bin/lrelease|" qttranslations/translations/translations.pro && \
mkdir -p qtbase/mkspecs/macx-clang-linux &&\
cp -f qtbase/mkspecs/macx-clang/qplatformdefs.h qtbase/mkspecs/macx-clang-linux/ &&\
diff --git a/depends/patches/miniupnpc/dont_leak_info.patch b/depends/patches/miniupnpc/dont_leak_info.patch
new file mode 100644
index 0000000000..512f9c50ea
--- /dev/null
+++ b/depends/patches/miniupnpc/dont_leak_info.patch
@@ -0,0 +1,32 @@
+commit 8815452257437ba36607d0e2381c01142d1c7bb0
+Author: fanquake <fanquake@gmail.com>
+Date: Thu Nov 19 10:51:19 2020 +0800
+
+ Don't leak OS and miniupnpc version info in User-Agent
+
+diff --git a//minisoap.c b/minisoap.c
+index 7860667..775580b 100644
+--- a/minisoap.c
++++ b/minisoap.c
+@@ -90,7 +90,7 @@ int soapPostSubmit(SOCKET fd,
+ headerssize = snprintf(headerbuf, sizeof(headerbuf),
+ "POST %s HTTP/%s\r\n"
+ "Host: %s%s\r\n"
+- "User-Agent: " OS_STRING ", " UPNP_VERSION_STRING ", MiniUPnPc/" MINIUPNPC_VERSION_STRING "\r\n"
++ "User-Agent: " UPNP_VERSION_STRING "\r\n"
+ "Content-Length: %d\r\n"
+ "Content-Type: text/xml\r\n"
+ "SOAPAction: \"%s\"\r\n"
+diff --git a/miniwget.c b/miniwget.c
+index d5b7970..05aeb9c 100644
+--- a/miniwget.c
++++ b/miniwget.c
+@@ -444,7 +444,7 @@ miniwget3(const char * host,
+ "GET %s HTTP/%s\r\n"
+ "Host: %s:%d\r\n"
+ "Connection: Close\r\n"
+- "User-Agent: " OS_STRING ", " UPNP_VERSION_STRING ", MiniUPnPc/" MINIUPNPC_VERSION_STRING "\r\n"
++ "User-Agent: " UPNP_VERSION_STRING "\r\n"
+
+ "\r\n",
+ path, httpversion, host, port);
diff --git a/depends/patches/miniupnpc/dont_use_wingen.patch b/depends/patches/miniupnpc/dont_use_wingen.patch
deleted file mode 100644
index a1cc9b50d1..0000000000
--- a/depends/patches/miniupnpc/dont_use_wingen.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-commit e8077044df239bcf0d9e9980b0e1afb9f1f5c446
-Author: fanquake <fanquake@gmail.com>
-Date: Tue Aug 18 20:50:19 2020 +0800
-
- Don't use wingenminiupnpcstrings when generating miniupnpcstrings.h
-
- The wingenminiupnpcstrings tool is used on Windows to generate version
- information. This information is irrelevant for us, and trying to use
- wingenminiupnpcstrings would cause builds to fail, so just don't use it.
-
- We should be able to drop this once we are using 2.1 or later. See
- upstream commit: 9663c55c61408fdcc39a82987d2243f816b22932.
-
-diff --git a/Makefile.mingw b/Makefile.mingw
-index 574720e..fcc17bb 100644
---- a/Makefile.mingw
-+++ b/Makefile.mingw
-@@ -74,7 +74,7 @@ wingenminiupnpcstrings: wingenminiupnpcstrings.o
-
- wingenminiupnpcstrings.o: wingenminiupnpcstrings.c
-
--miniupnpcstrings.h: miniupnpcstrings.h.in wingenminiupnpcstrings
-+miniupnpcstrings.h: miniupnpcstrings.h.in
- wingenminiupnpcstrings $< $@
-
- minixml.o: minixml.c minixml.h
diff --git a/depends/patches/qt/fix_android_pch.patch b/depends/patches/qt/fix_android_pch.patch
new file mode 100644
index 0000000000..bed6e4bb63
--- /dev/null
+++ b/depends/patches/qt/fix_android_pch.patch
@@ -0,0 +1,10 @@
+--- old/qtbase/mkspecs/common/android-base-head.conf
++++ new/qtbase/mkspecs/common/android-base-head.conf
+@@ -73,6 +73,6 @@ CROSS_COMPILE = $$NDK_TOOLCHAIN_PATH/bin/$$NDK_TOOLS_PREFIX-
+ QMAKE_PCH_OUTPUT_EXT = .gch
+
+ QMAKE_CFLAGS_PRECOMPILE = -x c-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT}
+-QMAKE_CFLAGS_USE_PRECOMPILE = -include ${QMAKE_PCH_OUTPUT_BASE}
++QMAKE_CFLAGS_USE_PRECOMPILE = -include-pch ${QMAKE_PCH_OUTPUT}
+ QMAKE_CXXFLAGS_PRECOMPILE = -x c++-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT}
+ QMAKE_CXXFLAGS_USE_PRECOMPILE = $$QMAKE_CFLAGS_USE_PRECOMPILE
diff --git a/depends/patches/qt/fix_bigsur_drawing.patch b/depends/patches/qt/fix_bigsur_drawing.patch
new file mode 100644
index 0000000000..98c0c6be30
--- /dev/null
+++ b/depends/patches/qt/fix_bigsur_drawing.patch
@@ -0,0 +1,31 @@
+Fix GUI stuck on Big Sur
+
+See:
+ - https://github.com/bitcoin-core/gui/issues/249
+ - https://github.com/bitcoin/bitcoin/pull/21495
+ - https://bugreports.qt.io/browse/QTBUG-87014
+
+We should be able to drop this once we are using one of the following versions:
+ - Qt 5.12.11 or later, see upstream commit: c5d904639dbd690a36306e2b455610029704d821
+ - Qt 5.15.3 or later, see upstream commit: 2cae34354bd41ae286258c7a6b3653b746e786ae
+
+--- a/qtbase/src/plugins/platforms/cocoa/qnsview_drawing.mm
++++ b/qtbase/src/plugins/platforms/cocoa/qnsview_drawing.mm
+@@ -95,8 +95,15 @@
+ // by AppKit at a point where we've already set up other parts of the platform plugin
+ // based on the presence of layers or not. Once we've rewritten these parts to support
+ // dynamically picking up layer enablement we can let AppKit do its thing.
+- return QMacVersion::buildSDK() >= QOperatingSystemVersion::MacOSMojave
+- && QMacVersion::currentRuntime() >= QOperatingSystemVersion::MacOSMojave;
++
++ if (QMacVersion::currentRuntime() >= QOperatingSystemVersion::MacOSBigSur)
++ return true; // Big Sur always enables layer-backing, regardless of SDK
++
++ if (QMacVersion::currentRuntime() >= QOperatingSystemVersion::MacOSMojave
++ && QMacVersion::buildSDK() >= QOperatingSystemVersion::MacOSMojave)
++ return true; // Mojave and Catalina enable layers based on the app's SDK
++
++ return false; // Prior versions needed explicitly enabled layer backing
+ }
+
+ - (BOOL)layerExplicitlyRequested
diff --git a/doc/README.md b/doc/README.md
index 19d8204d83..f32600d009 100644
--- a/doc/README.md
+++ b/doc/README.md
@@ -44,6 +44,7 @@ The following are developer notes on how to build Bitcoin Core on your native pl
- [FreeBSD Build Notes](build-freebsd.md)
- [OpenBSD Build Notes](build-openbsd.md)
- [NetBSD Build Notes](build-netbsd.md)
+- [Android Build Notes](build-android.md)
- [Gitian Building Guide (External Link)](https://github.com/bitcoin-core/docs/blob/master/gitian-building.md)
Development
diff --git a/doc/REST-interface.md b/doc/REST-interface.md
index ea06952af4..8b281acca7 100644
--- a/doc/REST-interface.md
+++ b/doc/REST-interface.md
@@ -95,11 +95,8 @@ $ curl localhost:18332/rest/getutxos/checkmempool/b2cdfd7b89def827ff8af7cd9bff76
"scriptPubKey" : {
"asm" : "OP_DUP OP_HASH160 1c7cebb529b86a04c683dfa87be49de35bcf589e OP_EQUALVERIFY OP_CHECKSIG",
"hex" : "76a9141c7cebb529b86a04c683dfa87be49de35bcf589e88ac",
- "reqSigs" : 1,
"type" : "pubkeyhash",
- "addresses" : [
- "mi7as51dvLJsizWnTMurtRmrP8hG2m1XvD"
- ]
+ "address" : "mi7as51dvLJsizWnTMurtRmrP8hG2m1XvD"
}
}
]
diff --git a/doc/bips.md b/doc/bips.md
index a5e9a6c020..f72dbead9d 100644
--- a/doc/bips.md
+++ b/doc/bips.md
@@ -1,4 +1,4 @@
-BIPs that are implemented by Bitcoin Core (up-to-date up to **v0.21.0**):
+BIPs that are implemented by Bitcoin Core (up-to-date up to **v22.0**):
* [`BIP 9`](https://github.com/bitcoin/bips/blob/master/bip-0009.mediawiki): The changes allowing multiple soft-forks to be deployed in parallel have been implemented since **v0.12.1** ([PR #7575](https://github.com/bitcoin/bitcoin/pull/7575))
* [`BIP 11`](https://github.com/bitcoin/bips/blob/master/bip-0011.mediawiki): Multisig outputs are standard since **v0.6.0** ([PR #669](https://github.com/bitcoin/bitcoin/pull/669)).
@@ -50,3 +50,4 @@ BIPs that are implemented by Bitcoin Core (up-to-date up to **v0.21.0**):
* [`BIP 325`](https://github.com/bitcoin/bips/blob/master/bip-0325.mediawiki): Signet test network is supported as of **v0.21.0** ([PR 18267](https://github.com/bitcoin/bitcoin/pull/18267)).
* [`BIP 339`](https://github.com/bitcoin/bips/blob/master/bip-0339.mediawiki): Relay of transactions by wtxid is supported as of **v0.21.0** ([PR 18044](https://github.com/bitcoin/bitcoin/pull/18044)).
* [`BIP 340`](https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki) [`341`](https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki) [`342`](https://github.com/bitcoin/bips/blob/master/bip-0342.mediawiki): Validation rules for Taproot (including Schnorr signatures and Tapscript leaves) are implemented as of **v0.21.0** ([PR 19953](https://github.com/bitcoin/bitcoin/pull/19953)), without mainnet activation.
+* [`BIP 350`](https://github.com/bitcoin/bips/blob/master/bip-0350.mediawiki): Addresses for native v1+ segregated Witness outputs use Bech32m instead of Bech32 as of **v22.0** ([PR 20861](https://github.com/bitcoin/bitcoin/pull/20861)).
diff --git a/doc/build-android.md b/doc/build-android.md
new file mode 100644
index 0000000000..7a8a9e6a65
--- /dev/null
+++ b/doc/build-android.md
@@ -0,0 +1,12 @@
+ANDROID BUILD NOTES
+======================
+
+This guide describes how to build and package the `bitcoin-qt` GUI for Android on Linux and macOS.
+
+## Preparation
+
+You will need to get the Android NDK and build dependencies for Android as described in [depends/README.md](../depends/README.md).
+
+## Building and packaging
+
+After the depends are built configure with one of the resulting prefixes and run `make && make apk` in `src/qt`. \ No newline at end of file
diff --git a/doc/build-osx.md b/doc/build-osx.md
index 52a734c80a..16c6da66d5 100644
--- a/doc/build-osx.md
+++ b/doc/build-osx.md
@@ -1,116 +1,303 @@
-# macOS Build Instructions and Notes
+# macOS Build Guide
+
+**Updated for MacOS [11.2](https://www.apple.com/macos/big-sur/)**
+
+This guide describes how to build bitcoind, command-line utilities, and GUI on macOS
+
+**Note:** The following is for Intel Macs only!
+
+## Dependencies
+
+The following dependencies are **required**:
+
+Library | Purpose | Description
+-----------------------------------------------------------|------------|----------------------
+[automake](https://formulae.brew.sh/formula/automake) | Build | Generate makefile
+[libtool](https://formulae.brew.sh/formula/libtool) | Build | Shared library support
+[pkg-config](https://formulae.brew.sh/formula/pkg-config) | Build | Configure compiler and linker flags
+[boost](https://formulae.brew.sh/formula/boost) | Utility | Library for threading, data structures, etc
+[libevent](https://formulae.brew.sh/formula/libevent) | Networking | OS independent asynchronous networking
+
+The following dependencies are **optional**:
+
+Library | Purpose | Description
+--------------------------------------------------------------- |------------------|----------------------
+[berkeley-db@4](https://formulae.brew.sh/formula/berkeley-db@4) | Berkeley DB | Wallet storage (only needed when wallet enabled)
+[qt@5](https://formulae.brew.sh/formula/qt@5) | GUI | GUI toolkit (only needed when GUI enabled)
+[qrencode](https://formulae.brew.sh/formula/qrencode) | QR codes in GUI | Generating QR codes (only needed when GUI enabled)
+[zeromq](https://formulae.brew.sh/formula/zeromq) | ZMQ notification | Allows generating ZMQ notifications (requires ZMQ version >= 4.0.0)
+[sqlite](https://formulae.brew.sh/formula/sqlite) | SQLite DB | Wallet storage (only needed when wallet enabled)
+[miniupnpc](https://formulae.brew.sh/formula/miniupnpc) | UPnP Support | Firewall-jumping support (needed for port mapping support)
+[libnatpmp](https://formulae.brew.sh/formula/libnatpmp) | NAT-PMP Support | Firewall-jumping support (needed for port mapping support)
+[python3](https://formulae.brew.sh/formula/python@3.9) | Testing | Python Interpreter (only needed when running the test suite)
+
+The following dependencies are **optional** packages required for deploying:
+
+Library | Purpose | Description
+----------------------------------------------------|------------------|----------------------
+[librsvg](https://formulae.brew.sh/formula/librsvg) | Deploy Dependency| Library to render SVG files
+[ds_store](https://pypi.org/project/ds-store/) | Deploy Dependency| Examine and modify .DS_Store files
+[mac_alias](https://pypi.org/project/mac-alias/) | Deploy Dependency| Generate/Read binary alias and bookmark records
+
+See [dependencies.md](dependencies.md) for a complete overview.
+
+## Preparation
The commands in this guide should be executed in a Terminal application.
-The built-in one is located in
+macOS comes with a built-in Terminal located in:
+
```
/Applications/Utilities/Terminal.app
```
-## Preparation
-Install the macOS command line tools:
+### 1. Xcode Command Line Tools
-```shell
+The Xcode Command Line Tools are a collection of build tools for macOS.
+These tools must be installed in order to build Bitcoin Core from source.
+
+To install, run the following command from your terminal:
+
+``` bash
xcode-select --install
```
-When the popup appears, click `Install`.
+Upon running the command, you should see a popup appear.
+Click on `Install` to continue the installation process.
-Then install [Homebrew](https://brew.sh).
+### 2. Homebrew Package Manager
-## Dependencies
-```shell
-brew install automake libtool boost miniupnpc libnatpmp pkg-config python qt@5 libevent qrencode
+Homebrew is a package manager for macOS that allows one to install packages from the command line easily.
+While several package managers are available for macOS, this guide will focus on Homebrew as it is the most popular.
+Since the examples in this guide which walk through the installation of a package will use Homebrew, it is recommended that you install it to follow along.
+Otherwise, you can adapt the commands to your package manager of choice.
+
+To install the Homebrew package manager, see: https://brew.sh
+
+Note: If you run into issues while installing Homebrew or pulling packages, refer to [Homebrew's troubleshooting page](https://docs.brew.sh/Troubleshooting).
+
+### 3. Install Required Dependencies
+
+The first step is to download the required dependencies.
+These dependencies represent the packages required to get a barebones installation up and running.
+To install, run the following from your terminal:
+
+``` bash
+brew install automake libtool boost pkg-config libevent
```
-If you run into issues, check [Homebrew's troubleshooting page](https://docs.brew.sh/Troubleshooting).
-See [dependencies.md](dependencies.md) for a complete overview.
+### 4. Clone Bitcoin repository
-If you want to build the disk image with `make deploy` (.dmg / optional), you need RSVG:
-```shell
-brew install librsvg
+`git` should already be installed by default on your system.
+Now that all the required dependencies are installed, let's clone the Bitcoin Core repository to a directory.
+All build scripts and commands will run from this directory.
+
+``` bash
+git clone https://github.com/bitcoin/bitcoin.git
```
-and [`macdeployqtplus`](../contrib/macdeploy/README.md) dependencies:
-```shell
-pip3 install ds_store mac_alias
+### 5. Install Optional Dependencies
+
+#### Wallet Dependencies
+
+It is not necessary to build wallet functionality to run `bitcoind` or `bitcoin-qt`.
+To enable legacy wallets, you must install `berkeley-db@4`.
+To enable [descriptor wallets](https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md), `sqlite` is required.
+Skip `berkeley-db@4` if you intend to *exclusively* use descriptor wallets.
+
+###### Legacy Wallet Support
+
+`berkeley-db@4` is required to enable support for legacy wallets.
+Skip if you don't intend to use legacy wallets.
+
+``` bash
+brew install berkeley-db@4
```
-The wallet support requires one or both of the dependencies ([*SQLite*](#sqlite) and [*Berkeley DB*](#berkeley-db)) in the sections below.
-To build Bitcoin Core without wallet, see [*Disable-wallet mode*](#disable-wallet-mode).
+###### Descriptor Wallet Support
-#### SQLite
+Note: Apple has included a useable `sqlite` package since macOS 10.14.
+You may not need to install this package.
-Usually, macOS installation already has a suitable SQLite installation.
-Also, the Homebrew package could be installed:
+`sqlite` is required to enable support for descriptor wallets.
+Skip if you don't intend to use descriptor wallets.
-```shell
+``` bash
brew install sqlite
```
+---
-In that case the Homebrew package will prevail.
+#### GUI Dependencies
-#### Berkeley DB
+###### Qt
-It is recommended to use Berkeley DB 4.8. If you have to build it yourself,
-you can use [this](/contrib/install_db4.sh) script to install it
-like so:
+Bitcoin Core includes a GUI built with the cross-platform Qt Framework.
+To compile the GUI, we need to install `qt@5`.
+Skip if you don't intend to use the GUI.
-```shell
-./contrib/install_db4.sh .
+``` bash
+brew install qt@5
```
-from the root of the repository.
+Note: Building with Qt binaries downloaded from the Qt website is not officially supported.
+See the notes in [#7714](https://github.com/bitcoin/bitcoin/issues/7714).
-Also, the Homebrew package could be installed:
+###### qrencode
-```shell
-brew install berkeley-db4
+The GUI can encode addresses in a QR Code. To build in QR support for the GUI, install `qrencode`.
+Skip if not using the GUI or don't want QR code functionality.
+
+``` bash
+brew install qrencode
```
+---
+
+#### Port Mapping Dependencies
+
+###### miniupnpc
-## Build Bitcoin Core
+miniupnpc may be used for UPnP port mapping.
+Skip if you do not need this functionality.
-1. Clone the Bitcoin Core source code:
- ```shell
- git clone https://github.com/bitcoin/bitcoin
- cd bitcoin
- ```
+``` bash
+brew install miniupnpc
+```
-2. Build Bitcoin Core:
+###### libnatpmp
- Configure and build the headless Bitcoin Core binaries as well as the GUI (if Qt is found).
+libnatpmp may be used for NAT-PMP port mapping.
+Skip if you do not need this functionality.
- You can disable the GUI build by passing `--without-gui` to configure.
- ```shell
- ./autogen.sh
- ./configure
- make
- ```
+``` bash
+brew install libnatpmp
+```
-3. It is recommended to build and run the unit tests:
- ```shell
- make check
- ```
+Note: UPnP and NAT-PMP support will be compiled in and disabled by default.
+Check out the [further configuration](#further-configuration) section for more information.
-4. You can also create a `.dmg` that contains the `.app` bundle (optional):
- ```shell
- make deploy
- ```
+---
-## Disable-wallet mode
-When the intention is to run only a P2P node without a wallet, Bitcoin Core may be
-compiled in disable-wallet mode with:
-```shell
-./configure --disable-wallet
+#### ZMQ Dependencies
+
+Support for ZMQ notifications requires the following dependency.
+Skip if you do not need ZMQ functionality.
+
+``` bash
+brew install zeromq
```
-In this case there is no dependency on [*Berkeley DB*](#berkeley-db) and [*SQLite*](#sqlite).
+ZMQ is automatically compiled in and enabled if the dependency is detected.
+Check out the [further configuration](#further-configuration) section for more information.
+
+For more information on ZMQ, see: [zmq.md](zmq.md)
-Mining is also possible in disable-wallet mode using the `getblocktemplate` RPC call.
+---
-## Running
-Bitcoin Core is now available at `./src/bitcoind`
+#### Test Suite Dependencies
+
+There is an included test suite that is useful for testing code changes when developing.
+To run the test suite (recommended), you will need to have Python 3 installed:
+
+``` bash
+brew install python
+```
+
+---
+
+#### Deploy Dependencies
+
+You can deploy a `.dmg` containing the Bitcoin Core application using `make deploy`.
+This command depends on a couple of python packages, so it is required that you have `python` installed.
+
+Ensuring that `python` is installed, you can install the deploy dependencies by running the following commands in your terminal:
+
+``` bash
+brew install librsvg
+```
+
+``` bash
+pip3 install ds_store mac_alias
+```
+
+## Building Bitcoin Core
+
+### 1. Configuration
+
+There are many ways to configure Bitcoin Core, here are a few common examples:
+
+##### Wallet (BDB + SQlite) Support, No GUI:
+
+If `berkeley-db@4` is installed, then legacy wallet support will be built.
+If `berkeley-db@4` is not installed, then this will throw an error.
+If `sqlite` is installed, then descriptor wallet support will also be built.
+Additionally, this explicitly disables the GUI.
+
+``` bash
+./autogen.sh
+./configure --with-gui=no
+```
+
+##### Wallet (only SQlite) and GUI Support:
+
+This explicitly enables the GUI and disables legacy wallet support.
+If `qt` is not installed, this will throw an error.
+If `sqlite` is installed then descriptor wallet functionality will be built.
+If `sqlite` is not installed, then wallet functionality will be disabled.
+
+``` bash
+./autogen.sh
+./configure --without-bdb --with-gui=yes
+```
+
+##### No Wallet or GUI
+
+``` bash
+./autogen.sh
+./configure --without-wallet --with-gui=no
+```
+
+##### Further Configuration
+
+You may want to dig deeper into the configuration options to achieve your desired behavior.
+Examine the output of the following command for a full list of configuration options:
+
+``` bash
+./configure -help
+```
+
+### 2. Compile
+
+After configuration, you are ready to compile.
+Run the following in your terminal to compile Bitcoin Core:
+
+``` bash
+make -jx # use -jX here for parallelism
+make check # Run tests if Python 3 is available
+```
+
+### 3. Deploy (optional)
+
+You can also create a `.dmg` containing the `.app` bundle by running the following command:
+
+``` bash
+make deploy
+```
+
+## Running Bitcoin Core
+
+Bitcoin Core should now be available at `./src/bitcoind`.
+If you compiled support for the GUI, it should be available at `./src/qt/bitcoin-qt`.
+
+The first time you run `bitcoind` or `bitcoin-qt`, it will start downloading the blockchain.
+This process could take many hours, or even days on slower than average systems.
+
+By default, blockchain and wallet data files will be stored in:
+
+``` bash
+/Users/${USER}/Library/Application Support/Bitcoin/
+```
Before running, you may create an empty configuration file:
+
```shell
mkdir -p "/Users/${USER}/Library/Application Support/Bitcoin"
@@ -119,22 +306,17 @@ touch "/Users/${USER}/Library/Application Support/Bitcoin/bitcoin.conf"
chmod 600 "/Users/${USER}/Library/Application Support/Bitcoin/bitcoin.conf"
```
-The first time you run bitcoind, it will start downloading the blockchain. This process could
-take many hours, or even days on slower than average systems.
-
You can monitor the download process by looking at the debug.log file:
+
```shell
tail -f $HOME/Library/Application\ Support/Bitcoin/debug.log
```
## Other commands:
+
```shell
./src/bitcoind -daemon # Starts the bitcoin daemon.
./src/bitcoin-cli --help # Outputs a list of command-line options.
./src/bitcoin-cli help # Outputs a list of RPC commands when the daemon is running.
+./src/qt/bitcoin-qt -server # Starts the bitcoin-qt server mode, allows bitcoin-cli control
```
-
-## Notes
-* Tested on OS X 10.14 Mojave through macOS 11 Big Sur on 64-bit Intel
-processors only.
-* Building with downloaded Qt binaries is not officially supported. See the notes in [#7714](https://github.com/bitcoin/bitcoin/issues/7714).
diff --git a/doc/dependencies.md b/doc/dependencies.md
index 159c6bcc28..22161856ce 100644
--- a/doc/dependencies.md
+++ b/doc/dependencies.md
@@ -14,19 +14,19 @@ These are the dependencies currently used by Bitcoin Core. You can find instruct
| GCC | | [7+](https://gcc.gnu.org/) (C++17 support) | | | |
| HarfBuzz-NG | | | | | [Yes](https://github.com/bitcoin/bitcoin/blob/master/depends/packages/qt.mk) |
| libevent | [2.1.11-stable](https://github.com/libevent/libevent/releases) | [2.0.21](https://github.com/bitcoin/bitcoin/pull/18676) | No | | |
-| libnatpmp | [20150609](https://miniupnp.tuxfamily.org/files) | | No | | |
+| libnatpmp | git commit [4536032...](https://github.com/miniupnp/libnatpmp/tree/4536032ae32268a45c073a4d5e91bbab4534773a) | | No | | |
| libpng | | | | | [Yes](https://github.com/bitcoin/bitcoin/blob/master/depends/packages/qt.mk) |
| librsvg | | | | | |
-| MiniUPnPc | [2.0.20180203](https://miniupnp.tuxfamily.org/files) | | No | | |
+| MiniUPnPc | [2.2.2](https://miniupnp.tuxfamily.org/files) | | No | | |
| PCRE | | | | | [Yes](https://github.com/bitcoin/bitcoin/blob/master/depends/packages/qt.mk) |
| Python (tests) | | [3.6](https://www.python.org/downloads) | | | |
| qrencode | [3.4.4](https://fukuchi.org/works/qrencode) | | No | | |
-| Qt | [5.9.8](https://download.qt.io/official_releases/qt/) | [5.9.5](https://github.com/bitcoin/bitcoin/issues/20104) | No | | |
+| Qt | [5.12.10](https://download.qt.io/official_releases/qt/) | [5.9.5](https://github.com/bitcoin/bitcoin/issues/20104) | No | | |
| SQLite | [3.32.1](https://sqlite.org/download.html) | [3.7.17](https://github.com/bitcoin/bitcoin/pull/19077) | | | |
| XCB | | | | | [Yes](https://github.com/bitcoin/bitcoin/blob/master/depends/packages/qt.mk) (Linux only) |
| xkbcommon | | | | | [Yes](https://github.com/bitcoin/bitcoin/blob/master/depends/packages/qt.mk) (Linux only) |
| ZeroMQ | [4.3.1](https://github.com/zeromq/libzmq/releases) | 4.0.0 | No | | |
-| zlib | [1.2.11](https://zlib.net/) | | | | No |
+| zlib | | | | | [Yes](https://github.com/bitcoin/bitcoin/blob/master/depends/packages/qt.mk) |
Controlling dependencies
------------------------
@@ -43,3 +43,4 @@ Some dependencies are not needed in all configurations. The following are some f
#### Other
* librsvg is only needed if you need to run `make deploy` on (cross-compilation to) macOS.
+* Not-Qt-bundled zlib is required to build the [DMG tool](../contrib/macdeploy/README.md#deterministic-macos-dmg-notes) from the libdmg-hfsplus project.
diff --git a/doc/release-notes-20861.md b/doc/release-notes-20861.md
new file mode 100644
index 0000000000..5c68e4ab0c
--- /dev/null
+++ b/doc/release-notes-20861.md
@@ -0,0 +1,13 @@
+Updated RPCs
+------------
+
+- Due to [BIP 350](https://github.com/bitcoin/bips/blob/master/bip-0350.mediawiki)
+ being implemented, behavior for all RPCs that accept addresses is changed when
+ a native witness version 1 (or higher) is passed. These now require a Bech32m
+ encoding instead of a Bech32 one, and Bech32m encoding will be used for such
+ addresses in RPC output as well. No version 1 addresses should be created
+ for mainnet until consensus rules are adopted that give them meaning
+ (e.g. through [BIP 341](https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki)).
+ Once that happens, Bech32m is expected to be used for them, so this shouldn't
+ affect any production systems, but may be observed on other networks where such
+ addresses already have meaning (like signet).
diff --git a/doc/release-notes.md b/doc/release-notes.md
index 0f248494c7..e46380b38f 100644
--- a/doc/release-notes.md
+++ b/doc/release-notes.md
@@ -51,9 +51,7 @@ Core should also work on most other Unix-like systems but is not as
frequently tested on them. It is not recommended to use Bitcoin Core on
unsupported systems.
-From Bitcoin Core 0.22.0 onwards, macOS versions earlier than 10.14 are no
-longer supported. Additionally, Bitcoin Core does not yet change appearance
-when macOS "dark mode" is activated.
+From Bitcoin Core 22.0 onwards, macOS versions earlier than 10.14 are no longer supported.
Notable changes
===============
@@ -69,6 +67,21 @@ Updated RPCs
`whitelisted`, the `permissions` field indicates if the peer has special
privileges. The `banscore` field has simply been removed. (#20755)
+- The following RPCs: `gettxout`, `getrawtransaction`, `decoderawtransaction`,
+ `decodescript`, `gettransaction`, and REST endpoints: `/rest/tx`,
+ `/rest/getutxos`, `/rest/block` deprecated the following fields (which are no
+ longer returned in the responses by default): `addresses`, `reqSigs`.
+ The `-deprecatedrpc=addresses` flag must be passed for these fields to be
+ included in the RPC response. This flag/option will be available until v23, at which
+ point the deprecation will be removed entirely. Note that these fields are attributes of
+ the `scriptPubKey` object returned in the RPC response. However, in the response
+ of `decodescript` these fields are top-level attributes, and included again as attributes
+ of the `scriptPubKey` object. (#20286)
+
+- When creating a hex-encoded bitcoin transaction using the `bitcoin-tx` utility
+ with the `-json` option set, the following fields: `addresses`, `reqSigs` are no longer
+ returned in the tx output of the response. (#20286)
+
Changes to Wallet or GUI related RPCs can be found in the GUI or Wallet section below.
New RPCs
@@ -105,6 +118,10 @@ Low-level changes
RPC
---
+- The RPC server can process a limited number of simultaneous RPC requests.
+ Previously, if this limit was exceeded, `bitcoind` would respond with
+ [status code 500 (`HTTP_INTERNAL_SERVER_ERROR`)](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#5xx_server_errors).
+ Now it returns status code 503 (`HTTP_SERVICE_UNAVAILABLE`). (#18335)
Tests
-----
diff --git a/share/qt/Info.plist.in b/share/qt/Info.plist.in
index 207d60aca3..da10dbb3be 100644
--- a/share/qt/Info.plist.in
+++ b/share/qt/Info.plist.in
@@ -60,9 +60,6 @@
<key>NSHighResolutionCapable</key>
<string>True</string>
- <key>NSRequiresAquaSystemAppearance</key>
- <string>True</string>
-
<key>LSApplicationCategoryType</key>
<string>public.app-category.finance</string>
</dict>
diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include
index 59cfdb9839..399a8430ef 100644
--- a/src/Makefile.qt.include
+++ b/src/Makefile.qt.include
@@ -378,6 +378,20 @@ bitcoin_qt_clean: FORCE
bitcoin_qt : qt/bitcoin-qt$(EXEEXT)
+APK_LIB_DIR = qt/android/libs/$(ANDROID_ARCH)
+QT_BASE_PATH = $(shell find ../depends/sources/ -maxdepth 1 -type f -regex ".*qtbase.*\.tar.xz")
+QT_BASE_TLD = $(shell tar tf $(QT_BASE_PATH) --exclude='*/*')
+
+bitcoin_qt_apk: FORCE
+ mkdir -p $(APK_LIB_DIR)
+ cp $(dir $(CC))../sysroot/usr/lib/$(host_alias)/libc++_shared.so $(APK_LIB_DIR)
+ tar xf $(QT_BASE_PATH) -C qt/android/src/ $(QT_BASE_TLD)src/android/jar/src --strip-components=5
+ tar xf $(QT_BASE_PATH) -C qt/android/src/ $(QT_BASE_TLD)src/android/java/src --strip-components=5
+ tar xf $(QT_BASE_PATH) -C qt/android/res/ $(QT_BASE_TLD)src/android/java/res --strip-components=5
+ cp qt/bitcoin-qt $(APK_LIB_DIR)/libbitcoin-qt.so
+ cd qt/android && gradle wrapper --gradle-version=6.6.1
+ cd qt/android && ./gradlew build
+
ui_%.h: %.ui
@test -f $(UIC)
@$(MKDIR_P) $(@D)
diff --git a/src/Makefile.qttest.include b/src/Makefile.qttest.include
index a6a857d952..91a5e9fd9b 100644
--- a/src/Makefile.qttest.include
+++ b/src/Makefile.qttest.include
@@ -7,7 +7,6 @@ TESTS += qt/test/test_bitcoin-qt
TEST_QT_MOC_CPP = \
qt/test/moc_apptests.cpp \
- qt/test/moc_compattests.cpp \
qt/test/moc_rpcnestedtests.cpp \
qt/test/moc_uritests.cpp
@@ -20,7 +19,6 @@ endif # ENABLE_WALLET
TEST_QT_H = \
qt/test/addressbooktests.h \
qt/test/apptests.h \
- qt/test/compattests.h \
qt/test/rpcnestedtests.h \
qt/test/uritests.h \
qt/test/util.h \
@@ -31,7 +29,6 @@ qt_test_test_bitcoin_qt_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(BITCOIN_
qt_test_test_bitcoin_qt_SOURCES = \
qt/test/apptests.cpp \
- qt/test/compattests.cpp \
qt/test/rpcnestedtests.cpp \
qt/test/test_main.cpp \
qt/test/uritests.cpp \
diff --git a/src/Makefile.test.include b/src/Makefile.test.include
index dc385b87b5..c5b1c065ce 100644
--- a/src/Makefile.test.include
+++ b/src/Makefile.test.include
@@ -298,8 +298,10 @@ test_fuzz_fuzz_SOURCES = \
test/fuzz/transaction.cpp \
test/fuzz/tx_in.cpp \
test/fuzz/tx_out.cpp \
+ test/fuzz/tx_pool.cpp \
test/fuzz/txrequest.cpp \
- test/fuzz/validation_load_mempool.cpp
+ test/fuzz/validation_load_mempool.cpp \
+ test/fuzz/versionbits.cpp
endif # ENABLE_FUZZ_BINARY
nodist_test_test_bitcoin_SOURCES = $(GENERATED_TEST_FILES)
diff --git a/src/bech32.cpp b/src/bech32.cpp
index 1e0471f110..288b14e023 100644
--- a/src/bech32.cpp
+++ b/src/bech32.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Pieter Wuille
+// Copyright (c) 2017, 2021 Pieter Wuille
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -7,15 +7,18 @@
#include <assert.h>
+namespace bech32
+{
+
namespace
{
typedef std::vector<uint8_t> data;
-/** The Bech32 character set for encoding. */
+/** The Bech32 and Bech32m character set for encoding. */
const char* CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l";
-/** The Bech32 character set for decoding. */
+/** The Bech32 and Bech32m character set for decoding. */
const int8_t CHARSET_REV[128] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
@@ -27,6 +30,12 @@ const int8_t CHARSET_REV[128] = {
1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, -1, -1
};
+/* Determine the final constant to use for the specified encoding. */
+uint32_t EncodingConstant(Encoding encoding) {
+ assert(encoding == Encoding::BECH32 || encoding == Encoding::BECH32M);
+ return encoding == Encoding::BECH32 ? 1 : 0x2bc830a3;
+}
+
/** This function will compute what 6 5-bit values to XOR into the last 6 input values, in order to
* make the checksum 0. These 6 values are packed together in a single 30-bit integer. The higher
* bits correspond to earlier values. */
@@ -111,21 +120,24 @@ data ExpandHRP(const std::string& hrp)
}
/** Verify a checksum. */
-bool VerifyChecksum(const std::string& hrp, const data& values)
+Encoding VerifyChecksum(const std::string& hrp, const data& values)
{
// PolyMod computes what value to xor into the final values to make the checksum 0. However,
// if we required that the checksum was 0, it would be the case that appending a 0 to a valid
// list of values would result in a new valid list. For that reason, Bech32 requires the
- // resulting checksum to be 1 instead.
- return PolyMod(Cat(ExpandHRP(hrp), values)) == 1;
+ // resulting checksum to be 1 instead. In Bech32m, this constant was amended.
+ const uint32_t check = PolyMod(Cat(ExpandHRP(hrp), values));
+ if (check == EncodingConstant(Encoding::BECH32)) return Encoding::BECH32;
+ if (check == EncodingConstant(Encoding::BECH32M)) return Encoding::BECH32M;
+ return Encoding::INVALID;
}
/** Create a checksum. */
-data CreateChecksum(const std::string& hrp, const data& values)
+data CreateChecksum(Encoding encoding, const std::string& hrp, const data& values)
{
data enc = Cat(ExpandHRP(hrp), values);
enc.resize(enc.size() + 6); // Append 6 zeroes
- uint32_t mod = PolyMod(enc) ^ 1; // Determine what to XOR into those 6 zeroes.
+ uint32_t mod = PolyMod(enc) ^ EncodingConstant(encoding); // Determine what to XOR into those 6 zeroes.
data ret(6);
for (size_t i = 0; i < 6; ++i) {
// Convert the 5-bit groups in mod to checksum values.
@@ -136,16 +148,13 @@ data CreateChecksum(const std::string& hrp, const data& values)
} // namespace
-namespace bech32
-{
-
-/** Encode a Bech32 string. */
-std::string Encode(const std::string& hrp, const data& values) {
- // First ensure that the HRP is all lowercase. BIP-173 requires an encoder
- // to return a lowercase Bech32 string, but if given an uppercase HRP, the
+/** Encode a Bech32 or Bech32m string. */
+std::string Encode(Encoding encoding, const std::string& hrp, const data& values) {
+ // First ensure that the HRP is all lowercase. BIP-173 and BIP350 require an encoder
+ // to return a lowercase Bech32/Bech32m string, but if given an uppercase HRP, the
// result will always be invalid.
for (const char& c : hrp) assert(c < 'A' || c > 'Z');
- data checksum = CreateChecksum(hrp, values);
+ data checksum = CreateChecksum(encoding, hrp, values);
data combined = Cat(values, checksum);
std::string ret = hrp + '1';
ret.reserve(ret.size() + combined.size());
@@ -155,8 +164,8 @@ std::string Encode(const std::string& hrp, const data& values) {
return ret;
}
-/** Decode a Bech32 string. */
-std::pair<std::string, data> Decode(const std::string& str) {
+/** Decode a Bech32 or Bech32m string. */
+DecodeResult Decode(const std::string& str) {
bool lower = false, upper = false;
for (size_t i = 0; i < str.size(); ++i) {
unsigned char c = str[i];
@@ -183,10 +192,9 @@ std::pair<std::string, data> Decode(const std::string& str) {
for (size_t i = 0; i < pos; ++i) {
hrp += LowerCase(str[i]);
}
- if (!VerifyChecksum(hrp, values)) {
- return {};
- }
- return {hrp, data(values.begin(), values.end() - 6)};
+ Encoding result = VerifyChecksum(hrp, values);
+ if (result == Encoding::INVALID) return {};
+ return {result, std::move(hrp), data(values.begin(), values.end() - 6)};
}
} // namespace bech32
diff --git a/src/bech32.h b/src/bech32.h
index fb39cd352b..e9450ccc2b 100644
--- a/src/bech32.h
+++ b/src/bech32.h
@@ -1,13 +1,14 @@
-// Copyright (c) 2017 Pieter Wuille
+// Copyright (c) 2017, 2021 Pieter Wuille
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-// Bech32 is a string encoding format used in newer address types.
-// The output consists of a human-readable part (alphanumeric), a
-// separator character (1), and a base32 data section, the last
-// 6 characters of which are a checksum.
+// Bech32 and Bech32m are string encoding formats used in newer
+// address types. The outputs consist of a human-readable part
+// (alphanumeric), a separator character (1), and a base32 data
+// section, the last 6 characters of which are a checksum. The
+// module is namespaced under bech32 for historical reasons.
//
-// For more information, see BIP 173.
+// For more information, see BIP 173 and BIP 350.
#ifndef BITCOIN_BECH32_H
#define BITCOIN_BECH32_H
@@ -19,11 +20,29 @@
namespace bech32
{
-/** Encode a Bech32 string. If hrp contains uppercase characters, this will cause an assertion error. */
-std::string Encode(const std::string& hrp, const std::vector<uint8_t>& values);
+enum class Encoding {
+ INVALID, //!< Failed decoding
-/** Decode a Bech32 string. Returns (hrp, data). Empty hrp means failure. */
-std::pair<std::string, std::vector<uint8_t>> Decode(const std::string& str);
+ BECH32, //!< Bech32 encoding as defined in BIP173
+ BECH32M, //!< Bech32m encoding as defined in BIP350
+};
+
+/** Encode a Bech32 or Bech32m string. If hrp contains uppercase characters, this will cause an
+ * assertion error. Encoding must be one of BECH32 or BECH32M. */
+std::string Encode(Encoding encoding, const std::string& hrp, const std::vector<uint8_t>& values);
+
+struct DecodeResult
+{
+ Encoding encoding; //!< What encoding was detected in the result; Encoding::INVALID if failed.
+ std::string hrp; //!< The human readable part
+ std::vector<uint8_t> data; //!< The payload (excluding checksum)
+
+ DecodeResult() : encoding(Encoding::INVALID) {}
+ DecodeResult(Encoding enc, std::string&& h, std::vector<uint8_t>&& d) : encoding(enc), hrp(std::move(h)), data(std::move(d)) {}
+};
+
+/** Decode a Bech32 or Bech32m string. */
+DecodeResult Decode(const std::string& str);
} // namespace bech32
diff --git a/src/bench/bech32.cpp b/src/bench/bech32.cpp
index c74d8d51b3..8e10862a37 100644
--- a/src/bench/bech32.cpp
+++ b/src/bench/bech32.cpp
@@ -19,7 +19,7 @@ static void Bech32Encode(benchmark::Bench& bench)
tmp.reserve(1 + 32 * 8 / 5);
ConvertBits<8, 5, true>([&](unsigned char c) { tmp.push_back(c); }, v.begin(), v.end());
bench.batch(v.size()).unit("byte").run([&] {
- bech32::Encode("bc", tmp);
+ bech32::Encode(bech32::Encoding::BECH32, "bc", tmp);
});
}
diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp
index ecd08c62eb..4f3d7a4ffe 100644
--- a/src/bitcoin-cli.cpp
+++ b/src/bitcoin-cli.cpp
@@ -618,9 +618,9 @@ static UniValue CallRPC(BaseRequestHandler* rh, const std::string& strMethod, co
// 1. -rpcport
// 2. port in -rpcconnect (ie following : in ipv4 or ]: in ipv6)
// 3. default port for chain
- int port = BaseParams().RPCPort();
+ uint16_t port{BaseParams().RPCPort()};
SplitHostPort(gArgs.GetArg("-rpcconnect", DEFAULT_RPCCONNECT), port, host);
- port = gArgs.GetArg("-rpcport", port);
+ port = static_cast<uint16_t>(gArgs.GetArg("-rpcport", port));
// Obtain event base
raii_event_base base = obtain_event_base();
@@ -708,6 +708,8 @@ static UniValue CallRPC(BaseRequestHandler* rh, const std::string& strMethod, co
} else {
throw std::runtime_error("Authorization failed: Incorrect rpcuser or rpcpassword");
}
+ } else if (response.status == HTTP_SERVICE_UNAVAILABLE) {
+ throw std::runtime_error(strprintf("Server response: %s", response.body));
} else if (response.status >= 400 && response.status != HTTP_BAD_REQUEST && response.status != HTTP_NOT_FOUND && response.status != HTTP_INTERNAL_SERVER_ERROR)
throw std::runtime_error(strprintf("server returned HTTP error %d", response.status));
else if (response.body.empty())
diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp
index 321d62fe4d..93ac4b8f7e 100644
--- a/src/bitcoin-tx.cpp
+++ b/src/bitcoin-tx.cpp
@@ -725,7 +725,7 @@ static void MutateTx(CMutableTransaction& tx, const std::string& command,
static void OutputTxJSON(const CTransaction& tx)
{
UniValue entry(UniValue::VOBJ);
- TxToUniv(tx, uint256(), entry);
+ TxToUniv(tx, uint256(), /* include_addresses */ false, entry);
std::string jsonOutput = entry.write(4);
tfm::format(std::cout, "%s\n", jsonOutput);
diff --git a/src/chainparams.h b/src/chainparams.h
index 4d24dcdb7c..013f075be6 100644
--- a/src/chainparams.h
+++ b/src/chainparams.h
@@ -84,7 +84,7 @@ public:
const Consensus::Params& GetConsensus() const { return consensus; }
const CMessageHeader::MessageStartChars& MessageStart() const { return pchMessageStart; }
- int GetDefaultPort() const { return nDefaultPort; }
+ uint16_t GetDefaultPort() const { return nDefaultPort; }
const CBlock& GenesisBlock() const { return genesis; }
/** Default value for -checkmempool and -checkblockindex argument */
@@ -121,7 +121,7 @@ protected:
Consensus::Params consensus;
CMessageHeader::MessageStartChars pchMessageStart;
- int nDefaultPort;
+ uint16_t nDefaultPort;
uint64_t nPruneAfterHeight;
uint64_t m_assumed_blockchain_size;
uint64_t m_assumed_chain_state_size;
diff --git a/src/coins.h b/src/coins.h
index feb441fd6a..5a6f73652b 100644
--- a/src/coins.h
+++ b/src/coins.h
@@ -75,6 +75,9 @@ public:
::Unserialize(s, Using<TxOutCompression>(out));
}
+ /** Either this coin never existed (see e.g. coinEmpty in coins.cpp), or it
+ * did exist and has been spent.
+ */
bool IsSpent() const {
return out.IsNull();
}
diff --git a/src/core_io.h b/src/core_io.h
index 01340ae2ee..3b9b66574c 100644
--- a/src/core_io.h
+++ b/src/core_io.h
@@ -44,8 +44,8 @@ UniValue ValueFromAmount(const CAmount amount);
std::string FormatScript(const CScript& script);
std::string EncodeHexTx(const CTransaction& tx, const int serializeFlags = 0);
std::string SighashToStr(unsigned char sighash_type);
-void ScriptPubKeyToUniv(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex);
+void ScriptPubKeyToUniv(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex, bool include_addresses);
void ScriptToUniv(const CScript& script, UniValue& out, bool include_address);
-void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry, bool include_hex = true, int serialize_flags = 0, const CTxUndo* txundo = nullptr);
+void TxToUniv(const CTransaction& tx, const uint256& hashBlock, bool include_addresses, UniValue& entry, bool include_hex = true, int serialize_flags = 0, const CTxUndo* txundo = nullptr);
#endif // BITCOIN_CORE_IO_H
diff --git a/src/core_write.cpp b/src/core_write.cpp
index d3034ae25d..b35f835f42 100644
--- a/src/core_write.cpp
+++ b/src/core_write.cpp
@@ -156,10 +156,13 @@ void ScriptToUniv(const CScript& script, UniValue& out, bool include_address)
}
}
+// TODO: from v23 ("addresses" and "reqSigs" deprecated) this method should be refactored to remove the `include_addresses` option
+// this method can also be combined with `ScriptToUniv` as they will overlap
void ScriptPubKeyToUniv(const CScript& scriptPubKey,
- UniValue& out, bool fIncludeHex)
+ UniValue& out, bool fIncludeHex, bool include_addresses)
{
TxoutType type;
+ CTxDestination address;
std::vector<CTxDestination> addresses;
int nRequired;
@@ -172,17 +175,22 @@ void ScriptPubKeyToUniv(const CScript& scriptPubKey,
return;
}
- out.pushKV("reqSigs", nRequired);
+ if (ExtractDestination(scriptPubKey, address)) {
+ out.pushKV("address", EncodeDestination(address));
+ }
out.pushKV("type", GetTxnOutputType(type));
- UniValue a(UniValue::VARR);
- for (const CTxDestination& addr : addresses) {
- a.push_back(EncodeDestination(addr));
+ if (include_addresses) {
+ UniValue a(UniValue::VARR);
+ for (const CTxDestination& addr : addresses) {
+ a.push_back(EncodeDestination(addr));
+ }
+ out.pushKV("addresses", a);
+ out.pushKV("reqSigs", nRequired);
}
- out.pushKV("addresses", a);
}
-void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry, bool include_hex, int serialize_flags, const CTxUndo* txundo)
+void TxToUniv(const CTransaction& tx, const uint256& hashBlock, bool include_addresses, UniValue& entry, bool include_hex, int serialize_flags, const CTxUndo* txundo)
{
entry.pushKV("txid", tx.GetHash().GetHex());
entry.pushKV("hash", tx.GetWitnessHash().GetHex());
@@ -241,7 +249,7 @@ void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry,
out.pushKV("n", (int64_t)i);
UniValue o(UniValue::VOBJ);
- ScriptPubKeyToUniv(txout.scriptPubKey, o, true);
+ ScriptPubKeyToUniv(txout.scriptPubKey, o, true, include_addresses);
out.pushKV("scriptPubKey", o);
vout.push_back(out);
diff --git a/src/httpserver.cpp b/src/httpserver.cpp
index 0a8e58ab67..12395f5b24 100644
--- a/src/httpserver.cpp
+++ b/src/httpserver.cpp
@@ -262,7 +262,7 @@ static void http_request_cb(struct evhttp_request* req, void* arg)
item.release(); /* if true, queue took ownership */
else {
LogPrintf("WARNING: request rejected because http work queue depth exceeded, it can be increased with the -rpcworkqueue= setting\n");
- item->req->WriteReply(HTTP_INTERNAL_SERVER_ERROR, "Work queue depth exceeded");
+ item->req->WriteReply(HTTP_SERVICE_UNAVAILABLE, "Work queue depth exceeded");
}
} else {
hreq->WriteReply(HTTP_NOT_FOUND);
@@ -290,8 +290,8 @@ static bool ThreadHTTP(struct event_base* base)
/** Bind HTTP server to specified addresses */
static bool HTTPBindAddresses(struct evhttp* http)
{
- int http_port = gArgs.GetArg("-rpcport", BaseParams().RPCPort());
- std::vector<std::pair<std::string, uint16_t> > endpoints;
+ uint16_t http_port{static_cast<uint16_t>(gArgs.GetArg("-rpcport", BaseParams().RPCPort()))};
+ std::vector<std::pair<std::string, uint16_t>> endpoints;
// Determine what addresses to bind to
if (!(gArgs.IsArgSet("-rpcallowip") && gArgs.IsArgSet("-rpcbind"))) { // Default to loopback if not allowing external IPs
@@ -305,7 +305,7 @@ static bool HTTPBindAddresses(struct evhttp* http)
}
} else if (gArgs.IsArgSet("-rpcbind")) { // Specific bind address
for (const std::string& strRPCBind : gArgs.GetArgs("-rpcbind")) {
- int port = http_port;
+ uint16_t port{http_port};
std::string host;
SplitHostPort(strRPCBind, port, host);
endpoints.push_back(std::make_pair(host, port));
diff --git a/src/init.cpp b/src/init.cpp
index 7d5420e3be..8b1f531b81 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -228,6 +228,7 @@ void Shutdown(NodeContext& node)
node.peerman.reset();
node.connman.reset();
node.banman.reset();
+ node.addrman.reset();
if (node.mempool && node.mempool->IsLoaded() && node.args->GetArg("-persistmempool", DEFAULT_PERSIST_MEMPOOL)) {
DumpMempool(*node.mempool);
@@ -1308,7 +1309,7 @@ bool AppInitMain(const util::Ref& context, NodeContext& node, interfaces::BlockA
LogPrintf("Config file: %s\n", config_file_path.string());
} else if (args.IsArgSet("-conf")) {
// Warn if no conf file exists at path provided by user
- InitWarning(strprintf(_("The specified config file %s does not exist\n"), config_file_path.string()));
+ InitWarning(strprintf(_("The specified config file %s does not exist"), config_file_path.string()));
} else {
// Not categorizing as "Warning" because it's the default behavior
LogPrintf("Config file: %s (not found, skipping)\n", config_file_path.string());
@@ -1402,10 +1403,12 @@ bool AppInitMain(const util::Ref& context, NodeContext& node, interfaces::BlockA
fDiscover = args.GetBoolArg("-discover", true);
const bool ignores_incoming_txs{args.GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY)};
+ assert(!node.addrman);
+ node.addrman = std::make_unique<CAddrMan>();
assert(!node.banman);
node.banman = std::make_unique<BanMan>(GetDataDir() / "banlist.dat", &uiInterface, args.GetArg("-bantime", DEFAULT_MISBEHAVING_BANTIME));
assert(!node.connman);
- node.connman = std::make_unique<CConnman>(GetRand(std::numeric_limits<uint64_t>::max()), GetRand(std::numeric_limits<uint64_t>::max()), args.GetBoolArg("-networkactive", true));
+ node.connman = std::make_unique<CConnman>(GetRand(std::numeric_limits<uint64_t>::max()), GetRand(std::numeric_limits<uint64_t>::max()), *node.addrman, args.GetBoolArg("-networkactive", true));
assert(!node.fee_estimator);
// Don't initialize fee estimation with old data if we don't relay transactions,
@@ -1421,7 +1424,7 @@ bool AppInitMain(const util::Ref& context, NodeContext& node, interfaces::BlockA
ChainstateManager& chainman = *Assert(node.chainman);
assert(!node.peerman);
- node.peerman = PeerManager::make(chainparams, *node.connman, node.banman.get(),
+ node.peerman = PeerManager::make(chainparams, *node.connman, *node.addrman, node.banman.get(),
*node.scheduler, chainman, *node.mempool, ignores_incoming_txs);
RegisterValidationInterface(node.peerman.get());
diff --git a/src/key_io.cpp b/src/key_io.cpp
index e27673fd16..dbcbfa1f29 100644
--- a/src/key_io.cpp
+++ b/src/key_io.cpp
@@ -43,7 +43,7 @@ public:
std::vector<unsigned char> data = {0};
data.reserve(33);
ConvertBits<8, 5, true>([&](unsigned char c) { data.push_back(c); }, id.begin(), id.end());
- return bech32::Encode(m_params.Bech32HRP(), data);
+ return bech32::Encode(bech32::Encoding::BECH32, m_params.Bech32HRP(), data);
}
std::string operator()(const WitnessV0ScriptHash& id) const
@@ -51,7 +51,7 @@ public:
std::vector<unsigned char> data = {0};
data.reserve(53);
ConvertBits<8, 5, true>([&](unsigned char c) { data.push_back(c); }, id.begin(), id.end());
- return bech32::Encode(m_params.Bech32HRP(), data);
+ return bech32::Encode(bech32::Encoding::BECH32, m_params.Bech32HRP(), data);
}
std::string operator()(const WitnessUnknown& id) const
@@ -62,7 +62,7 @@ public:
std::vector<unsigned char> data = {(unsigned char)id.version};
data.reserve(1 + (id.length * 8 + 4) / 5);
ConvertBits<8, 5, true>([&](unsigned char c) { data.push_back(c); }, id.program, id.program + id.length);
- return bech32::Encode(m_params.Bech32HRP(), data);
+ return bech32::Encode(bech32::Encoding::BECH32M, m_params.Bech32HRP(), data);
}
std::string operator()(const CNoDestination& no) const { return {}; }
@@ -95,20 +95,26 @@ CTxDestination DecodeDestination(const std::string& str, const CChainParams& par
error_str = "Invalid prefix for Base58-encoded address";
}
data.clear();
- auto bech = bech32::Decode(str);
- if (bech.second.size() > 0) {
+ const auto dec = bech32::Decode(str);
+ if ((dec.encoding == bech32::Encoding::BECH32 || dec.encoding == bech32::Encoding::BECH32M) && dec.data.size() > 0) {
+ // Bech32 decoding
error_str = "";
-
- if (bech.first != params.Bech32HRP()) {
+ if (dec.hrp != params.Bech32HRP()) {
error_str = "Invalid prefix for Bech32 address";
return CNoDestination();
}
-
- // Bech32 decoding
- int version = bech.second[0]; // The first 5 bit symbol is the witness version (0-16)
+ int version = dec.data[0]; // The first 5 bit symbol is the witness version (0-16)
+ if (version == 0 && dec.encoding != bech32::Encoding::BECH32) {
+ error_str = "Version 0 witness address must use Bech32 checksum";
+ return CNoDestination();
+ }
+ if (version != 0 && dec.encoding != bech32::Encoding::BECH32M) {
+ error_str = "Version 1+ witness address must use Bech32m checksum";
+ return CNoDestination();
+ }
// The rest of the symbols are converted witness program bytes.
- data.reserve(((bech.second.size() - 1) * 5) / 8);
- if (ConvertBits<5, 8, false>([&](unsigned char c) { data.push_back(c); }, bech.second.begin() + 1, bech.second.end())) {
+ data.reserve(((dec.data.size() - 1) * 5) / 8);
+ if (ConvertBits<5, 8, false>([&](unsigned char c) { data.push_back(c); }, dec.data.begin() + 1, dec.data.end())) {
if (version == 0) {
{
WitnessV0KeyHash keyid;
diff --git a/src/net.cpp b/src/net.cpp
index 66d81b115f..e629d6a0a5 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -113,7 +113,7 @@ void CConnman::AddAddrFetch(const std::string& strDest)
uint16_t GetListenPort()
{
- return (uint16_t)(gArgs.GetArg("-port", Params().GetDefaultPort()));
+ return static_cast<uint16_t>(gArgs.GetArg("-port", Params().GetDefaultPort()));
}
// find 'best' local address for a particular peer
@@ -394,7 +394,7 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
pszDest ? 0.0 : (double)(GetAdjustedTime() - addrConnect.nTime)/3600.0);
// Resolve
- const int default_port = Params().GetDefaultPort();
+ const uint16_t default_port{Params().GetDefaultPort()};
if (pszDest) {
std::vector<CService> resolved;
if (Lookup(pszDest, resolved, default_port, fNameLookup && !HaveNameProxy(), 256) && !resolved.empty()) {
@@ -462,7 +462,7 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
return nullptr;
}
std::string host;
- int port = default_port;
+ uint16_t port{default_port};
SplitHostPort(std::string(pszDest), port, host);
bool proxyConnectionFailed;
connected = ConnectThroughProxy(proxy, host, port, *sock, nConnectTimeout,
@@ -2383,8 +2383,8 @@ void CConnman::SetNetworkActive(bool active)
uiInterface.NotifyNetworkActiveChanged(fNetworkActive);
}
-CConnman::CConnman(uint64_t nSeed0In, uint64_t nSeed1In, bool network_active)
- : nSeed0(nSeed0In), nSeed1(nSeed1In)
+CConnman::CConnman(uint64_t nSeed0In, uint64_t nSeed1In, CAddrMan& addrman_in, bool network_active)
+ : addrman(addrman_in), nSeed0(nSeed0In), nSeed1(nSeed1In)
{
SetTryNewOutboundPeer(false);
@@ -2653,11 +2653,7 @@ void CConnman::StopNodes()
void CConnman::DeleteNode(CNode* pnode)
{
assert(pnode);
- bool fUpdateConnectionTime = false;
- m_msgproc->FinalizeNode(*pnode, fUpdateConnectionTime);
- if (fUpdateConnectionTime) {
- addrman.Connected(pnode->addr);
- }
+ m_msgproc->FinalizeNode(*pnode);
delete pnode;
}
@@ -2667,21 +2663,6 @@ CConnman::~CConnman()
Stop();
}
-void CConnman::SetServices(const CService &addr, ServiceFlags nServices)
-{
- addrman.SetServices(addr, nServices);
-}
-
-void CConnman::MarkAddressGood(const CAddress& addr)
-{
- addrman.Good(addr);
-}
-
-bool CConnman::AddNewAddresses(const std::vector<CAddress>& vAddr, const CAddress& addrFrom, int64_t nTimePenalty)
-{
- return addrman.Add(vAddr, addrFrom, nTimePenalty);
-}
-
std::vector<CAddress> CConnman::GetAddresses(size_t max_addresses, size_t max_pct)
{
std::vector<CAddress> addresses = addrman.GetAddr(max_addresses, max_pct);
diff --git a/src/net.h b/src/net.h
index eb7fa079ab..add48b11a4 100644
--- a/src/net.h
+++ b/src/net.h
@@ -229,7 +229,7 @@ extern std::string strSubVersion;
struct LocalServiceInfo {
int nScore;
- int nPort;
+ uint16_t nPort;
};
extern RecursiveMutex cs_mapLocalHost;
@@ -771,7 +771,7 @@ public:
virtual void InitializeNode(CNode* pnode) = 0;
/** Handle removal of a peer (clear state) */
- virtual void FinalizeNode(const CNode& node, bool& update_connection_time) = 0;
+ virtual void FinalizeNode(const CNode& node) = 0;
/**
* Process protocol messages received from a given node
@@ -857,7 +857,7 @@ public:
m_onion_binds = connOptions.onion_binds;
}
- CConnman(uint64_t seed0, uint64_t seed1, bool network_active = true);
+ CConnman(uint64_t seed0, uint64_t seed1, CAddrMan& addrman, bool network_active = true);
~CConnman();
bool Start(CScheduler& scheduler, const Options& options);
@@ -922,9 +922,6 @@ public:
};
// Addrman functions
- void SetServices(const CService &addr, ServiceFlags nServices);
- void MarkAddressGood(const CAddress& addr);
- bool AddNewAddresses(const std::vector<CAddress>& vAddr, const CAddress& addrFrom, int64_t nTimePenalty = 0);
std::vector<CAddress> GetAddresses(size_t max_addresses, size_t max_pct);
/**
* Cache is used to minimize topology leaks, so it should
@@ -1131,7 +1128,7 @@ private:
std::vector<ListenSocket> vhListenSocket;
std::atomic<bool> fNetworkActive{true};
bool fAddressesInitialized{false};
- CAddrMan addrman;
+ CAddrMan& addrman;
std::deque<std::string> m_addr_fetches GUARDED_BY(m_addr_fetches_mutex);
RecursiveMutex m_addr_fetches_mutex;
std::vector<std::string> vAddedNodes GUARDED_BY(cs_vAddedNodes);
diff --git a/src/net_processing.cpp b/src/net_processing.cpp
index 8ffbd45034..e4054968c0 100644
--- a/src/net_processing.cpp
+++ b/src/net_processing.cpp
@@ -225,9 +225,9 @@ using PeerRef = std::shared_ptr<Peer>;
class PeerManagerImpl final : public PeerManager
{
public:
- PeerManagerImpl(const CChainParams& chainparams, CConnman& connman, BanMan* banman,
- CScheduler& scheduler, ChainstateManager& chainman, CTxMemPool& pool,
- bool ignore_incoming_txs);
+ PeerManagerImpl(const CChainParams& chainparams, CConnman& connman, CAddrMan& addrman,
+ BanMan* banman, CScheduler& scheduler, ChainstateManager& chainman,
+ CTxMemPool& pool, bool ignore_incoming_txs);
/** Overridden from CValidationInterface. */
void BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindexConnected) override;
@@ -238,7 +238,7 @@ public:
/** Implement NetEventsInterface */
void InitializeNode(CNode* pnode) override;
- void FinalizeNode(const CNode& node, bool& fUpdateConnectionTime) override;
+ void FinalizeNode(const CNode& node) override;
bool ProcessMessages(CNode* pfrom, std::atomic<bool>& interrupt) override;
bool SendMessages(CNode* pto) override EXCLUSIVE_LOCKS_REQUIRED(pto->cs_sendProcessing);
@@ -247,6 +247,7 @@ public:
bool GetNodeStateStats(NodeId nodeid, CNodeStateStats& stats) override;
bool IgnoresIncomingTxs() override { return m_ignore_incoming_txs; }
void SendPings() override;
+ void RelayTransaction(const uint256& txid, const uint256& wtxid) override;
void SetBestHeight(int height) override { m_best_height = height; };
void Misbehaving(const NodeId pnode, const int howmuch, const std::string& message) override;
void ProcessMessage(CNode& pfrom, const std::string& msg_type, CDataStream& vRecv,
@@ -260,7 +261,7 @@ private:
void EvictExtraOutboundPeers(int64_t time_in_seconds) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
/** Retrieve unbroadcast transactions from the mempool and reattempt sending to peers */
- void ReattemptInitialBroadcast(CScheduler& scheduler) const;
+ void ReattemptInitialBroadcast(CScheduler& scheduler);
/** Get a shared pointer to the Peer object.
* May return an empty shared_ptr if the Peer object can't be found. */
@@ -321,6 +322,7 @@ private:
const CChainParams& m_chainparams;
CConnman& m_connman;
+ CAddrMan& m_addrman;
/** Pointer to this node's banman. May be nullptr - check existence before dereferencing. */
BanMan* const m_banman;
ChainstateManager& m_chainman;
@@ -475,22 +477,19 @@ private:
size_t vExtraTxnForCompactIt GUARDED_BY(g_cs_orphans) = 0;
void ProcessBlockAvailability(NodeId nodeid) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
- void UpdateBlockAvailability(NodeId nodeid, const uint256 &hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
- bool CanDirectFetch(const Consensus::Params &consensusParams) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
- bool BlockRequestAllowed(const CBlockIndex* pindex, const Consensus::Params& consensusParams) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+ void UpdateBlockAvailability(NodeId nodeid, const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+ bool CanDirectFetch() EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+ bool BlockRequestAllowed(const CBlockIndex* pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
bool AlreadyHaveBlock(const uint256& block_hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
- void ProcessGetBlockData(CNode& pfrom, Peer& peer, const CChainParams& chainparams, const CInv& inv, CConnman& connman);
- bool PrepareBlockFilterRequest(CNode& peer, const CChainParams& chain_params,
+ void ProcessGetBlockData(CNode& pfrom, Peer& peer, const CInv& inv);
+ bool PrepareBlockFilterRequest(CNode& peer,
BlockFilterType filter_type, uint32_t start_height,
const uint256& stop_hash, uint32_t max_height_diff,
const CBlockIndex*& stop_index,
BlockFilterIndex*& filter_index);
- void ProcessGetCFilters(CNode& peer, CDataStream& vRecv, const CChainParams& chain_params,
- CConnman& connman);
- void ProcessGetCFHeaders(CNode& peer, CDataStream& vRecv, const CChainParams& chain_params,
- CConnman& connman);
- void ProcessGetCFCheckPt(CNode& peer, CDataStream& vRecv, const CChainParams& chain_params,
- CConnman& connman);
+ void ProcessGetCFilters(CNode& peer, CDataStream& vRecv);
+ void ProcessGetCFHeaders(CNode& peer, CDataStream& vRecv);
+ void ProcessGetCFCheckPt(CNode& peer, CDataStream& vRecv);
};
} // namespace
@@ -729,9 +728,9 @@ bool PeerManagerImpl::TipMayBeStale()
return m_last_tip_update < GetTime() - consensusParams.nPowTargetSpacing * 3 && mapBlocksInFlight.empty();
}
-bool PeerManagerImpl::CanDirectFetch(const Consensus::Params &consensusParams)
+bool PeerManagerImpl::CanDirectFetch()
{
- return m_chainman.ActiveChain().Tip()->GetBlockTime() > GetAdjustedTime() - consensusParams.nPowTargetSpacing * 20;
+ return m_chainman.ActiveChain().Tip()->GetBlockTime() > GetAdjustedTime() - m_chainparams.GetConsensus().nPowTargetSpacing * 20;
}
static bool PeerHasHeader(CNodeState *state, const CBlockIndex *pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
@@ -949,7 +948,7 @@ void PeerManagerImpl::InitializeNode(CNode *pnode)
}
}
-void PeerManagerImpl::ReattemptInitialBroadcast(CScheduler& scheduler) const
+void PeerManagerImpl::ReattemptInitialBroadcast(CScheduler& scheduler)
{
std::set<uint256> unbroadcast_txids = m_mempool.GetUnbroadcastTxs();
@@ -958,7 +957,7 @@ void PeerManagerImpl::ReattemptInitialBroadcast(CScheduler& scheduler) const
if (tx != nullptr) {
LOCK(cs_main);
- RelayTransaction(txid, tx->GetWitnessHash(), m_connman);
+ RelayTransaction(txid, tx->GetWitnessHash());
} else {
m_mempool.RemoveUnbroadcastTx(txid, true);
}
@@ -970,13 +969,13 @@ void PeerManagerImpl::ReattemptInitialBroadcast(CScheduler& scheduler) const
scheduler.scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
}
-void PeerManagerImpl::FinalizeNode(const CNode& node, bool& fUpdateConnectionTime)
+void PeerManagerImpl::FinalizeNode(const CNode& node)
{
NodeId nodeid = node.GetId();
- fUpdateConnectionTime = false;
- LOCK(cs_main);
int misbehavior{0};
{
+ LOCK(cs_main);
+ {
// We remove the PeerRef from g_peer_map here, but we don't always
// destruct the Peer. Sometimes another thread is still holding a
// PeerRef, so the refcount is >= 1. Be careful not to do any
@@ -992,12 +991,6 @@ void PeerManagerImpl::FinalizeNode(const CNode& node, bool& fUpdateConnectionTim
if (state->fSyncStarted)
nSyncStarted--;
- if (node.fSuccessfullyConnected && misbehavior == 0 &&
- !node.IsBlockOnlyConn() && !node.IsInboundConn()) {
- // Only change visible addrman state for outbound, full-relay peers
- fUpdateConnectionTime = true;
- }
-
for (const QueuedBlock& entry : state->vBlocksInFlight) {
mapBlocksInFlight.erase(entry.hash);
}
@@ -1022,6 +1015,14 @@ void PeerManagerImpl::FinalizeNode(const CNode& node, bool& fUpdateConnectionTim
assert(m_wtxid_relay_peers == 0);
assert(m_txrequest.Size() == 0);
}
+ } // cs_main
+ if (node.fSuccessfullyConnected && misbehavior == 0 &&
+ !node.IsBlockOnlyConn() && !node.IsInboundConn()) {
+ // Only change visible addrman state for full outbound peers. We don't
+ // call Connected() for feeler connections since they don't have
+ // fSuccessfullyConnected set.
+ m_addrman.Connected(node.addr);
+ }
LogPrint(BCLog::NET, "Cleared nodestate for peer=%d\n", nodeid);
}
@@ -1194,27 +1195,28 @@ bool PeerManagerImpl::MaybePunishNodeForTx(NodeId nodeid, const TxValidationStat
// active chain if they are no more than a month older (both in time, and in
// best equivalent proof of work) than the best header chain we know about and
// we fully-validated them at some point.
-bool PeerManagerImpl::BlockRequestAllowed(const CBlockIndex* pindex, const Consensus::Params& consensusParams)
+bool PeerManagerImpl::BlockRequestAllowed(const CBlockIndex* pindex)
{
AssertLockHeld(cs_main);
if (m_chainman.ActiveChain().Contains(pindex)) return true;
return pindex->IsValid(BLOCK_VALID_SCRIPTS) && (pindexBestHeader != nullptr) &&
- (pindexBestHeader->GetBlockTime() - pindex->GetBlockTime() < STALE_RELAY_AGE_LIMIT) &&
- (GetBlockProofEquivalentTime(*pindexBestHeader, *pindex, *pindexBestHeader, consensusParams) < STALE_RELAY_AGE_LIMIT);
+ (pindexBestHeader->GetBlockTime() - pindex->GetBlockTime() < STALE_RELAY_AGE_LIMIT) &&
+ (GetBlockProofEquivalentTime(*pindexBestHeader, *pindex, *pindexBestHeader, m_chainparams.GetConsensus()) < STALE_RELAY_AGE_LIMIT);
}
-std::unique_ptr<PeerManager> PeerManager::make(const CChainParams& chainparams, CConnman& connman, BanMan* banman,
- CScheduler& scheduler, ChainstateManager& chainman, CTxMemPool& pool,
- bool ignore_incoming_txs)
+std::unique_ptr<PeerManager> PeerManager::make(const CChainParams& chainparams, CConnman& connman, CAddrMan& addrman,
+ BanMan* banman, CScheduler& scheduler, ChainstateManager& chainman,
+ CTxMemPool& pool, bool ignore_incoming_txs)
{
- return std::make_unique<PeerManagerImpl>(chainparams, connman, banman, scheduler, chainman, pool, ignore_incoming_txs);
+ return std::make_unique<PeerManagerImpl>(chainparams, connman, addrman, banman, scheduler, chainman, pool, ignore_incoming_txs);
}
-PeerManagerImpl::PeerManagerImpl(const CChainParams& chainparams, CConnman& connman, BanMan* banman,
- CScheduler& scheduler, ChainstateManager& chainman, CTxMemPool& pool,
- bool ignore_incoming_txs)
+PeerManagerImpl::PeerManagerImpl(const CChainParams& chainparams, CConnman& connman, CAddrMan& addrman,
+ BanMan* banman, CScheduler& scheduler, ChainstateManager& chainman,
+ CTxMemPool& pool, bool ignore_incoming_txs)
: m_chainparams(chainparams),
m_connman(connman),
+ m_addrman(addrman),
m_banman(banman),
m_chainman(chainman),
m_mempool(pool),
@@ -1460,9 +1462,9 @@ void PeerManagerImpl::SendPings()
for(auto& it : m_peer_map) it.second->m_ping_queued = true;
}
-void RelayTransaction(const uint256& txid, const uint256& wtxid, const CConnman& connman)
+void PeerManagerImpl::RelayTransaction(const uint256& txid, const uint256& wtxid)
{
- connman.ForEachNode([&txid, &wtxid](CNode* pnode) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) {
+ m_connman.ForEachNode([&txid, &wtxid](CNode* pnode) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) {
AssertLockHeld(::cs_main);
CNodeState* state = State(pnode->GetId());
@@ -1530,13 +1532,11 @@ static void RelayAddress(const CNode& originator,
connman.ForEachNodeThen(std::move(sortfunc), std::move(pushfunc));
}
-void PeerManagerImpl::ProcessGetBlockData(CNode& pfrom, Peer& peer, const CChainParams& chainparams, const CInv& inv, CConnman& connman)
+void PeerManagerImpl::ProcessGetBlockData(CNode& pfrom, Peer& peer, const CInv& inv)
{
- bool send = false;
std::shared_ptr<const CBlock> a_recent_block;
std::shared_ptr<const CBlockHeaderAndShortTxIDs> a_recent_compact_block;
bool fWitnessesPresentInARecentCompactBlock;
- const Consensus::Params& consensusParams = chainparams.GetConsensus();
{
LOCK(cs_most_recent_block);
a_recent_block = most_recent_block;
@@ -1562,126 +1562,124 @@ void PeerManagerImpl::ProcessGetBlockData(CNode& pfrom, Peer& peer, const CChain
} // release cs_main before calling ActivateBestChain
if (need_activate_chain) {
BlockValidationState state;
- if (!m_chainman.ActiveChainstate().ActivateBestChain(state, chainparams, a_recent_block)) {
+ if (!m_chainman.ActiveChainstate().ActivateBestChain(state, m_chainparams, a_recent_block)) {
LogPrint(BCLog::NET, "failed to activate chain (%s)\n", state.ToString());
}
}
LOCK(cs_main);
const CBlockIndex* pindex = m_chainman.m_blockman.LookupBlockIndex(inv.hash);
- if (pindex) {
- send = BlockRequestAllowed(pindex, consensusParams);
- if (!send) {
- LogPrint(BCLog::NET, "%s: ignoring request from peer=%i for old block that isn't in the main chain\n", __func__, pfrom.GetId());
- }
+ if (!pindex) {
+ return;
+ }
+ if (!BlockRequestAllowed(pindex)) {
+ LogPrint(BCLog::NET, "%s: ignoring request from peer=%i for old block that isn't in the main chain\n", __func__, pfrom.GetId());
+ return;
}
const CNetMsgMaker msgMaker(pfrom.GetCommonVersion());
// disconnect node in case we have reached the outbound limit for serving historical blocks
- if (send &&
- connman.OutboundTargetReached(true) &&
+ if (m_connman.OutboundTargetReached(true) &&
(((pindexBestHeader != nullptr) && (pindexBestHeader->GetBlockTime() - pindex->GetBlockTime() > HISTORICAL_BLOCK_AGE)) || inv.IsMsgFilteredBlk()) &&
!pfrom.HasPermission(PF_DOWNLOAD) // nodes with the download permission may exceed target
) {
LogPrint(BCLog::NET, "historical block serving limit reached, disconnect peer=%d\n", pfrom.GetId());
-
- //disconnect node
pfrom.fDisconnect = true;
- send = false;
+ return;
}
// Avoid leaking prune-height by never sending blocks below the NODE_NETWORK_LIMITED threshold
- if (send && !pfrom.HasPermission(PF_NOBAN) && (
+ if (!pfrom.HasPermission(PF_NOBAN) && (
(((pfrom.GetLocalServices() & NODE_NETWORK_LIMITED) == NODE_NETWORK_LIMITED) && ((pfrom.GetLocalServices() & NODE_NETWORK) != NODE_NETWORK) && (m_chainman.ActiveChain().Tip()->nHeight - pindex->nHeight > (int)NODE_NETWORK_LIMITED_MIN_BLOCKS + 2 /* add two blocks buffer extension for possible races */) )
)) {
- LogPrint(BCLog::NET, "Ignore block request below NODE_NETWORK_LIMITED threshold from peer=%d\n", pfrom.GetId());
-
+ LogPrint(BCLog::NET, "Ignore block request below NODE_NETWORK_LIMITED threshold, disconnect peer=%d\n", pfrom.GetId());
//disconnect node and prevent it from stalling (would otherwise wait for the missing block)
pfrom.fDisconnect = true;
- send = false;
+ return;
}
// Pruned nodes may have deleted the block, so check whether
// it's available before trying to send.
- if (send && (pindex->nStatus & BLOCK_HAVE_DATA))
- {
- std::shared_ptr<const CBlock> pblock;
- if (a_recent_block && a_recent_block->GetHash() == pindex->GetBlockHash()) {
- pblock = a_recent_block;
- } else if (inv.IsMsgWitnessBlk()) {
- // Fast-path: in this case it is possible to serve the block directly from disk,
- // as the network format matches the format on disk
- std::vector<uint8_t> block_data;
- if (!ReadRawBlockFromDisk(block_data, pindex, chainparams.MessageStart())) {
- assert(!"cannot load block from disk");
- }
- connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::BLOCK, MakeSpan(block_data)));
- // Don't set pblock as we've sent the block
- } else {
- // Send block from disk
- std::shared_ptr<CBlock> pblockRead = std::make_shared<CBlock>();
- if (!ReadBlockFromDisk(*pblockRead, pindex, consensusParams))
- assert(!"cannot load block from disk");
- pblock = pblockRead;
+ if (!(pindex->nStatus & BLOCK_HAVE_DATA)) {
+ return;
+ }
+ std::shared_ptr<const CBlock> pblock;
+ if (a_recent_block && a_recent_block->GetHash() == pindex->GetBlockHash()) {
+ pblock = a_recent_block;
+ } else if (inv.IsMsgWitnessBlk()) {
+ // Fast-path: in this case it is possible to serve the block directly from disk,
+ // as the network format matches the format on disk
+ std::vector<uint8_t> block_data;
+ if (!ReadRawBlockFromDisk(block_data, pindex, m_chainparams.MessageStart())) {
+ assert(!"cannot load block from disk");
+ }
+ m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::BLOCK, MakeSpan(block_data)));
+ // Don't set pblock as we've sent the block
+ } else {
+ // Send block from disk
+ std::shared_ptr<CBlock> pblockRead = std::make_shared<CBlock>();
+ if (!ReadBlockFromDisk(*pblockRead, pindex, m_chainparams.GetConsensus())) {
+ assert(!"cannot load block from disk");
}
- if (pblock) {
- if (inv.IsMsgBlk()) {
- connman.PushMessage(&pfrom, msgMaker.Make(SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::BLOCK, *pblock));
- } else if (inv.IsMsgWitnessBlk()) {
- connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::BLOCK, *pblock));
- } else if (inv.IsMsgFilteredBlk()) {
- bool sendMerkleBlock = false;
- CMerkleBlock merkleBlock;
- if (pfrom.m_tx_relay != nullptr) {
- LOCK(pfrom.m_tx_relay->cs_filter);
- if (pfrom.m_tx_relay->pfilter) {
- sendMerkleBlock = true;
- merkleBlock = CMerkleBlock(*pblock, *pfrom.m_tx_relay->pfilter);
- }
- }
- if (sendMerkleBlock) {
- connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::MERKLEBLOCK, merkleBlock));
- // CMerkleBlock just contains hashes, so also push any transactions in the block the client did not see
- // This avoids hurting performance by pointlessly requiring a round-trip
- // Note that there is currently no way for a node to request any single transactions we didn't send here -
- // they must either disconnect and retry or request the full block.
- // Thus, the protocol spec specified allows for us to provide duplicate txn here,
- // however we MUST always provide at least what the remote peer needs
- typedef std::pair<unsigned int, uint256> PairType;
- for (PairType& pair : merkleBlock.vMatchedTxn)
- connman.PushMessage(&pfrom, msgMaker.Make(SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::TX, *pblock->vtx[pair.first]));
+ pblock = pblockRead;
+ }
+ if (pblock) {
+ if (inv.IsMsgBlk()) {
+ m_connman.PushMessage(&pfrom, msgMaker.Make(SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::BLOCK, *pblock));
+ } else if (inv.IsMsgWitnessBlk()) {
+ m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::BLOCK, *pblock));
+ } else if (inv.IsMsgFilteredBlk()) {
+ bool sendMerkleBlock = false;
+ CMerkleBlock merkleBlock;
+ if (pfrom.m_tx_relay != nullptr) {
+ LOCK(pfrom.m_tx_relay->cs_filter);
+ if (pfrom.m_tx_relay->pfilter) {
+ sendMerkleBlock = true;
+ merkleBlock = CMerkleBlock(*pblock, *pfrom.m_tx_relay->pfilter);
}
- // else
- // no response
- } else if (inv.IsMsgCmpctBlk()) {
- // If a peer is asking for old blocks, we're almost guaranteed
- // they won't have a useful mempool to match against a compact block,
- // and we don't feel like constructing the object for them, so
- // instead we respond with the full, non-compact block.
- bool fPeerWantsWitness = State(pfrom.GetId())->fWantsCmpctWitness;
- int nSendFlags = fPeerWantsWitness ? 0 : SERIALIZE_TRANSACTION_NO_WITNESS;
- if (CanDirectFetch(consensusParams) && pindex->nHeight >= m_chainman.ActiveChain().Height() - MAX_CMPCTBLOCK_DEPTH) {
- if ((fPeerWantsWitness || !fWitnessesPresentInARecentCompactBlock) && a_recent_compact_block && a_recent_compact_block->header.GetHash() == pindex->GetBlockHash()) {
- connman.PushMessage(&pfrom, msgMaker.Make(nSendFlags, NetMsgType::CMPCTBLOCK, *a_recent_compact_block));
- } else {
- CBlockHeaderAndShortTxIDs cmpctblock(*pblock, fPeerWantsWitness);
- connman.PushMessage(&pfrom, msgMaker.Make(nSendFlags, NetMsgType::CMPCTBLOCK, cmpctblock));
- }
+ }
+ if (sendMerkleBlock) {
+ m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::MERKLEBLOCK, merkleBlock));
+ // CMerkleBlock just contains hashes, so also push any transactions in the block the client did not see
+ // This avoids hurting performance by pointlessly requiring a round-trip
+ // Note that there is currently no way for a node to request any single transactions we didn't send here -
+ // they must either disconnect and retry or request the full block.
+ // Thus, the protocol spec specified allows for us to provide duplicate txn here,
+ // however we MUST always provide at least what the remote peer needs
+ typedef std::pair<unsigned int, uint256> PairType;
+ for (PairType& pair : merkleBlock.vMatchedTxn)
+ m_connman.PushMessage(&pfrom, msgMaker.Make(SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::TX, *pblock->vtx[pair.first]));
+ }
+ // else
+ // no response
+ } else if (inv.IsMsgCmpctBlk()) {
+ // If a peer is asking for old blocks, we're almost guaranteed
+ // they won't have a useful mempool to match against a compact block,
+ // and we don't feel like constructing the object for them, so
+ // instead we respond with the full, non-compact block.
+ bool fPeerWantsWitness = State(pfrom.GetId())->fWantsCmpctWitness;
+ int nSendFlags = fPeerWantsWitness ? 0 : SERIALIZE_TRANSACTION_NO_WITNESS;
+ if (CanDirectFetch() && pindex->nHeight >= m_chainman.ActiveChain().Height() - MAX_CMPCTBLOCK_DEPTH) {
+ if ((fPeerWantsWitness || !fWitnessesPresentInARecentCompactBlock) && a_recent_compact_block && a_recent_compact_block->header.GetHash() == pindex->GetBlockHash()) {
+ m_connman.PushMessage(&pfrom, msgMaker.Make(nSendFlags, NetMsgType::CMPCTBLOCK, *a_recent_compact_block));
} else {
- connman.PushMessage(&pfrom, msgMaker.Make(nSendFlags, NetMsgType::BLOCK, *pblock));
+ CBlockHeaderAndShortTxIDs cmpctblock(*pblock, fPeerWantsWitness);
+ m_connman.PushMessage(&pfrom, msgMaker.Make(nSendFlags, NetMsgType::CMPCTBLOCK, cmpctblock));
}
+ } else {
+ m_connman.PushMessage(&pfrom, msgMaker.Make(nSendFlags, NetMsgType::BLOCK, *pblock));
}
}
+ }
- {
- LOCK(peer.m_block_inv_mutex);
- // Trigger the peer node to send a getblocks request for the next batch of inventory
- if (inv.hash == peer.m_continuation_block) {
- // Send immediately. This must send even if redundant,
- // and we want it right after the last block so they don't
- // wait for other stuff first.
- std::vector<CInv> vInv;
- vInv.push_back(CInv(MSG_BLOCK, m_chainman.ActiveChain().Tip()->GetBlockHash()));
- connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::INV, vInv));
- peer.m_continuation_block.SetNull();
- }
+ {
+ LOCK(peer.m_block_inv_mutex);
+ // Trigger the peer node to send a getblocks request for the next batch of inventory
+ if (inv.hash == peer.m_continuation_block) {
+ // Send immediately. This must send even if redundant,
+ // and we want it right after the last block so they don't
+ // wait for other stuff first.
+ std::vector<CInv> vInv;
+ vInv.push_back(CInv(MSG_BLOCK, m_chainman.ActiveChain().Tip()->GetBlockHash()));
+ m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::INV, vInv));
+ peer.m_continuation_block.SetNull();
}
}
}
@@ -1780,7 +1778,7 @@ void PeerManagerImpl::ProcessGetData(CNode& pfrom, Peer& peer, const std::atomic
if (it != peer.m_getdata_requests.end() && !pfrom.fPauseSend) {
const CInv &inv = *it++;
if (inv.IsGenBlkMsg()) {
- ProcessGetBlockData(pfrom, peer, m_chainparams, inv, m_connman);
+ ProcessGetBlockData(pfrom, peer, inv);
}
// else: If the first item on the queue is an unknown type, we erase it
// and continue processing the queue on the next call.
@@ -1928,10 +1926,9 @@ void PeerManagerImpl::ProcessHeadersMessage(CNode& pfrom, const Peer& peer,
m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::GETHEADERS, m_chainman.ActiveChain().GetLocator(pindexLast), uint256()));
}
- bool fCanDirectFetch = CanDirectFetch(m_chainparams.GetConsensus());
// If this set of headers is valid and ends in a block with at least as
// much work as our tip, download as much as possible.
- if (fCanDirectFetch && pindexLast->IsValid(BLOCK_VALID_TREE) && m_chainman.ActiveChain().Tip()->nChainWork <= pindexLast->nChainWork) {
+ if (CanDirectFetch() && pindexLast->IsValid(BLOCK_VALID_TREE) && m_chainman.ActiveChain().Tip()->nChainWork <= pindexLast->nChainWork) {
std::vector<const CBlockIndex*> vToFetch;
const CBlockIndex *pindexWalk = pindexLast;
// Calculate all the blocks we'd need to switch to pindexLast, up to a limit.
@@ -2042,7 +2039,7 @@ void PeerManagerImpl::ProcessOrphanTx(std::set<uint256>& orphan_work_set)
if (result.m_result_type == MempoolAcceptResult::ResultType::VALID) {
LogPrint(BCLog::MEMPOOL, " accepted orphan tx %s\n", orphanHash.ToString());
- RelayTransaction(orphanHash, porphanTx->GetWitnessHash(), m_connman);
+ RelayTransaction(orphanHash, porphanTx->GetWitnessHash());
m_orphanage.AddChildrenToWorkSet(*porphanTx, orphan_work_set);
m_orphanage.EraseTx(orphanHash);
for (const CTransactionRef& removedTx : result.m_replaced_transactions.value()) {
@@ -2104,7 +2101,6 @@ void PeerManagerImpl::ProcessOrphanTx(std::set<uint256>& orphan_work_set)
* May disconnect from the peer in the case of a bad request.
*
* @param[in] peer The peer that we received the request from
- * @param[in] chain_params Chain parameters
* @param[in] filter_type The filter type the request is for. Must be basic filters.
* @param[in] start_height The start height for the request
* @param[in] stop_hash The stop_hash for the request
@@ -2113,11 +2109,11 @@ void PeerManagerImpl::ProcessOrphanTx(std::set<uint256>& orphan_work_set)
* @param[out] filter_index The filter index, if the request can be serviced.
* @return True if the request can be serviced.
*/
-bool PeerManagerImpl::PrepareBlockFilterRequest(CNode& peer, const CChainParams& chain_params,
- BlockFilterType filter_type, uint32_t start_height,
- const uint256& stop_hash, uint32_t max_height_diff,
- const CBlockIndex*& stop_index,
- BlockFilterIndex*& filter_index)
+bool PeerManagerImpl::PrepareBlockFilterRequest(CNode& peer,
+ BlockFilterType filter_type, uint32_t start_height,
+ const uint256& stop_hash, uint32_t max_height_diff,
+ const CBlockIndex*& stop_index,
+ BlockFilterIndex*& filter_index)
{
const bool supported_filter_type =
(filter_type == BlockFilterType::BASIC &&
@@ -2134,7 +2130,7 @@ bool PeerManagerImpl::PrepareBlockFilterRequest(CNode& peer, const CChainParams&
stop_index = m_chainman.m_blockman.LookupBlockIndex(stop_hash);
// Check that the stop block exists and the peer would be allowed to fetch it.
- if (!stop_index || !BlockRequestAllowed(stop_index, chain_params.GetConsensus())) {
+ if (!stop_index || !BlockRequestAllowed(stop_index)) {
LogPrint(BCLog::NET, "peer %d requested invalid block hash: %s\n",
peer.GetId(), stop_hash.ToString());
peer.fDisconnect = true;
@@ -2173,11 +2169,8 @@ bool PeerManagerImpl::PrepareBlockFilterRequest(CNode& peer, const CChainParams&
*
* @param[in] peer The peer that we received the request from
* @param[in] vRecv The raw message received
- * @param[in] chain_params Chain parameters
- * @param[in] connman Pointer to the connection manager
*/
-void PeerManagerImpl::ProcessGetCFilters(CNode& peer, CDataStream& vRecv, const CChainParams& chain_params,
- CConnman& connman)
+void PeerManagerImpl::ProcessGetCFilters(CNode& peer, CDataStream& vRecv)
{
uint8_t filter_type_ser;
uint32_t start_height;
@@ -2189,7 +2182,7 @@ void PeerManagerImpl::ProcessGetCFilters(CNode& peer, CDataStream& vRecv, const
const CBlockIndex* stop_index;
BlockFilterIndex* filter_index;
- if (!PrepareBlockFilterRequest(peer, chain_params, filter_type, start_height, stop_hash,
+ if (!PrepareBlockFilterRequest(peer, filter_type, start_height, stop_hash,
MAX_GETCFILTERS_SIZE, stop_index, filter_index)) {
return;
}
@@ -2204,7 +2197,7 @@ void PeerManagerImpl::ProcessGetCFilters(CNode& peer, CDataStream& vRecv, const
for (const auto& filter : filters) {
CSerializedNetMsg msg = CNetMsgMaker(peer.GetCommonVersion())
.Make(NetMsgType::CFILTER, filter);
- connman.PushMessage(&peer, std::move(msg));
+ m_connman.PushMessage(&peer, std::move(msg));
}
}
@@ -2215,11 +2208,8 @@ void PeerManagerImpl::ProcessGetCFilters(CNode& peer, CDataStream& vRecv, const
*
* @param[in] peer The peer that we received the request from
* @param[in] vRecv The raw message received
- * @param[in] chain_params Chain parameters
- * @param[in] connman Pointer to the connection manager
*/
-void PeerManagerImpl::ProcessGetCFHeaders(CNode& peer, CDataStream& vRecv, const CChainParams& chain_params,
- CConnman& connman)
+void PeerManagerImpl::ProcessGetCFHeaders(CNode& peer, CDataStream& vRecv)
{
uint8_t filter_type_ser;
uint32_t start_height;
@@ -2231,7 +2221,7 @@ void PeerManagerImpl::ProcessGetCFHeaders(CNode& peer, CDataStream& vRecv, const
const CBlockIndex* stop_index;
BlockFilterIndex* filter_index;
- if (!PrepareBlockFilterRequest(peer, chain_params, filter_type, start_height, stop_hash,
+ if (!PrepareBlockFilterRequest(peer, filter_type, start_height, stop_hash,
MAX_GETCFHEADERS_SIZE, stop_index, filter_index)) {
return;
}
@@ -2260,7 +2250,7 @@ void PeerManagerImpl::ProcessGetCFHeaders(CNode& peer, CDataStream& vRecv, const
stop_index->GetBlockHash(),
prev_header,
filter_hashes);
- connman.PushMessage(&peer, std::move(msg));
+ m_connman.PushMessage(&peer, std::move(msg));
}
/**
@@ -2270,11 +2260,8 @@ void PeerManagerImpl::ProcessGetCFHeaders(CNode& peer, CDataStream& vRecv, const
*
* @param[in] peer The peer that we received the request from
* @param[in] vRecv The raw message received
- * @param[in] chain_params Chain parameters
- * @param[in] connman Pointer to the connection manager
*/
-void PeerManagerImpl::ProcessGetCFCheckPt(CNode& peer, CDataStream& vRecv, const CChainParams& chain_params,
- CConnman& connman)
+void PeerManagerImpl::ProcessGetCFCheckPt(CNode& peer, CDataStream& vRecv)
{
uint8_t filter_type_ser;
uint256 stop_hash;
@@ -2285,7 +2272,7 @@ void PeerManagerImpl::ProcessGetCFCheckPt(CNode& peer, CDataStream& vRecv, const
const CBlockIndex* stop_index;
BlockFilterIndex* filter_index;
- if (!PrepareBlockFilterRequest(peer, chain_params, filter_type, /*start_height=*/0, stop_hash,
+ if (!PrepareBlockFilterRequest(peer, filter_type, /*start_height=*/0, stop_hash,
/*max_height_diff=*/std::numeric_limits<uint32_t>::max(),
stop_index, filter_index)) {
return;
@@ -2311,7 +2298,7 @@ void PeerManagerImpl::ProcessGetCFCheckPt(CNode& peer, CDataStream& vRecv, const
filter_type_ser,
stop_index->GetBlockHash(),
headers);
- connman.PushMessage(&peer, std::move(msg));
+ m_connman.PushMessage(&peer, std::move(msg));
}
void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDataStream& vRecv,
@@ -2347,7 +2334,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
nServices = ServiceFlags(nServiceInt);
if (!pfrom.IsInboundConn())
{
- m_connman.SetServices(pfrom.addr, nServices);
+ m_addrman.SetServices(pfrom.addr, nServices);
}
if (pfrom.ExpectServicesFromConn() && !HasAllDesirableServiceFlags(nServices))
{
@@ -2491,7 +2478,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
//
// This moves an address from New to Tried table in Addrman,
// resolves tried-table collisions, etc.
- m_connman.MarkAddressGood(pfrom.addr);
+ m_addrman.Good(pfrom.addr);
}
std::string remoteAddr;
@@ -2696,7 +2683,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
if (fReachable)
vAddrOk.push_back(addr);
}
- m_connman.AddNewAddresses(vAddrOk, pfrom.addr, 2 * 60 * 60);
+ m_addrman.Add(vAddrOk, pfrom.addr, 2 * 60 * 60);
if (vAddr.size() < 1000)
pfrom.fGetAddr = false;
if (pfrom.IsAddrFetchConn()) {
@@ -2949,7 +2936,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
return;
}
- if (!BlockRequestAllowed(pindex, m_chainparams.GetConsensus())) {
+ if (!BlockRequestAllowed(pindex)) {
LogPrint(BCLog::NET, "%s: ignoring request from peer=%i for old block header that isn't in the main chain\n", __func__, pfrom.GetId());
return;
}
@@ -3046,7 +3033,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
LogPrintf("Not relaying non-mempool transaction %s from forcerelay peer=%d\n", tx.GetHash().ToString(), pfrom.GetId());
} else {
LogPrintf("Force relaying tx %s from peer=%d\n", tx.GetHash().ToString(), pfrom.GetId());
- RelayTransaction(tx.GetHash(), tx.GetWitnessHash(), m_connman);
+ RelayTransaction(tx.GetHash(), tx.GetWitnessHash());
}
}
return;
@@ -3061,7 +3048,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
// requests for it.
m_txrequest.ForgetTxHash(tx.GetHash());
m_txrequest.ForgetTxHash(tx.GetWitnessHash());
- RelayTransaction(tx.GetHash(), tx.GetWitnessHash(), m_connman);
+ RelayTransaction(tx.GetHash(), tx.GetWitnessHash());
m_orphanage.AddChildrenToWorkSet(tx, peer->m_orphan_work_set);
pfrom.nLastTXTime = GetTime();
@@ -3287,8 +3274,9 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
}
// If we're not close to tip yet, give up and let parallel block fetch work its magic
- if (!fAlreadyInFlight && !CanDirectFetch(m_chainparams.GetConsensus()))
+ if (!fAlreadyInFlight && !CanDirectFetch()) {
return;
+ }
if (IsWitnessEnabled(pindex->pprev, m_chainparams.GetConsensus()) && !nodestate->fSupportsDesiredCmpctVersion) {
// Don't bother trying to process compact blocks from v1 peers
@@ -3781,17 +3769,17 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
}
if (msg_type == NetMsgType::GETCFILTERS) {
- ProcessGetCFilters(pfrom, vRecv, m_chainparams, m_connman);
+ ProcessGetCFilters(pfrom, vRecv);
return;
}
if (msg_type == NetMsgType::GETCFHEADERS) {
- ProcessGetCFHeaders(pfrom, vRecv, m_chainparams, m_connman);
+ ProcessGetCFHeaders(pfrom, vRecv);
return;
}
if (msg_type == NetMsgType::GETCFCHECKPT) {
- ProcessGetCFCheckPt(pfrom, vRecv, m_chainparams, m_connman);
+ ProcessGetCFCheckPt(pfrom, vRecv);
return;
}
@@ -4106,7 +4094,7 @@ void PeerManagerImpl::CheckForStaleTipAndEvictPeers()
m_stale_tip_check_time = time_in_seconds + STALE_CHECK_INTERVAL;
}
- if (!m_initial_sync_finished && CanDirectFetch(m_chainparams.GetConsensus())) {
+ if (!m_initial_sync_finished && CanDirectFetch()) {
m_connman.StartExtraBlockRelayPeers();
m_initial_sync_finished = true;
}
@@ -4705,7 +4693,10 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
//
// Message: feefilter
//
- if (pto->m_tx_relay != nullptr && pto->GetCommonVersion() >= FEEFILTER_VERSION && gArgs.GetBoolArg("-feefilter", DEFAULT_FEEFILTER) &&
+ if (pto->m_tx_relay != nullptr &&
+ !m_ignore_incoming_txs &&
+ pto->GetCommonVersion() >= FEEFILTER_VERSION &&
+ gArgs.GetBoolArg("-feefilter", DEFAULT_FEEFILTER) &&
!pto->HasPermission(PF_FORCERELAY) // peers with the forcerelay permission should not filter txs to us
) {
CAmount currentFilter = m_mempool.GetMinFee(gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000).GetFeePerK();
diff --git a/src/net_processing.h b/src/net_processing.h
index 6f900410a7..4556d32377 100644
--- a/src/net_processing.h
+++ b/src/net_processing.h
@@ -10,6 +10,7 @@
#include <sync.h>
#include <validationinterface.h>
+class CAddrMan;
class CChainParams;
class CTxMemPool;
class ChainstateManager;
@@ -36,9 +37,9 @@ struct CNodeStateStats {
class PeerManager : public CValidationInterface, public NetEventsInterface
{
public:
- static std::unique_ptr<PeerManager> make(const CChainParams& chainparams, CConnman& connman, BanMan* banman,
- CScheduler& scheduler, ChainstateManager& chainman, CTxMemPool& pool,
- bool ignore_incoming_txs);
+ static std::unique_ptr<PeerManager> make(const CChainParams& chainparams, CConnman& connman, CAddrMan& addrman,
+ BanMan* banman, CScheduler& scheduler, ChainstateManager& chainman,
+ CTxMemPool& pool, bool ignore_incoming_txs);
virtual ~PeerManager() { }
/** Get statistics from node state */
@@ -47,6 +48,10 @@ public:
/** Whether this node ignores txs received over p2p. */
virtual bool IgnoresIncomingTxs() = 0;
+ /** Relay transaction to all peers. */
+ virtual void RelayTransaction(const uint256& txid, const uint256& wtxid)
+ EXCLUSIVE_LOCKS_REQUIRED(cs_main) = 0;
+
/** Send ping message to all peers */
virtual void SendPings() = 0;
@@ -71,7 +76,4 @@ public:
const std::chrono::microseconds time_received, const std::atomic<bool>& interruptMsgProc) = 0;
};
-/** Relay transaction to every node */
-void RelayTransaction(const uint256& txid, const uint256& wtxid, const CConnman& connman) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
-
#endif // BITCOIN_NET_PROCESSING_H
diff --git a/src/netbase.cpp b/src/netbase.cpp
index ac2392ebed..49e455aa84 100644
--- a/src/netbase.cpp
+++ b/src/netbase.cpp
@@ -194,12 +194,12 @@ bool LookupHost(const std::string& name, CNetAddr& addr, bool fAllowLookup, DNSL
return true;
}
-bool Lookup(const std::string& name, std::vector<CService>& vAddr, int portDefault, bool fAllowLookup, unsigned int nMaxSolutions, DNSLookupFn dns_lookup_function)
+bool Lookup(const std::string& name, std::vector<CService>& vAddr, uint16_t portDefault, bool fAllowLookup, unsigned int nMaxSolutions, DNSLookupFn dns_lookup_function)
{
if (name.empty() || !ValidAsCString(name)) {
return false;
}
- int port = portDefault;
+ uint16_t port{portDefault};
std::string hostname;
SplitHostPort(name, port, hostname);
@@ -213,7 +213,7 @@ bool Lookup(const std::string& name, std::vector<CService>& vAddr, int portDefau
return true;
}
-bool Lookup(const std::string& name, CService& addr, int portDefault, bool fAllowLookup, DNSLookupFn dns_lookup_function)
+bool Lookup(const std::string& name, CService& addr, uint16_t portDefault, bool fAllowLookup, DNSLookupFn dns_lookup_function)
{
if (!ValidAsCString(name)) {
return false;
@@ -226,7 +226,7 @@ bool Lookup(const std::string& name, CService& addr, int portDefault, bool fAllo
return true;
}
-CService LookupNumeric(const std::string& name, int portDefault, DNSLookupFn dns_lookup_function)
+CService LookupNumeric(const std::string& name, uint16_t portDefault, DNSLookupFn dns_lookup_function)
{
if (!ValidAsCString(name)) {
return {};
@@ -363,7 +363,7 @@ static std::string Socks5ErrorString(uint8_t err)
}
}
-bool Socks5(const std::string& strDest, int port, const ProxyCredentials* auth, const Sock& sock)
+bool Socks5(const std::string& strDest, uint16_t port, const ProxyCredentials* auth, const Sock& sock)
{
IntrRecvError recvr;
LogPrint(BCLog::NET, "SOCKS5 connecting %s\n", strDest);
@@ -665,7 +665,7 @@ bool IsProxy(const CNetAddr &addr) {
return false;
}
-bool ConnectThroughProxy(const proxyType& proxy, const std::string& strDest, int port, const Sock& sock, int nTimeout, bool& outProxyConnectionFailed)
+bool ConnectThroughProxy(const proxyType& proxy, const std::string& strDest, uint16_t port, const Sock& sock, int nTimeout, bool& outProxyConnectionFailed)
{
// first connect to proxy server
if (!ConnectSocketDirectly(proxy.proxy, sock.Get(), nTimeout, true)) {
@@ -677,11 +677,11 @@ bool ConnectThroughProxy(const proxyType& proxy, const std::string& strDest, int
ProxyCredentials random_auth;
static std::atomic_int counter(0);
random_auth.username = random_auth.password = strprintf("%i", counter++);
- if (!Socks5(strDest, (uint16_t)port, &random_auth, sock)) {
+ if (!Socks5(strDest, port, &random_auth, sock)) {
return false;
}
} else {
- if (!Socks5(strDest, (uint16_t)port, 0, sock)) {
+ if (!Socks5(strDest, port, 0, sock)) {
return false;
}
}
diff --git a/src/netbase.h b/src/netbase.h
index e98a21ce1f..08172b9984 100644
--- a/src/netbase.h
+++ b/src/netbase.h
@@ -111,7 +111,7 @@ extern DNSLookupFn g_dns_lookup;
* @returns Whether or not the specified host string successfully resolved to
* any resulting network addresses.
*
- * @see Lookup(const std::string&, std::vector<CService>&, int, bool, unsigned int, DNSLookupFn)
+ * @see Lookup(const std::string&, std::vector<CService>&, uint16_t, bool, unsigned int, DNSLookupFn)
* for additional parameter descriptions.
*/
bool LookupHost(const std::string& name, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions, bool fAllowLookup, DNSLookupFn dns_lookup_function = g_dns_lookup);
@@ -119,7 +119,7 @@ bool LookupHost(const std::string& name, std::vector<CNetAddr>& vIP, unsigned in
/**
* Resolve a host string to its first corresponding network address.
*
- * @see LookupHost(const std::string&, std::vector<CNetAddr>&, unsigned int, bool, DNSLookupFn)
+ * @see LookupHost(const std::string&, std::vector<CNetAddr>&, uint16_t, bool, DNSLookupFn)
* for additional parameter descriptions.
*/
bool LookupHost(const std::string& name, CNetAddr& addr, bool fAllowLookup, DNSLookupFn dns_lookup_function = g_dns_lookup);
@@ -129,7 +129,7 @@ bool LookupHost(const std::string& name, CNetAddr& addr, bool fAllowLookup, DNSL
*
* @param name The string representing a service. Could be a name or a
* numerical IP address (IPv6 addresses should be in their
- * disambiguated bracketed form), optionally followed by a port
+ * disambiguated bracketed form), optionally followed by a uint16_t port
* number. (e.g. example.com:8333 or
* [2001:db8:85a3:8d3:1319:8a2e:370:7348]:420)
* @param[out] vAddr The resulting services to which the specified service string
@@ -144,15 +144,15 @@ bool LookupHost(const std::string& name, CNetAddr& addr, bool fAllowLookup, DNSL
* @returns Whether or not the service string successfully resolved to any
* resulting services.
*/
-bool Lookup(const std::string& name, std::vector<CService>& vAddr, int portDefault, bool fAllowLookup, unsigned int nMaxSolutions, DNSLookupFn dns_lookup_function = g_dns_lookup);
+bool Lookup(const std::string& name, std::vector<CService>& vAddr, uint16_t portDefault, bool fAllowLookup, unsigned int nMaxSolutions, DNSLookupFn dns_lookup_function = g_dns_lookup);
/**
* Resolve a service string to its first corresponding service.
*
- * @see Lookup(const std::string&, std::vector<CService>&, int, bool, unsigned int, DNSLookupFn)
+ * @see Lookup(const std::string&, std::vector<CService>&, uint16_t, bool, unsigned int, DNSLookupFn)
* for additional parameter descriptions.
*/
-bool Lookup(const std::string& name, CService& addr, int portDefault, bool fAllowLookup, DNSLookupFn dns_lookup_function = g_dns_lookup);
+bool Lookup(const std::string& name, CService& addr, uint16_t portDefault, bool fAllowLookup, DNSLookupFn dns_lookup_function = g_dns_lookup);
/**
* Resolve a service string with a numeric IP to its first corresponding
@@ -160,10 +160,10 @@ bool Lookup(const std::string& name, CService& addr, int portDefault, bool fAllo
*
* @returns The resulting CService if the resolution was successful, [::]:0 otherwise.
*
- * @see Lookup(const std::string&, std::vector<CService>&, int, bool, unsigned int, DNSLookupFn)
+ * @see Lookup(const std::string&, std::vector<CService>&, uint16_t, bool, unsigned int, DNSLookupFn)
* for additional parameter descriptions.
*/
-CService LookupNumeric(const std::string& name, int portDefault = 0, DNSLookupFn dns_lookup_function = g_dns_lookup);
+CService LookupNumeric(const std::string& name, uint16_t portDefault = 0, DNSLookupFn dns_lookup_function = g_dns_lookup);
/**
* Parse and resolve a specified subnet string into the appropriate internal
@@ -219,7 +219,7 @@ bool ConnectSocketDirectly(const CService &addrConnect, const SOCKET& hSocket, i
*
* @returns Whether or not the operation succeeded.
*/
-bool ConnectThroughProxy(const proxyType& proxy, const std::string& strDest, int port, const Sock& sock, int nTimeout, bool& outProxyConnectionFailed);
+bool ConnectThroughProxy(const proxyType& proxy, const std::string& strDest, uint16_t port, const Sock& sock, int nTimeout, bool& outProxyConnectionFailed);
/** Disable or enable blocking-mode for a socket */
bool SetSocketNonBlocking(const SOCKET& hSocket, bool fNonBlocking);
@@ -245,6 +245,6 @@ void InterruptSocks5(bool interrupt);
* @see <a href="https://www.ietf.org/rfc/rfc1928.txt">RFC1928: SOCKS Protocol
* Version 5</a>
*/
-bool Socks5(const std::string& strDest, int port, const ProxyCredentials* auth, const Sock& socket);
+bool Socks5(const std::string& strDest, uint16_t port, const ProxyCredentials* auth, const Sock& socket);
#endif // BITCOIN_NETBASE_H
diff --git a/src/node/coinstats.cpp b/src/node/coinstats.cpp
index 88bdba5953..268580c6e6 100644
--- a/src/node/coinstats.cpp
+++ b/src/node/coinstats.cpp
@@ -15,6 +15,7 @@
#include <map>
+// Database-independent metric indicating the UTXO set size
static uint64_t GetBogoSize(const CScript& scriptPubKey)
{
return 32 /* txid */ +
diff --git a/src/node/context.cpp b/src/node/context.cpp
index 958221a913..6d22a6b110 100644
--- a/src/node/context.cpp
+++ b/src/node/context.cpp
@@ -4,6 +4,7 @@
#include <node/context.h>
+#include <addrman.h>
#include <banman.h>
#include <interfaces/chain.h>
#include <net.h>
diff --git a/src/node/context.h b/src/node/context.h
index 9b611bf8f5..2be9a584e6 100644
--- a/src/node/context.h
+++ b/src/node/context.h
@@ -12,6 +12,7 @@
class ArgsManager;
class BanMan;
+class CAddrMan;
class CBlockPolicyEstimator;
class CConnman;
class CScheduler;
@@ -35,6 +36,7 @@ class WalletClient;
//! any member functions. It should just be a collection of references that can
//! be used without pulling in unwanted dependencies or functionality.
struct NodeContext {
+ std::unique_ptr<CAddrMan> addrman;
std::unique_ptr<CConnman> connman;
std::unique_ptr<CTxMemPool> mempool;
std::unique_ptr<CBlockPolicyEstimator> fee_estimator;
diff --git a/src/node/transaction.cpp b/src/node/transaction.cpp
index 97763f4fa2..f47e85aceb 100644
--- a/src/node/transaction.cpp
+++ b/src/node/transaction.cpp
@@ -29,9 +29,9 @@ static TransactionError HandleATMPError(const TxValidationState& state, std::str
TransactionError BroadcastTransaction(NodeContext& node, const CTransactionRef tx, std::string& err_string, const CAmount& max_tx_fee, bool relay, bool wait_callback)
{
// BroadcastTransaction can be called by either sendrawtransaction RPC or wallet RPCs.
- // node.connman is assigned both before chain clients and before RPC server is accepting calls,
- // and reset after chain clients and RPC sever are stopped. node.connman should never be null here.
- assert(node.connman);
+ // node.peerman is assigned both before chain clients and before RPC server is accepting calls,
+ // and reset after chain clients and RPC sever are stopped. node.peerman should never be null here.
+ assert(node.peerman);
assert(node.mempool);
std::promise<void> promise;
uint256 hashTx = tx->GetHash();
@@ -101,7 +101,7 @@ TransactionError BroadcastTransaction(NodeContext& node, const CTransactionRef t
node.mempool->AddUnbroadcastTx(hashTx);
LOCK(cs_main);
- RelayTransaction(hashTx, tx->GetWitnessHash(), *node.connman);
+ node.peerman->RelayTransaction(hashTx, tx->GetWitnessHash());
}
return TransactionError::OK;
diff --git a/src/qt/Makefile b/src/qt/Makefile
index b9dcf0c599..3bd6199059 100644
--- a/src/qt/Makefile
+++ b/src/qt/Makefile
@@ -7,3 +7,5 @@ check: FORCE
$(MAKE) -C .. test_bitcoin_qt_check
bitcoin-qt bitcoin-qt.exe: FORCE
$(MAKE) -C .. bitcoin_qt
+apk: FORCE
+ $(MAKE) -C .. bitcoin_qt_apk
diff --git a/src/qt/android/AndroidManifest.xml b/src/qt/android/AndroidManifest.xml
new file mode 100644
index 0000000000..abb88fe89d
--- /dev/null
+++ b/src/qt/android/AndroidManifest.xml
@@ -0,0 +1,38 @@
+<?xml version='1.0' encoding='utf-8'?>
+<manifest package="org.bitcoincore.qt" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="1.0" android:versionCode="1" android:installLocation="auto">
+ <uses-sdk android:targetSdkVersion="24"/>
+
+ <uses-permission android:name="android.permission.INTERNET" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+
+ <uses-feature android:glEsVersion="0x00020000" android:required="true" />
+
+ <supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>
+
+ <application android:hardwareAccelerated="true" android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="Bitcoin Core">
+ <activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation|mcc|mnc|density"
+ android:name="org.bitcoincore.qt.BitcoinQtActivity"
+ android:label="Bitcoin Core"
+ android:icon="@drawable/bitcoin"
+ android:screenOrientation="unspecified"
+ android:launchMode="singleTop">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+
+ <meta-data android:name="android.app.arguments" android:value="-testnet"/>
+ <meta-data android:name="android.app.lib_name" android:value="bitcoin-qt"/>
+ <meta-data android:name="android.app.repository" android:value="default"/>
+ <meta-data android:name="android.app.bundle_local_qt_libs" android:value="1"/>
+ <meta-data android:name="android.app.use_local_qt_libs" android:value="1"/>
+ <meta-data android:name="android.app.libs_prefix" android:value="/data/local/tmp/qt/"/>
+ <meta-data android:name="android.app.system_libs_prefix" android:value="/system/lib/"/>
+ <meta-data android:name="android.app.background_running" android:value="true"/>
+ <meta-data android:name="android.app.auto_screen_scale_factor" android:value="true"/>
+ <meta-data android:name="android.app.extract_android_style" android:value="default"/>
+ </activity>
+
+ </application>
+</manifest>
diff --git a/src/qt/android/build.gradle b/src/qt/android/build.gradle
new file mode 100644
index 0000000000..4c36e79db8
--- /dev/null
+++ b/src/qt/android/build.gradle
@@ -0,0 +1,52 @@
+buildscript {
+ repositories {
+ google()
+ jcenter()
+ }
+
+ dependencies {
+ classpath 'com.android.tools.build:gradle:3.1.0'
+ }
+}
+
+repositories {
+ google()
+ jcenter()
+}
+
+apply plugin: 'com.android.application'
+
+dependencies {
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
+}
+
+android {
+ compileSdkVersion androidCompileSdkVersion.toInteger()
+
+ buildToolsVersion androidBuildToolsVersion
+
+ sourceSets {
+ main {
+ manifest.srcFile 'AndroidManifest.xml'
+ java.srcDirs = [qt5AndroidDir + '/src', 'src', 'java']
+ aidl.srcDirs = [qt5AndroidDir + '/src', 'src', 'aidl']
+ res.srcDirs = [qt5AndroidDir + '/res', 'res']
+ resources.srcDirs = ['src']
+ renderscript.srcDirs = ['src']
+ assets.srcDirs = ['assets']
+ jniLibs.srcDirs = ['libs']
+ }
+ }
+
+ lintOptions {
+ abortOnError false
+ }
+
+ dexOptions {
+ javaMaxHeapSize '4g'
+ }
+
+ defaultConfig {
+ minSdkVersion 24
+ }
+}
diff --git a/src/qt/android/gradle.properties b/src/qt/android/gradle.properties
new file mode 100644
index 0000000000..838870f62d
--- /dev/null
+++ b/src/qt/android/gradle.properties
@@ -0,0 +1,4 @@
+androidBuildToolsVersion=28.0.3
+androidCompileSdkVersion=28
+qt5AndroidDir=new File(".").absolutePath
+org.gradle.jvmargs=-Xmx4608M
diff --git a/src/qt/android/res/drawable-hdpi/bitcoin.png b/src/qt/android/res/drawable-hdpi/bitcoin.png
new file mode 100644
index 0000000000..31a556a35f
--- /dev/null
+++ b/src/qt/android/res/drawable-hdpi/bitcoin.png
Binary files differ
diff --git a/src/qt/android/res/drawable-ldpi/bitcoin.png b/src/qt/android/res/drawable-ldpi/bitcoin.png
new file mode 100644
index 0000000000..76d80d4196
--- /dev/null
+++ b/src/qt/android/res/drawable-ldpi/bitcoin.png
Binary files differ
diff --git a/src/qt/android/res/drawable-mdpi/bitcoin.png b/src/qt/android/res/drawable-mdpi/bitcoin.png
new file mode 100644
index 0000000000..c2aeab851a
--- /dev/null
+++ b/src/qt/android/res/drawable-mdpi/bitcoin.png
Binary files differ
diff --git a/src/qt/android/res/drawable-xhdpi/bitcoin.png b/src/qt/android/res/drawable-xhdpi/bitcoin.png
new file mode 100644
index 0000000000..2bd5e3defc
--- /dev/null
+++ b/src/qt/android/res/drawable-xhdpi/bitcoin.png
Binary files differ
diff --git a/src/qt/android/res/drawable-xxhdpi/bitcoin.png b/src/qt/android/res/drawable-xxhdpi/bitcoin.png
new file mode 100644
index 0000000000..d236cf2132
--- /dev/null
+++ b/src/qt/android/res/drawable-xxhdpi/bitcoin.png
Binary files differ
diff --git a/src/qt/android/res/drawable-xxxhdpi/bitcoin.png b/src/qt/android/res/drawable-xxxhdpi/bitcoin.png
new file mode 100644
index 0000000000..bb1dbc3554
--- /dev/null
+++ b/src/qt/android/res/drawable-xxxhdpi/bitcoin.png
Binary files differ
diff --git a/src/qt/android/src/org/bitcoincore/qt/BitcoinQtActivity.java b/src/qt/android/src/org/bitcoincore/qt/BitcoinQtActivity.java
new file mode 100644
index 0000000000..cf3b4f6668
--- /dev/null
+++ b/src/qt/android/src/org/bitcoincore/qt/BitcoinQtActivity.java
@@ -0,0 +1,29 @@
+package org.bitcoincore.qt;
+
+import android.os.Bundle;
+import android.system.ErrnoException;
+import android.system.Os;
+
+import org.qtproject.qt5.android.bindings.QtActivity;
+
+import java.io.File;
+
+public class BitcoinQtActivity extends QtActivity
+{
+ @Override
+ public void onCreate(Bundle savedInstanceState)
+ {
+ final File bitcoinDir = new File(getFilesDir().getAbsolutePath() + "/.bitcoin");
+ if (!bitcoinDir.exists()) {
+ bitcoinDir.mkdir();
+ }
+
+ try {
+ Os.setenv("QT_QPA_PLATFORM", "android", true);
+ } catch (ErrnoException e) {
+ e.printStackTrace();
+ }
+
+ super.onCreate(savedInstanceState);
+ }
+}
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp
index 791a29f7a0..fc6d0febc2 100644
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -466,6 +466,12 @@ int GuiMain(int argc, char* argv[])
QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+#if defined(QT_QPA_PLATFORM_ANDROID)
+ QApplication::setAttribute(Qt::AA_DontUseNativeMenuBar);
+ QApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
+ QApplication::setAttribute(Qt::AA_DontUseNativeDialogs);
+#endif
+
BitcoinApplication app;
QFontDatabase::addApplicationFont(":/fonts/monospace");
diff --git a/src/qt/createwalletdialog.cpp b/src/qt/createwalletdialog.cpp
index 1467801522..113bd30a0c 100644
--- a/src/qt/createwalletdialog.cpp
+++ b/src/qt/createwalletdialog.cpp
@@ -53,6 +53,12 @@ CreateWalletDialog::CreateWalletDialog(QWidget* parent) :
}
});
+ connect(ui->blank_wallet_checkbox, &QCheckBox::toggled, [this](bool checked) {
+ if (!checked) {
+ ui->disable_privkeys_checkbox->setChecked(false);
+ }
+ });
+
#ifndef USE_SQLITE
ui->descriptor_checkbox->setToolTip(tr("Compiled without sqlite support (required for descriptor wallets)"));
ui->descriptor_checkbox->setEnabled(false);
diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp
index 32890ed0fe..b4afdbcc22 100644
--- a/src/qt/guiutil.cpp
+++ b/src/qt/guiutil.cpp
@@ -759,14 +759,14 @@ QString formatNiceTimeOffset(qint64 secs)
QString formatBytes(uint64_t bytes)
{
- if(bytes < 1024)
+ if (bytes < 1'000)
return QObject::tr("%1 B").arg(bytes);
- if(bytes < 1024 * 1024)
- return QObject::tr("%1 KB").arg(bytes / 1024);
- if(bytes < 1024 * 1024 * 1024)
- return QObject::tr("%1 MB").arg(bytes / 1024 / 1024);
+ if (bytes < 1'000'000)
+ return QObject::tr("%1 kB").arg(bytes / 1'000);
+ if (bytes < 1'000'000'000)
+ return QObject::tr("%1 MB").arg(bytes / 1'000'000);
- return QObject::tr("%1 GB").arg(bytes / 1024 / 1024 / 1024);
+ return QObject::tr("%1 GB").arg(bytes / 1'000'000'000);
}
qreal calculateIdealFontSize(int width, const QString& text, QFont font, qreal minPointSize, qreal font_size) {
diff --git a/src/qt/optionsdialog.h b/src/qt/optionsdialog.h
index 1cc96035c6..ba35ff3b67 100644
--- a/src/qt/optionsdialog.h
+++ b/src/qt/optionsdialog.h
@@ -67,7 +67,7 @@ private Q_SLOTS:
void updateDefaultProxyNets();
Q_SIGNALS:
- void proxyIpChecks(QValidatedLineEdit *pUiProxyIp, int nProxyPort);
+ void proxyIpChecks(QValidatedLineEdit *pUiProxyIp, uint16_t nProxyPort);
private:
Ui::OptionsDialog *ui;
diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp
index 96f6202874..58f6c14e7a 100644
--- a/src/qt/paymentserver.cpp
+++ b/src/qt/paymentserver.cpp
@@ -235,9 +235,9 @@ void PaymentServer::handleURIOrFile(const QString& s)
if (!IsValidDestinationString(recipient.address.toStdString())) {
if (uri.hasQueryItem("r")) { // payment request
Q_EMIT message(tr("URI handling"),
- tr("Cannot process payment request because BIP70 is not supported.")+
- tr("Due to widespread security flaws in BIP70 it's strongly recommended that any merchant instructions to switch wallets be ignored.")+
- tr("If you are receiving this error you should request the merchant provide a BIP21 compatible URI."),
+ tr("Cannot process payment request because BIP70 is not supported.\n"
+ "Due to widespread security flaws in BIP70 it's strongly recommended that any merchant instructions to switch wallets be ignored.\n"
+ "If you are receiving this error you should request the merchant provide a BIP21 compatible URI."),
CClientUIInterface::ICON_WARNING);
}
Q_EMIT message(tr("URI handling"), tr("Invalid payment address %1").arg(recipient.address),
@@ -258,9 +258,9 @@ void PaymentServer::handleURIOrFile(const QString& s)
if (QFile::exists(s)) // payment request file
{
Q_EMIT message(tr("Payment request file handling"),
- tr("Cannot process payment request because BIP70 is not supported.")+
- tr("Due to widespread security flaws in BIP70 it's strongly recommended that any merchant instructions to switch wallets be ignored.")+
- tr("If you are receiving this error you should request the merchant provide a BIP21 compatible URI."),
+ tr("Cannot process payment request because BIP70 is not supported.\n"
+ "Due to widespread security flaws in BIP70 it's strongly recommended that any merchant instructions to switch wallets be ignored.\n"
+ "If you are receiving this error you should request the merchant provide a BIP21 compatible URI."),
CClientUIInterface::ICON_WARNING);
}
}
diff --git a/src/qt/platformstyle.cpp b/src/qt/platformstyle.cpp
index aab8d8e4af..1d0605c903 100644
--- a/src/qt/platformstyle.cpp
+++ b/src/qt/platformstyle.cpp
@@ -18,7 +18,7 @@ static const struct {
/** Extra padding/spacing in transactionview */
const bool useExtraSpacing;
} platform_styles[] = {
- {"macosx", false, false, true},
+ {"macosx", false, true, true},
{"windows", true, false, false},
/* Other: linux, unix, ... */
{"other", true, true, false}
diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp
index b258219894..34d055e5a5 100644
--- a/src/qt/rpcconsole.cpp
+++ b/src/qt/rpcconsole.cpp
@@ -608,7 +608,6 @@ void RPCConsole::setClientModel(ClientModel *model, int bestblock_height, int64_
// set up peer table
ui->peerWidget->setModel(model->getPeerTableModel());
ui->peerWidget->verticalHeader()->hide();
- ui->peerWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
ui->peerWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
ui->peerWidget->setSelectionMode(QAbstractItemView::ExtendedSelection);
ui->peerWidget->setContextMenuPolicy(Qt::CustomContextMenu);
@@ -651,7 +650,6 @@ void RPCConsole::setClientModel(ClientModel *model, int bestblock_height, int64_
// set up ban table
ui->banlistWidget->setModel(model->getBanTableModel());
ui->banlistWidget->verticalHeader()->hide();
- ui->banlistWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
ui->banlistWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
ui->banlistWidget->setSelectionMode(QAbstractItemView::SingleSelection);
ui->banlistWidget->setContextMenuPolicy(Qt::CustomContextMenu);
diff --git a/src/qt/test/compattests.cpp b/src/qt/test/compattests.cpp
deleted file mode 100644
index c76dee5091..0000000000
--- a/src/qt/test/compattests.cpp
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) 2016-2019 The Bitcoin Core developers
-// Distributed under the MIT software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-#if defined(HAVE_CONFIG_H)
-#include <config/bitcoin-config.h>
-#endif
-
-#include <qt/test/compattests.h>
-
-#include <compat/byteswap.h>
-
-void CompatTests::bswapTests()
-{
- // Sibling in bitcoin/src/test/bswap_tests.cpp
- uint16_t u1 = 0x1234;
- uint32_t u2 = 0x56789abc;
- uint64_t u3 = 0xdef0123456789abc;
- uint16_t e1 = 0x3412;
- uint32_t e2 = 0xbc9a7856;
- uint64_t e3 = 0xbc9a78563412f0de;
- QVERIFY(bswap_16(u1) == e1);
- QVERIFY(bswap_32(u2) == e2);
- QVERIFY(bswap_64(u3) == e3);
-}
diff --git a/src/qt/test/compattests.h b/src/qt/test/compattests.h
deleted file mode 100644
index 1af97696b2..0000000000
--- a/src/qt/test/compattests.h
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (c) 2009-2016 The Bitcoin Core developers
-// Distributed under the MIT software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-#ifndef BITCOIN_QT_TEST_COMPATTESTS_H
-#define BITCOIN_QT_TEST_COMPATTESTS_H
-
-#include <QObject>
-#include <QTest>
-
-class CompatTests : public QObject
-{
- Q_OBJECT
-
-private Q_SLOTS:
- void bswapTests();
-};
-
-#endif // BITCOIN_QT_TEST_COMPATTESTS_H
diff --git a/src/qt/test/test_main.cpp b/src/qt/test/test_main.cpp
index a1baf6a402..eb86f027ef 100644
--- a/src/qt/test/test_main.cpp
+++ b/src/qt/test/test_main.cpp
@@ -11,7 +11,6 @@
#include <qt/test/apptests.h>
#include <qt/test/rpcnestedtests.h>
#include <qt/test/uritests.h>
-#include <qt/test/compattests.h>
#include <test/util/setup_common.h>
#ifdef ENABLE_WALLET
@@ -92,10 +91,6 @@ int main(int argc, char* argv[])
if (QTest::qExec(&test3) != 0) {
fInvalid = true;
}
- CompatTests test4;
- if (QTest::qExec(&test4) != 0) {
- fInvalid = true;
- }
#ifdef ENABLE_WALLET
WalletTests test5(app.node());
if (QTest::qExec(&test5) != 0) {
diff --git a/src/qt/trafficgraphwidget.cpp b/src/qt/trafficgraphwidget.cpp
index dabdf9d887..7e12410c80 100644
--- a/src/qt/trafficgraphwidget.cpp
+++ b/src/qt/trafficgraphwidget.cpp
@@ -79,7 +79,7 @@ void TrafficGraphWidget::paintEvent(QPaintEvent *)
int base = floor(log10(fMax));
float val = pow(10.0f, base);
- const QString units = tr("KB/s");
+ const QString units = tr("kB/s");
const float yMarginText = 2.0;
// draw lines
@@ -128,10 +128,10 @@ void TrafficGraphWidget::updateRates()
quint64 bytesIn = clientModel->node().getTotalBytesRecv(),
bytesOut = clientModel->node().getTotalBytesSent();
- float inRate = (bytesIn - nLastBytesIn) / 1024.0f * 1000 / timer->interval();
- float outRate = (bytesOut - nLastBytesOut) / 1024.0f * 1000 / timer->interval();
- vSamplesIn.push_front(inRate);
- vSamplesOut.push_front(outRate);
+ float in_rate_kilobytes_per_sec = static_cast<float>(bytesIn - nLastBytesIn) / timer->interval();
+ float out_rate_kilobytes_per_sec = static_cast<float>(bytesOut - nLastBytesOut) / timer->interval();
+ vSamplesIn.push_front(in_rate_kilobytes_per_sec);
+ vSamplesOut.push_front(out_rate_kilobytes_per_sec);
nLastBytesIn = bytesIn;
nLastBytesOut = bytesOut;
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index b90dc9bf42..f0ad141fa9 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -1050,15 +1050,15 @@ static RPCHelpMan gettxoutsetinfo()
RPCResult{
RPCResult::Type::OBJ, "", "",
{
- {RPCResult::Type::NUM, "height", "The current block height (index)"},
- {RPCResult::Type::STR_HEX, "bestblock", "The hash of the block at the tip of the chain"},
+ {RPCResult::Type::NUM, "height", "The block height (index) of the returned statistics"},
+ {RPCResult::Type::STR_HEX, "bestblock", "The hash of the block at which these statistics are calculated"},
{RPCResult::Type::NUM, "transactions", "The number of transactions with unspent outputs"},
{RPCResult::Type::NUM, "txouts", "The number of unspent transaction outputs"},
{RPCResult::Type::NUM, "bogosize", "A meaningless metric for UTXO set size"},
{RPCResult::Type::STR_HEX, "hash_serialized_2", /* optional */ true, "The serialized hash (only present if 'hash_serialized_2' hash_type is chosen)"},
{RPCResult::Type::STR_HEX, "muhash", /* optional */ true, "The serialized hash (only present if 'muhash' hash_type is chosen)"},
{RPCResult::Type::NUM, "disk_size", "The estimated size of the chainstate on disk"},
- {RPCResult::Type::STR_AMOUNT, "total_amount", "The total amount"},
+ {RPCResult::Type::STR_AMOUNT, "total_amount", "The total amount of coins in the UTXO set"},
}},
RPCExamples{
HelpExampleCli("gettxoutsetinfo", "")
@@ -1113,11 +1113,13 @@ static RPCHelpMan gettxout()
{RPCResult::Type::NUM, "confirmations", "The number of confirmations"},
{RPCResult::Type::STR_AMOUNT, "value", "The transaction value in " + CURRENCY_UNIT},
{RPCResult::Type::OBJ, "scriptPubKey", "", {
- {RPCResult::Type::STR_HEX, "asm", ""},
+ {RPCResult::Type::STR, "asm", ""},
{RPCResult::Type::STR_HEX, "hex", ""},
- {RPCResult::Type::NUM, "reqSigs", "Number of required signatures"},
- {RPCResult::Type::STR_HEX, "type", "The type, eg pubkeyhash"},
- {RPCResult::Type::ARR, "addresses", "array of bitcoin addresses", {{RPCResult::Type::STR, "address", "bitcoin address"}}},
+ {RPCResult::Type::NUM, "reqSigs", /* optional */ true, "(DEPRECATED, returned only if config option -deprecatedrpc=addresses is passed) Number of required signatures"},
+ {RPCResult::Type::STR, "type", "The type, eg pubkeyhash"},
+ {RPCResult::Type::STR, "address", /* optional */ true, "bitcoin address (only if a well-defined address exists)"},
+ {RPCResult::Type::ARR, "addresses", /* optional */ true, "(DEPRECATED, returned only if config option -deprecatedrpc=addresses is passed) Array of bitcoin addresses",
+ {{RPCResult::Type::STR, "address", "bitcoin address"}}},
}},
{RPCResult::Type::BOOL, "coinbase", "Coinbase or not"},
}},
@@ -1775,6 +1777,16 @@ void CalculatePercentilesByWeight(CAmount result[NUM_GETBLOCKSTATS_PERCENTILES],
}
}
+void ScriptPubKeyToUniv(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex)
+{
+ ScriptPubKeyToUniv(scriptPubKey, out, fIncludeHex, IsDeprecatedRPCEnabled("addresses"));
+}
+
+void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry, bool include_hex, int serialize_flags, const CTxUndo* txundo)
+{
+ TxToUniv(tx, hashBlock, IsDeprecatedRPCEnabled("addresses"), entry, include_hex, serialize_flags, txundo);
+}
+
template<typename T>
static inline bool SetHasKeys(const std::set<T>& set) {return false;}
template<typename T, typename Tk, typename... Args>
diff --git a/src/rpc/blockchain.h b/src/rpc/blockchain.h
index d8cae4dd24..e719dfc702 100644
--- a/src/rpc/blockchain.h
+++ b/src/rpc/blockchain.h
@@ -6,6 +6,7 @@
#define BITCOIN_RPC_BLOCKCHAIN_H
#include <amount.h>
+#include <core_io.h>
#include <streams.h>
#include <sync.h>
@@ -54,6 +55,9 @@ UniValue blockheaderToJSON(const CBlockIndex* tip, const CBlockIndex* blockindex
/** Used by getblockstats to get feerates at different percentiles by weight */
void CalculatePercentilesByWeight(CAmount result[NUM_GETBLOCKSTATS_PERCENTILES], std::vector<std::pair<CAmount, int64_t>>& scores, int64_t total_weight);
+void ScriptPubKeyToUniv(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex);
+void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry, bool include_hex = true, int serialize_flags = 0, const CTxUndo* txundo = nullptr);
+
NodeContext& EnsureNodeContext(const util::Ref& context);
CTxMemPool& EnsureMemPool(const util::Ref& context);
ChainstateManager& EnsureChainman(const util::Ref& context);
diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp
index cf4d46cf2c..96533a50c8 100644
--- a/src/rpc/net.cpp
+++ b/src/rpc/net.cpp
@@ -907,14 +907,14 @@ static RPCHelpMan addpeeraddress()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
NodeContext& node = EnsureNodeContext(request.context);
- if (!node.connman) {
- throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
+ if (!node.addrman) {
+ throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Address manager functionality missing or disabled");
}
UniValue obj(UniValue::VOBJ);
std::string addr_string = request.params[0].get_str();
- uint16_t port = request.params[1].get_int();
+ uint16_t port{static_cast<uint16_t>(request.params[1].get_int())};
CNetAddr net_addr;
if (!LookupHost(addr_string, net_addr, false)) {
@@ -925,7 +925,7 @@ static RPCHelpMan addpeeraddress()
address.nTime = GetAdjustedTime();
// The source address is set equal to the address. This is equivalent to the peer
// announcing itself.
- if (!node.connman->AddNewAddresses({address}, address)) {
+ if (!node.addrman->Add(address, address)) {
obj.pushKV("success", false);
return obj;
}
diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp
index 2f92a321f8..7932bd2915 100644
--- a/src/rpc/rawtransaction.cpp
+++ b/src/rpc/rawtransaction.cpp
@@ -35,7 +35,6 @@
#include <validation.h>
#include <validationinterface.h>
-
#include <numeric>
#include <stdint.h>
@@ -132,9 +131,10 @@ static RPCHelpMan getrawtransaction()
{
{RPCResult::Type::STR, "asm", "the asm"},
{RPCResult::Type::STR, "hex", "the hex"},
- {RPCResult::Type::NUM, "reqSigs", "The required sigs"},
+ {RPCResult::Type::NUM, "reqSigs", /* optional */ true, "(DEPRECATED, returned only if config option -deprecatedrpc=addresses is passed) Number of required signatures"},
{RPCResult::Type::STR, "type", "The type, eg 'pubkeyhash'"},
- {RPCResult::Type::ARR, "addresses", "",
+ {RPCResult::Type::STR, "address", /* optional */ true, "bitcoin address (only if a well-defined address exists)"},
+ {RPCResult::Type::ARR, "addresses", /* optional */ true, "(DEPRECATED, returned only if config option -deprecatedrpc=addresses is passed) Array of bitcoin addresses",
{
{RPCResult::Type::STR, "address", "bitcoin address"},
}},
@@ -490,9 +490,10 @@ static RPCHelpMan decoderawtransaction()
{
{RPCResult::Type::STR, "asm", "the asm"},
{RPCResult::Type::STR_HEX, "hex", "the hex"},
- {RPCResult::Type::NUM, "reqSigs", "The required sigs"},
+ {RPCResult::Type::NUM, "reqSigs", /* optional */ true, "(DEPRECATED, returned only if config option -deprecatedrpc=addresses is passed) Number of required signatures"},
{RPCResult::Type::STR, "type", "The type, eg 'pubkeyhash'"},
- {RPCResult::Type::ARR, "addresses", "",
+ {RPCResult::Type::STR, "address", /* optional */ true, "bitcoin address (only if a well-defined address exists)"},
+ {RPCResult::Type::ARR, "addresses", /* optional */ true, "(DEPRECATED, returned only if config option -deprecatedrpc=addresses is passed) Array of bitcoin addresses",
{
{RPCResult::Type::STR, "address", "bitcoin address"},
}},
@@ -548,8 +549,9 @@ static RPCHelpMan decodescript()
{
{RPCResult::Type::STR, "asm", "Script public key"},
{RPCResult::Type::STR, "type", "The output type (e.g. "+GetAllOutputTypes()+")"},
- {RPCResult::Type::NUM, "reqSigs", "The required signatures"},
- {RPCResult::Type::ARR, "addresses", "",
+ {RPCResult::Type::STR, "address", /* optional */ true, "bitcoin address (only if a well-defined address exists)"},
+ {RPCResult::Type::NUM, "reqSigs", /* optional */ true, "(DEPRECATED, returned only if config option -deprecatedrpc=addresses is passed) Number of required signatures"},
+ {RPCResult::Type::ARR, "addresses", /* optional */ true, "(DEPRECATED, returned only if config option -deprecatedrpc=addresses is passed) Array of bitcoin addresses",
{
{RPCResult::Type::STR, "address", "bitcoin address"},
}},
@@ -559,8 +561,9 @@ static RPCHelpMan decodescript()
{RPCResult::Type::STR, "asm", "String representation of the script public key"},
{RPCResult::Type::STR_HEX, "hex", "Hex string of the script public key"},
{RPCResult::Type::STR, "type", "The type of the script public key (e.g. witness_v0_keyhash or witness_v0_scripthash)"},
- {RPCResult::Type::NUM, "reqSigs", "The required signatures (always 1)"},
- {RPCResult::Type::ARR, "addresses", "(always length 1)",
+ {RPCResult::Type::STR, "address", /* optional */ true, "bitcoin address (only if a well-defined address exists)"},
+ {RPCResult::Type::NUM, "reqSigs", /* optional */ true, "(DEPRECATED, returned only if config option -deprecatedrpc=addresses is passed) Number of required signatures"},
+ {RPCResult::Type::ARR, "addresses", /* optional */ true, "(DEPRECATED, returned only if config option -deprecatedrpc=addresses is passed) Array of bitcoin addresses",
{
{RPCResult::Type::STR, "address", "segwit address"},
}},
diff --git a/src/script/standard.cpp b/src/script/standard.cpp
index 4d882cd1f1..700155c8d4 100644
--- a/src/script/standard.cpp
+++ b/src/script/standard.cpp
@@ -220,7 +220,6 @@ bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet)
return true;
}
case TxoutType::MULTISIG:
- // Multisig txns have more than one address...
case TxoutType::NULL_DATA:
case TxoutType::NONSTANDARD:
return false;
@@ -228,6 +227,7 @@ bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet)
assert(false);
}
+// TODO: from v23 ("addresses" and "reqSigs" deprecated) "ExtractDestinations" should be removed
bool ExtractDestinations(const CScript& scriptPubKey, TxoutType& typeRet, std::vector<CTxDestination>& addressRet, int& nRequiredRet)
{
addressRet.clear();
diff --git a/src/script/standard.h b/src/script/standard.h
index d5d87392ad..f2bf4a8af3 100644
--- a/src/script/standard.h
+++ b/src/script/standard.h
@@ -247,6 +247,8 @@ bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet)
* Note: this function confuses destinations (a subset of CScripts that are
* encodable as an address) with key identifiers (of keys involved in a
* CScript), and its use should be phased out.
+ *
+ * TODO: from v23 ("addresses" and "reqSigs" deprecated) "ExtractDestinations" should be removed
*/
bool ExtractDestinations(const CScript& scriptPubKey, TxoutType& typeRet, std::vector<CTxDestination>& addressRet, int& nRequiredRet);
diff --git a/src/test/addrman_tests.cpp b/src/test/addrman_tests.cpp
index 37ff8a9afe..d438537606 100644
--- a/src/test/addrman_tests.cpp
+++ b/src/test/addrman_tests.cpp
@@ -100,7 +100,7 @@ static CNetAddr ResolveIP(const std::string& ip)
return addr;
}
-static CService ResolveService(const std::string& ip, const int port = 0)
+static CService ResolveService(const std::string& ip, uint16_t port = 0)
{
CService serv;
BOOST_CHECK_MESSAGE(Lookup(ip, serv, port, false), strprintf("failed to resolve: %s:%i", ip, port));
diff --git a/src/test/bech32_tests.cpp b/src/test/bech32_tests.cpp
index a2098f4f56..2651e46430 100644
--- a/src/test/bech32_tests.cpp
+++ b/src/test/bech32_tests.cpp
@@ -10,7 +10,7 @@
BOOST_FIXTURE_TEST_SUITE(bech32_tests, BasicTestingSetup)
-BOOST_AUTO_TEST_CASE(bip173_testvectors_valid)
+BOOST_AUTO_TEST_CASE(bech32_testvectors_valid)
{
static const std::string CASES[] = {
"A12UEL5L",
@@ -22,15 +22,35 @@ BOOST_AUTO_TEST_CASE(bip173_testvectors_valid)
"?1ezyfcl",
};
for (const std::string& str : CASES) {
- auto ret = bech32::Decode(str);
- BOOST_CHECK(!ret.first.empty());
- std::string recode = bech32::Encode(ret.first, ret.second);
+ const auto dec = bech32::Decode(str);
+ BOOST_CHECK(dec.encoding == bech32::Encoding::BECH32);
+ std::string recode = bech32::Encode(bech32::Encoding::BECH32, dec.hrp, dec.data);
BOOST_CHECK(!recode.empty());
BOOST_CHECK(CaseInsensitiveEqual(str, recode));
}
}
-BOOST_AUTO_TEST_CASE(bip173_testvectors_invalid)
+BOOST_AUTO_TEST_CASE(bech32m_testvectors_valid)
+{
+ static const std::string CASES[] = {
+ "A1LQFN3A",
+ "a1lqfn3a",
+ "an83characterlonghumanreadablepartthatcontainsthetheexcludedcharactersbioandnumber11sg7hg6",
+ "abcdef1l7aum6echk45nj3s0wdvt2fg8x9yrzpqzd3ryx",
+ "11llllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllludsr8",
+ "split1checkupstagehandshakeupstreamerranterredcaperredlc445v",
+ "?1v759aa"
+ };
+ for (const std::string& str : CASES) {
+ const auto dec = bech32::Decode(str);
+ BOOST_CHECK(dec.encoding == bech32::Encoding::BECH32M);
+ std::string recode = bech32::Encode(bech32::Encoding::BECH32M, dec.hrp, dec.data);
+ BOOST_CHECK(!recode.empty());
+ BOOST_CHECK(CaseInsensitiveEqual(str, recode));
+ }
+}
+
+BOOST_AUTO_TEST_CASE(bech32_testvectors_invalid)
{
static const std::string CASES[] = {
" 1nwldj5",
@@ -49,8 +69,32 @@ BOOST_AUTO_TEST_CASE(bip173_testvectors_invalid)
"A12uEL5L",
};
for (const std::string& str : CASES) {
- auto ret = bech32::Decode(str);
- BOOST_CHECK(ret.first.empty());
+ const auto dec = bech32::Decode(str);
+ BOOST_CHECK(dec.encoding == bech32::Encoding::INVALID);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(bech32m_testvectors_invalid)
+{
+ static const std::string CASES[] = {
+ " 1xj0phk",
+ "\x7f""1g6xzxy",
+ "\x80""1vctc34",
+ "an84characterslonghumanreadablepartthatcontainsthetheexcludedcharactersbioandnumber11d6pts4",
+ "qyrz8wqd2c9m",
+ "1qyrz8wqd2c9m",
+ "y1b0jsk6g",
+ "lt1igcx5c0",
+ "in1muywd",
+ "mm1crxm3i",
+ "au1s5cgom",
+ "M1VUXWEZ",
+ "16plkw9",
+ "1p2gdwpf"
+ };
+ for (const std::string& str : CASES) {
+ const auto dec = bech32::Decode(str);
+ BOOST_CHECK(dec.encoding == bech32::Encoding::INVALID);
}
}
diff --git a/src/test/bswap_tests.cpp b/src/test/bswap_tests.cpp
index c89cb5488d..2dbca4e8b6 100644
--- a/src/test/bswap_tests.cpp
+++ b/src/test/bswap_tests.cpp
@@ -11,7 +11,6 @@ BOOST_FIXTURE_TEST_SUITE(bswap_tests, BasicTestingSetup)
BOOST_AUTO_TEST_CASE(bswap_tests)
{
- // Sibling in bitcoin/src/qt/test/compattests.cpp
uint16_t u1 = 0x1234;
uint32_t u2 = 0x56789abc;
uint64_t u3 = 0xdef0123456789abc;
diff --git a/src/test/data/key_io_invalid.json b/src/test/data/key_io_invalid.json
index 9b52943ac6..abe07dad24 100644
--- a/src/test/data/key_io_invalid.json
+++ b/src/test/data/key_io_invalid.json
@@ -6,177 +6,207 @@
"x"
],
[
- "37qgekLpCCHrQuSjvX3fs496FWTGsHFHizjJAs6NPcR47aefnnCWECAhHV6E3g4YN7u7Yuwod5Y"
+ "2v7k5Bb8Lr1MMgTgW6HAf5YHXi6BzpPjHpQ4srD4RSwHYpzXKiXmLAgiLhkXvp3JF5v7nq45EWr"
],
[
- "dzb7VV1Ui55BARxv7ATxAtCUeJsANKovDGWFVgpTbhq9gvPqP3yv"
+ "RAZzCGtMbiUgMiiyrZySrSpdfnQReFXA3r"
],
[
- "MuNu7ZAEDFiHthiunm7dPjwKqrVNCM3mAz6rP9zFveQu14YA8CxExSJTHcVP9DErn6u84E6Ej7S"
+ "NYamy7tcPQTzoU5iyQojD3sqhiz7zxkvn8"
],
[
- "rPpQpYknyNQ5AEHuY6H8ijJJrYc2nDKKk9jjmKEXsWzyAQcFGpDLU2Zvsmoi8JLR7hAwoy3RQWf"
+ "geaFG555Ex5nyRf7JjW6Pj2GwZA8KYxtJJLbr1eZhVW75STbYBZeRszy3wg4pkKdF4ez9J4wQiz"
],
[
- "4Uc3FmN6NQ6zLBK5QQBXRBUREaaHwCZYsGCueHauuDmJpZKn6jkEskMB2Zi2CNgtb5r6epWEFfUJq"
+ "2Cxmid3c2XQ2zvQ8SA1ha2TKqvqbJS9XFmXRsCneBS3Po7Qqb65z5zNdsoF9AfieXFcpoVPmkmfa"
],
[
- "7aQgR5DFQ25vyXmqZAWmnVCjL3PkBcdVkBUpjrjMTcghHx3E8wb"
+ "gaJ7UVge2njVg9tFTetJrtHgruMm7aQDiSAxfHrVEgzK8N2ooagDVmDkdph434xzc4K96Gjyxcs"
],
[
- "17QpPprjeg69fW1DV8DcYYCKvWjYhXvWkov6MJ1iTTvMFj6weAqW7wybZeH57WTNxXVCRH4veVs"
+ "5JN5BEVQPZ3tAiatz1RGXkrJuE3EC6bervMaPb38wTNgEuZCeqp"
],
[
- "KxuACDviz8Xvpn1xAh9MfopySZNuyajYMZWz16Dv2mHHryznWUp3"
+ "3TnFbyUtBRS5rE1KTW81qLVspjJNaB3uu6uuvLjxhZo2DB6PCGh"
],
[
- "7nK3GSmqdXJQtdohvGfJ7KsSmn3TmGqExug49583bDAL91pVSGq5xS9SHoAYL3Wv3ijKTit65th"
+ "7UgSZGaMaTc4d2mdEgcGBFiMeS6eMsithGUqvBsKTQdGzD7XQDbMEYo3gojdbXEPbUdFF3CQoK72f"
],
[
- "cTivdBmq7bay3RFGEBBuNfMh2P1pDCgRYN2Wbxmgwr4ki3jNUL2va"
+ "9261wfqQqruNDnBDhbbb4tN9oKA1KpRFHeoYeufyJApVGixyAG4V"
],
[
- "gjMV4vjNjyMrna4fsAr8bWxAbwtmMUBXJS3zL4NJt5qjozpbQLmAfK1uA3CquSqsZQMpoD1g2nk"
+ "cS824CTUh18scFmYuqt6BgxuRhdR4dEEnCHs3fzBbcyQgbfasHbw"
],
[
- "emXm1naBMoVzPjbk7xpeTVMFy4oDEe25UmoyGgKEB1gGWsK8kRGs"
+ "tc1q0ywf7wkz6t580n3yemd3ucfw8jxn93tpc6wskt"
],
[
- "7VThQnNRj1o3Zyvc7XHPRrjDf8j2oivPTeDXnRPYWeYGE4pXeRJDZgf28ppti5hsHWXS2GSobdqyo"
+ "bt1pxeeuh96wpm5c6u3kavts2qgwlv6y8um7u7ga6ltlwrhrv7w9vers8lgt3k"
],
[
- "1G9u6oCVCPh2o8m3t55ACiYvG1y5BHewUkDSdiQarDcYXXhFHYdzMdYfUAhfxn5vNZBwpgUNpso"
+ "tb130lvl2lyugsk2tf3zhwcjjv39dmwt2tt7ytqaexy8edwcuwks6p5scll5kz"
],
[
- "31QQ7ZMLkScDiB4VyZjuptr7AEc9j1SjstF7pRoLhHTGkW4Q2y9XELobQmhhWxeRvqcukGd1XCq"
+ "bcrt1rhsveeudk"
],
[
- "DHqKSnpxa8ZdQyH8keAhvLTrfkyBMQxqngcQA5N8LQ9KVt25kmGN"
+ "bc10rmfwl8nxdweeyc4sf89t0tn9fv9w6qpyzsnl2r4k48vjqh03qas9asdje0rlr0phru0wqw0p"
],
[
- "2LUHcJPbwLCy9GLH1qXmfmAwvadWw4bp4PCpDfduLqV17s6iDcy1imUwhQJhAoNoN1XNmweiJP4i"
+ "tb1qjqnfsuatr54e957xzg9sqk7yqcry9lns"
],
[
- "7USRzBXAnmck8fX9HmW7RAb4qt92VFX6soCnts9s74wxm4gguVhtG5of8fZGbNPJA83irHVY6bCos"
+ "bcrt1q8p08mv8echkf3es027u4cdswxlylm3th76ls8v6y4zy4vwsavngpr4e4td"
],
[
- "1DGezo7BfVebZxAbNT3XGujdeHyNNBF3vnficYoTSp4PfK2QaML9bHzAMxke3wdKdHYWmsMTJVu"
+ "BC1QNC2H66VLWTWTW52DP0FYUSNU3QQG5VT4V"
],
[
- "2D12DqDZKwCxxkzs1ZATJWvgJGhQ4cFi3WrizQ5zLAyhN5HxuAJ1yMYaJp8GuYsTLLxTAz6otCfb"
+ "tb1qgk665m2auw09rc7pqyf7aulcuhmatz9xqtr5mxew7zuysacaascqs9v0vn"
],
[
- "8AFJzuTujXjw1Z6M3fWhQ1ujDW7zsV4ePeVjVo7D1egERqSW9nZ"
+ "bcrt17CAPP7"
],
[
- "163Q17qLbTCue8YY3AvjpUhotuaodLm2uqMhpYirsKjVqnxJRWTEoywMVY3NbBAHuhAJ2cF9GAZ"
+ "bc1qxmf2d6aerjzam3rur0zufqxqnyqfts5u302s7x"
],
[
- "2MnmgiRH4eGLyLc9eAqStzk7dFgBjFtUCtu"
+ "tb1qn8x5dnzpexq7nnvrvnhwr9c3wkakpcyu9wwsjzq9pstkwg0t6qhs4l3rv6"
],
[
- "461QQ2sYWxU7H2PV4oBwJGNch8XVTYYbZxU"
+ "BCRT1Q397G2RNVYRL5LK07CE8NCKHVKP8Z4SC9U0MVH9"
],
[
- "2UCtv53VttmQYkVU4VMtXB31REvQg4ABzs41AEKZ8UcB7DAfVzdkV9JDErwGwyj5AUHLkmgZeobs"
+ "bc1pgxwyajq0gdn389f69uwn2fw9q0z5c9s063j5dgkdd23ajaud4hpsercr9h"
],
[
- "cSNjAsnhgtiFMi6MtfvgscMB2Cbhn2v1FUYfviJ1CdjfidvmeW6mn"
+ "tb1z6mnmp5k542l6yk4ul0mp4rq3yvz44lfm"
],
[
- "gmsow2Y6EWAFDFE1CE4Hd3Tpu2BvfmBfG1SXsuRARbnt1WjkZnFh1qGTiptWWbjsq2Q6qvpgJVj"
+ "bcrt17capp7"
],
[
- "nksUKSkzS76v8EsSgozXGMoQFiCoCHzCVajFKAXqzK5on9ZJYVHMD5CKwgmX3S3c7M1U3xabUny"
+ "2D2bqvKseKHdoKjCNvjVULUgmxHu9hjKGwDbPRjTRH59tsHNLeyKwq3vyVBbo9LByY9wiapqjwFY"
],
[
- "L3favK1UzFGgdzYBF2oBT5tbayCo4vtVBLJhg2iYuMeePxWG8SQc"
+ "2SSjAim4wZpeQRe5zTj1qqS6Li9ttJDaZ3ze"
],
[
- "7VxLxGGtYT6N99GdEfi6xz56xdQ8nP2dG1CavuXx7Rf2PrvNMTBNevjkfgs9JmkcGm6EXpj8ipyPZ"
+ "mi9H6MjLwXxy9kxe1x4ToxyLRBsmcZxgVi"
],
[
- "2mbZwFXF6cxShaCo2czTRB62WTx9LxhTtpP"
+ "VciXoxEitcn88jy197J9n9cpJ1pZahzU3SyWUiHqLgcfjttLEEJz"
],
[
- "dB7cwYdcPSgiyAwKWL3JwCVwSk6epU2txw"
+ "KppmwADGoExPT9Eq5hjRWpWFDbzJyfzHFgsfxBiDHNpVBgWPRNuy"
],
[
- "HPhFUhUAh8ZQQisH8QQWafAxtQYju3SFTX"
+ "TN7EQXMxKffzvHo54yHHu9R4ks9f5gWBW3MMVf5k72zAqrgVK9ys"
],
[
- "4ctAH6AkHzq5ioiM1m9T3E2hiYEev5mTsB"
+ "92dbrMEYzP5dD5UhQ6maNkCQ4GLG42BM4Gc6XKZzSSMSfosfkkcB"
],
[
- "Hn1uFi4dNexWrqARpjMqgT6cX1UsNPuV3cHdGg9ExyXw8HTKadbktRDtdeVmY3M1BxJStiL4vjJ"
+ "J7VQxPxyzuWEkRstQWpCz2AgysEz1APgnWCEQrFvkN3umAnCrhQF"
],
[
- "Sq3fDbvutABmnAHHExJDgPLQn44KnNC7UsXuT7KZecpaYDMU9Txs"
+ "tc1qymllj6c96v5qj2504y27ldtner6eh8ldx38t83"
],
[
- "6TqWyrqdgUEYDQU1aChMuFMMEimHX44qHFzCUgGfqxGgZNMUVWJ"
+ "bt1flep4g"
],
[
- "giqJo7oWqFxNKWyrgcBxAVHXnjJ1t6cGoEffce5Y1y7u649Noj5wJ4mmiUAKEVVrYAGg2KPB3Y4"
+ "tb13c553hwygcgj48qwmr9f8q0hgdcfklyaye5sxzcpcjnmxv4z506xs90tchn"
],
[
- "cNzHY5e8vcmM3QVJUcjCyiKMYfeYvyueq5qCMV3kqcySoLyGLYUK"
+ "bcrt1tyddyu"
],
[
- "37uTe568EYc9WLoHEd9jXEvUiWbq5LFLscNyqvAzLU5vBArUJA6eydkLmnMwJDjkL5kXc2VK7ig"
+ "bc10qssq2mknjqf0glwe2f3587wc4jysvs3f8s6chysae6hcl6fxzdm4wxyyscrl5k9f5qmnf05a"
],
[
- "EsYbG4tWWWY45G31nox838qNdzksbPySWc"
+ "tb1q425lmgvxdgtyl2m6xuu2pc354y4fvgg8"
],
[
- "nbuzhfwMoNzA3PaFnyLcRxE9bTJPDkjZ6Rf6Y6o2ckXZfzZzXBT"
+ "bcrt1q9wp8e5d2u3u4g0pll0cy7smeeuqezdun9xl439n3p2gg4fvgfvk3hu52hj"
],
[
- "cQN9PoxZeCWK1x56xnz6QYAsvR11XAce3Ehp3gMUdfSQ53Y2mPzx"
+ "bc1qrz5acazpue8vl4zsaxn8fxtmeuqmyjkq3"
],
[
- "1Gm3N3rkef6iMbx4voBzaxtXcmmiMTqZPhcuAepRzYUJQW4qRpEnHvMojzof42hjFRf8PE2jPde"
+ "tb1qkeuglpgmnex9tv3fr7htzfrh3rwrk23r52rx9halxzmv9fr85lwq0fwhmp"
],
[
- "2TAq2tuN6x6m233bpT7yqdYQPELdTDJn1eU"
+ "bcrt1qd0t2wrhl7s57z99rsyaekpq0dyjcQRSSmz80r4"
],
[
- "ntEtnnGhqPii4joABvBtSEJG6BxjT2tUZqE8PcVYgk3RHpgxgHDCQxNbLJf7ardf1dDk2oCQ7Cf"
+ "BC1QXLFDUCGX90T3E53PQCNKJ2PK25MSF3VLPMVY6T"
],
[
- "Ky1YjoZNgQ196HJV3HpdkecfhRBmRZdMJk89Hi5KGfpfPwS2bUbfd"
+ "tb1qmycg4zszgnk34vaurx3cu8wpvteg9h40yq6cp52gt26gjel03t3su3x3xu"
],
[
- "2A1q1YsMZowabbvta7kTy2Fd6qN4r5ZCeG3qLpvZBMzCixMUdkN2Y4dHB1wPsZAeVXUGD83MfRED"
+ "bcrt1q9hy58r4fnuxqzdqndpmq9pptc9nt2dw3rczf5e"
],
[
- "tc1qw508d6qejxtdg4y5r3zarvary0c5xw7kg3g4ty"
+ "BC1PA7682NAY6JQSLUWAJYTC0ERWTMW7A4RPWLNTUS32LCXWLHVKKKTQ2UL8CG"
],
[
- "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t5"
+ "tb1z850dpxnwz2fzae5h2myatj4yvu6rq5xq"
],
[
- "BC13W508D6QEJXTDG4Y5R3ZARVARY0C5XW7KN40WF2"
+ "bcrt1sp525pzjsmpqvcrawjreww36e9keg876skjvpwt"
],
[
- "bc1rw5uspcuh"
+ "xcAvW5jurCpzSpLxBKEhCewCgwwuGhqJnC"
],
[
- "bc10w508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7kw5rljs90"
+ "2Cvv8yp9kXbQt8EKh6Yma95yJ1uwYF9YKXuVhGJyu3dHGVsb2AVpTC62TFACZZ3KDNrALxR2CVNs"
],
[
- "BC1QR508D6QEJXTDG4Y5R3ZARVARYV98GJ9P"
+ "niUuL46hCuEVvkAzZKHvD746qbmLmzip9Pv3F6UZV14JxzEXBnTkVxCT4URapChJG6qAEgsZs6G"
],
[
- "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sL5k7"
+ "2UHHgGfiipzvB8Eumnmvq6SowvrMJimjT3NwwG1839XEiUfwtpSdkUrseNsQuagXv21ce7aZu6yo"
],
[
- "bc1zw508d6qejxtdg4y5r3zarvaryvqyzf3du"
+ "8u9djKu4u6o3bsgeR4BKNnLK3akpo64FYzDAmA9239wKeshgF97"
],
[
- "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3pjxtptv"
+ "TC1QPAARXSLVMXHVRR0474LZXQYZWLGFZYPSFVL9E4"
],
[
- "bc1gmk9yu"
+ "bt1pakek0n2267t9yaksxaczgr2syhv9y3xkx0wnsdwchfa6xkmjtvuqg3kgyr"
+ ],
+ [
+ "tb13h83rtwq62udrhwpn87uely7cyxcjrj0azz6a4r3n9s87x5uj98ys6ufp83"
+ ],
+ [
+ "bcrt1rk5vw5qf2"
+ ],
+ [
+ "bc10d3rmtg62h747en5j6fju5g5qyvsransrkty6ghh96pu647wumctejlsngh9pf26cysrys2x2"
+ ],
+ [
+ "tb1qajuy2cdwqgmrzc7la85al5cwcq374tsp"
+ ],
+ [
+ "bcrt1q3udxvj6x20chqh723mn064mzz65yr56ef00xk8czvu3jnx04ydapzk02s5"
+ ],
+ [
+ "bc1qule2szwzyaq4qy0s3aa4mauucyqt6fewe"
+ ],
+ [
+ "tb1ql0qny5vg9gh5tyzke6dw36px5ulkrp24x53x0pl2t5lpwrtejw3s2seej2"
+ ],
+ [
+ "bcrt17CAPP7"
+ ],
+ [
+ "bc1qtvm6davyf725wfedc2d5mrgfewqgcrce8gjrpl"
+ ],
+ [
+ "tb1q5acjgtqrrw3an0dzavxxxzlex8k7aukjzjk9v2u4rmfdqxjphcyq7ge97e"
]
]
diff --git a/src/test/data/key_io_valid.json b/src/test/data/key_io_valid.json
index 8418a6002d..5dee44c04b 100644
--- a/src/test/data/key_io_valid.json
+++ b/src/test/data/key_io_valid.json
@@ -1,533 +1,610 @@
[
[
- "1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i",
- "76a91465a16059864a2fdbc7c99a4723a8395bc6f188eb88ac",
+ "1BShJZ8A5q53oJJfMJoEF1gfZCWdZqZwwD",
+ "76a914728d4cc27d19707b0197cfcd7c412d43287864b588ac",
{
- "isPrivkey": false,
- "chain": "main"
+ "chain": "main",
+ "isPrivkey": false
}
],
[
- "3CMNFxN1oHBc4R1EpboAL5yzHGgE611Xou",
- "a91474f209f6ea907e2ea48f74fae05782ae8a66525787",
+ "3L1YkZjdeNSqaZcNKZFXQfyokx3zVYm7r6",
+ "a914c8f37c3cc21561296ad81f4bec6b5de10ebc185187",
{
- "isPrivkey": false,
- "chain": "main"
+ "chain": "main",
+ "isPrivkey": false
}
],
[
- "mo9ncXisMeAoXwqcV5EWuyncbmCcQN4rVs",
- "76a91453c0307d6851aa0ce7825ba883c6bd9ad242b48688ac",
+ "mhJuoGLgnJC8gdBgBzEigsoyG4omQXejPT",
+ "76a91413a92d1998e081354d36c13ce0c9dc04b865d40a88ac",
{
- "isPrivkey": false,
- "chain": "test"
+ "chain": "test",
+ "isPrivkey": false
}
],
[
- "mo9ncXisMeAoXwqcV5EWuyncbmCcQN4rVs",
- "76a91453c0307d6851aa0ce7825ba883c6bd9ad242b48688ac",
+ "2N5VpzKEuYvZJbmg6eUNGnfrrD1ir92FWGu",
+ "a91486648cc2faaf05660e72c04c7a837bcc3e986f1787",
{
- "isPrivkey": false,
- "chain": "regtest"
+ "chain": "test",
+ "isPrivkey": false
}
],
[
- "2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br",
- "a9146349a418fc4578d10a372b54b45c280cc8c4382f87",
+ "mtQueCtmAnP3E4aBHXCiFNEQAuPaLMuQNy",
+ "76a9148d74ecd86c845baf9c6d4484d2d00e731b79e34788ac",
{
- "isPrivkey": false,
- "chain": "test"
+ "chain": "signet",
+ "isPrivkey": false
+ }
+ ],
+ [
+ "2NEvWRTHjh89gV52fkperFtwzoFWQiQmiCh",
+ "a914edc895152c67ccff0ba620bcc373b789ec68266f87",
+ {
+ "chain": "signet",
+ "isPrivkey": false
}
],
[
- "5Kd3NBUAdUnhyzenEwVLy9pBKxSwXvE9FMPyR4UKZvpe6E3AgLr",
- "eddbdc1168f1daeadbd3e44c1e3f8f5a284c2029f78ad26af98583a499de5b19",
+ "mngdx94qJFhSf7A7SAEgQSC9fQJuapujJp",
+ "76a9144e9dba545455a80ce94c343d1cac9dec62cbf22288ac",
{
+ "chain": "regtest",
+ "isPrivkey": false
+ }
+ ],
+ [
+ "2NBzRN3pV56k3JUvSHifaHyzjGHv7ZS9FZZ",
+ "a914cd9da5642451273e5b6d088854cc1fad4a8d442187",
+ {
+ "chain": "regtest",
+ "isPrivkey": false
+ }
+ ],
+ [
+ "5KcrFZvJ2p4dM6QVUPu53cKXcCfozA1PJLHm1mNAxkDYhgThLu4",
+ "ed6c796e2f62377410766214f55aa81ac9a6590ad7ed57c509c983bf648409ac",
+ {
+ "chain": "main",
"isCompressed": false,
- "isPrivkey": true,
- "chain": "main"
+ "isPrivkey": true
}
],
[
- "Kz6UJmQACJmLtaQj5A3JAge4kVTNQ8gbvXuwbmCj7bsaabudb3RD",
- "55c9bccb9ed68446d1b75273bbce89d7fe013a8acd1625514420fb2aca1a21c4",
+ "L195WBrf2G3nCnun4CLxrb8XKk9LbCqH43THh4n4QrL5SzRzpq9j",
+ "74f76c106e38d20514a99a86e4fe3bb28319e7dd2ad21dbc170cbb516a5358fa",
{
+ "chain": "main",
"isCompressed": true,
- "isPrivkey": true,
- "chain": "main"
+ "isPrivkey": true
}
],
[
- "9213qJab2HNEpMpYNBa7wHGFKKbkDn24jpANDs2huN3yi4J11ko",
- "36cb93b9ab1bdabf7fb9f2c04f1b9cc879933530ae7842398eef5a63a56800c2",
+ "92z6HnMQR4tWqjfVA3UaUN5EuUMgoVMdCa5rZFYZfmgyD7wxYCw",
+ "b8511e1d74549e305517d48a1d394d1be2cfa5d0f3c0d83f9f450316ffa01276",
{
+ "chain": "test",
"isCompressed": false,
- "isPrivkey": true,
- "chain": "test"
+ "isPrivkey": true
}
],
[
- "9213qJab2HNEpMpYNBa7wHGFKKbkDn24jpANDs2huN3yi4J11ko",
- "36cb93b9ab1bdabf7fb9f2c04f1b9cc879933530ae7842398eef5a63a56800c2",
+ "cTPnaF52x4w4Tq6afPxRHux3wbYb86thS7S45A7r3oZc1AHTQ6Qm",
+ "ad68c48d337181da125de9061933ececcdf7d917631af7d34f7e38082bff9a11",
{
+ "chain": "test",
+ "isCompressed": true,
+ "isPrivkey": true
+ }
+ ],
+ [
+ "924U35yFcYkxe2JXGmuhSRVaShGyhRDZx1ysPmw1sAHuszGMoxq",
+ "3e8dfaf78d4f02b11d0b645648a4f3080d71d0d068979c47f7255c9a29eee01d",
+ {
+ "chain": "signet",
"isCompressed": false,
- "isPrivkey": true,
- "chain": "regtest"
+ "isPrivkey": true
}
],
[
- "cTpB4YiyKiBcPxnefsDpbnDxFDffjqJob8wGCEDXxgQ7zQoMXJdH",
- "b9f4892c9e8282028fea1d2667c4dc5213564d41fc5783896a0d843fc15089f3",
+ "cRy1qCf2LUesGPQagTkYwk2V3PyN2KCPKgxeg6k6KoJPzH7nrVjw",
+ "82d4187690d6b59bcffda27dae52f2ecb87313cfc0904e0b674a27d906a65fde",
{
+ "chain": "signet",
"isCompressed": true,
- "isPrivkey": true,
- "chain": "test"
+ "isPrivkey": true
}
],
[
- "cTpB4YiyKiBcPxnefsDpbnDxFDffjqJob8wGCEDXxgQ7zQoMXJdH",
- "b9f4892c9e8282028fea1d2667c4dc5213564d41fc5783896a0d843fc15089f3",
+ "932NTcHK35Apf2C3K9Zv1ZdeZEmB1x7ZT2Ju3SjoEY6pUgUpT7H",
+ "bd7dba24df9e003e145ae9b4862776413a0bb6fa5b4e42753397f2d9536e58a9",
{
- "isCompressed": true,
- "isPrivkey": true,
- "chain": "regtest"
+ "chain": "regtest",
+ "isCompressed": false,
+ "isPrivkey": true
}
],
[
- "1Ax4gZtb7gAit2TivwejZHYtNNLT18PUXJ",
- "76a9146d23156cbbdcc82a5a47eee4c2c7c583c18b6bf488ac",
+ "cNa75orYQ2oos52zCnMaS5PG6XbNZKc5LpGxTHacrxwWeX4WAK3E",
+ "1d87e3c58b08766fea03598380ec8d59f8c88d5392bf683ab1088bd4caf073ee",
{
- "isPrivkey": false,
- "chain": "main"
+ "chain": "regtest",
+ "isCompressed": true,
+ "isPrivkey": true
}
],
[
- "3QjYXhTkvuj8qPaXHTTWb5wjXhdsLAAWVy",
- "a914fcc5460dd6e2487c7d75b1963625da0e8f4c597587",
+ "bc1q5cuatynjmk4szh40mmunszfzh7zrc5xm9w8ccy",
+ "0014a639d59272ddab015eafdef9380922bf843c50db",
{
+ "chain": "main",
"isPrivkey": false,
- "chain": "main"
+ "tryCaseFlip": true
}
],
[
- "n3ZddxzLvAY9o7184TB4c6FJasAybsw4HZ",
- "76a914f1d470f9b02370fdec2e6b708b08ac431bf7a5f788ac",
+ "bc1qkw7lz3ahms6e0ajv27mzh7g62tchjpmve4afc29u7w49tddydy2syv0087",
+ "0020b3bdf147b7dc3597f64c57b62bf91a52f179076ccd7a9c28bcf3aa55b5a46915",
{
+ "chain": "main",
"isPrivkey": false,
- "chain": "test"
+ "tryCaseFlip": true
}
],
[
- "2NBFNJTktNa7GZusGbDbGKRZTxdK9VVez3n",
- "a914c579342c2c4c9220205e2cdc285617040c924a0a87",
+ "bc1p5rgvqejqh9dh37t9g94dd9cm8vtqns7dndgj423egwggsggcdzmsspvr7j",
+ "5120a0d0c06640b95b78f965416ad6971b3b1609c3cd9b512aaa39439088211868b7",
{
+ "chain": "main",
"isPrivkey": false,
- "chain": "test"
+ "tryCaseFlip": true
}
],
[
- "5K494XZwps2bGyeL71pWid4noiSNA2cfCibrvRWqcHSptoFn7rc",
- "a326b95ebae30164217d7a7f57d72ab2b54e3be64928a19da0210b9568d4015e",
+ "bc1zr4pq63udck",
+ "52021d42",
{
- "isCompressed": false,
- "isPrivkey": true,
- "chain": "main"
+ "chain": "main",
+ "isPrivkey": false,
+ "tryCaseFlip": true
}
],
[
- "L1RrrnXkcKut5DEMwtDthjwRcTTwED36thyL1DebVrKuwvohjMNi",
- "7d998b45c219a1e38e99e7cbd312ef67f77a455a9b50c730c27f02c6f730dfb4",
+ "tb1q74fxwnvhsue0l8wremgq66xzvn48jlc5zthsvz",
+ "0014f552674d978732ff9dc3ced00d68c264ea797f14",
{
- "isCompressed": true,
- "isPrivkey": true,
- "chain": "main"
+ "chain": "test",
+ "isPrivkey": false,
+ "tryCaseFlip": true
}
],
[
- "93DVKyFYwSN6wEo3E2fCrFPUp17FtrtNi2Lf7n4G3garFb16CRj",
- "d6bca256b5abc5602ec2e1c121a08b0da2556587430bcf7e1898af2224885203",
+ "tb1qpt7cqgq8ukv92dcraun9c3n0s3aswrt62vtv8nqmkfpa2tjfghesv9ln74",
+ "00200afd802007e598553703ef265c466f847b070d7a5316c3cc1bb243d52e4945f3",
{
- "isCompressed": false,
- "isPrivkey": true,
- "chain": "test"
+ "chain": "test",
+ "isPrivkey": false,
+ "tryCaseFlip": true
}
],
[
- "cTDVKtMGVYWTHCb1AFjmVbEbWjvKpKqKgMaR3QJxToMSQAhmCeTN",
- "a81ca4e8f90181ec4b61b6a7eb998af17b2cb04de8a03b504b9e34c4c61db7d9",
+ "tb1ph9v3e8nxct57hknlkhkz75p5pnxnkn05cw8ewpxu6tek56g29xgqydzfu7",
+ "5120b9591c9e66c2e9ebda7fb5ec2f50340ccd3b4df4c38f9704dcd2f36a690a2990",
{
- "isCompressed": true,
- "isPrivkey": true,
- "chain": "test"
+ "chain": "test",
+ "isPrivkey": false,
+ "tryCaseFlip": true
}
],
[
- "1C5bSj1iEGUgSTbziymG7Cn18ENQuT36vv",
- "76a9147987ccaa53d02c8873487ef919677cd3db7a691288ac",
+ "tb1ray6e8gxfx49ers6c4c70l3c8lsxtcmlx",
+ "5310e93593a0c9354b91c358ae3cffc707fc",
{
+ "chain": "test",
"isPrivkey": false,
- "chain": "main"
+ "tryCaseFlip": true
}
],
[
- "3AnNxabYGoTxYiTEZwFEnerUoeFXK2Zoks",
- "a91463bcc565f9e68ee0189dd5cc67f1b0e5f02f45cb87",
+ "tb1q0sqzfp3zj42u0perxr6jahhu4y03uw4dypk6sc",
+ "00147c002486229555c7872330f52edefca91f1e3aad",
{
+ "chain": "signet",
"isPrivkey": false,
- "chain": "main"
+ "tryCaseFlip": true
}
],
[
- "n3LnJXCqbPjghuVs8ph9CYsAe4Sh4j97wk",
- "76a914ef66444b5b17f14e8fae6e7e19b045a78c54fd7988ac",
+ "tb1q9jv4qnawnuevqaeadn47gkq05ev78m4qg3zqejykdr9u0cm7yutq6gu5dj",
+ "00202c99504fae9f32c0773d6cebe4580fa659e3eea044440cc89668cbc7e37e2716",
{
+ "chain": "signet",
"isPrivkey": false,
- "chain": "test"
+ "tryCaseFlip": true
}
],
[
- "2NB72XtkjpnATMggui83aEtPawyyKvnbX2o",
- "a914c3e55fceceaa4391ed2a9677f4a4d34eacd021a087",
+ "tb1pxqf7d825wjtcftj7uep8w24jq3tz8vudfaqj20rns8ahqya56gcs92eqtu",
+ "51203013e69d54749784ae5ee642772ab2045623b38d4f41253c7381fb7013b4d231",
{
+ "chain": "signet",
"isPrivkey": false,
- "chain": "test"
+ "tryCaseFlip": true
}
],
[
- "5KaBW9vNtWNhc3ZEDyNCiXLPdVPHCikRxSBWwV9NrpLLa4LsXi9",
- "e75d936d56377f432f404aabb406601f892fd49da90eb6ac558a733c93b47252",
+ "tb1rsrzkyvu2rt0dcgexajtazlw5nft4j7494ay396q6auw9375wxsrsgag884",
+ "532080c562338a1adedc2326ec97d17dd49a57597aa5af4912e81aef1c58fa8e3407",
{
- "isCompressed": false,
- "isPrivkey": true,
- "chain": "main"
+ "chain": "signet",
+ "isPrivkey": false,
+ "tryCaseFlip": true
}
],
[
- "L1axzbSyynNYA8mCAhzxkipKkfHtAXYF4YQnhSKcLV8YXA874fgT",
- "8248bd0375f2f75d7e274ae544fb920f51784480866b102384190b1addfbaa5c",
+ "bcrt1qwf52dt9y2sv0f7fwkcpmtfjf74d4np2saeljt6",
+ "00147268a6aca45418f4f92eb603b5a649f55b598550",
{
- "isCompressed": true,
- "isPrivkey": true,
- "chain": "main"
+ "chain": "regtest",
+ "isPrivkey": false,
+ "tryCaseFlip": true
}
],
[
- "927CnUkUbasYtDwYwVn2j8GdTuACNnKkjZ1rpZd2yBB1CLcnXpo",
- "44c4f6a096eac5238291a94cc24c01e3b19b8d8cef72874a079e00a242237a52",
+ "bcrt1q0lma84unycxl4n96etffthqlf7y5axyp4fxf64kmhymvw8l6pwfs39futd",
+ "00207ff7d3d793260dfaccbacad295dc1f4f894e9881aa4c9d56dbb936c71ffa0b93",
{
- "isCompressed": false,
- "isPrivkey": true,
- "chain": "test"
+ "chain": "regtest",
+ "isPrivkey": false,
+ "tryCaseFlip": true
}
],
[
- "cUcfCMRjiQf85YMzzQEk9d1s5A4K7xL5SmBCLrezqXFuTVefyhY7",
- "d1de707020a9059d6d3abaf85e17967c6555151143db13dbb06db78df0f15c69",
+ "bcrt1p3xat2ryucc2v0adrktqnavfzttvezrr27ngltsa2726p2ehvxz4se722v2",
+ "512089bab50c9cc614c7f5a3b2c13eb1225ad9910c6af4d1f5c3aaf2b41566ec30ab",
{
- "isCompressed": true,
- "isPrivkey": true,
- "chain": "test"
+ "chain": "regtest",
+ "isPrivkey": false,
+ "tryCaseFlip": true
}
],
[
- "1Gqk4Tv79P91Cc1STQtU3s1W6277M2CVWu",
- "76a914adc1cc2081a27206fae25792f28bbc55b831549d88ac",
+ "bcrt1saflydw6e26xhp29euhy5jke5jjqyywk3wvtc9ulgw9dvxyuqy9hdnxthyw755c7ldavy7u",
+ "6028ea7e46bb59568d70a8b9e5c9495b349480423ad1731782f3e8715ac31380216ed9997723bd4a63df",
{
+ "chain": "regtest",
"isPrivkey": false,
- "chain": "main"
+ "tryCaseFlip": true
}
],
[
- "33vt8ViH5jsr115AGkW6cEmEz9MpvJSwDk",
- "a914188f91a931947eddd7432d6e614387e32b24470987",
+ "16y3Q1XVRZqMR9T1XL1FkvNtD2E1bXBuYa",
+ "76a9144171ec673aeb9fcf42af6094a3c82207e3b9a78188ac",
{
- "isPrivkey": false,
- "chain": "main"
+ "chain": "main",
+ "isPrivkey": false
}
],
[
- "mhaMcBxNh5cqXm4aTQ6EcVbKtfL6LGyK2H",
- "76a9141694f5bc1a7295b600f40018a618a6ea48eeb49888ac",
+ "3CmZZnAiHVQgiAKSakf864oJMxN2BP1eLC",
+ "a914798575fc1041b9440c4e63c28e57e597d00b7e4387",
{
- "isPrivkey": false,
- "chain": "test"
+ "chain": "main",
+ "isPrivkey": false
}
],
[
- "2MxgPqX1iThW3oZVk9KoFcE5M4JpiETssVN",
- "a9143b9b3fd7a50d4f08d1a5b0f62f644fa7115ae2f387",
+ "mtCB3SoBo7EYUv8j54kUubGY4x3aJPY8nk",
+ "76a9148b0c5f9ee714e0d1d24642ad63d9d5f398d9b56588ac",
{
- "isPrivkey": false,
- "chain": "test"
+ "chain": "test",
+ "isPrivkey": false
}
],
[
- "5HtH6GdcwCJA4ggWEL1B3jzBBUB8HPiBi9SBc5h9i4Wk4PSeApR",
- "091035445ef105fa1bb125eccfb1882f3fe69592265956ade751fd095033d8d0",
+ "2N5ymzzKpx6EdUR4UdMZ7t9hcuwqtpHwgw5",
+ "a9148badb3c3b5c0d39f906f7618e0018b7eae4baf7387",
{
- "isCompressed": false,
- "isPrivkey": true,
- "chain": "main"
+ "chain": "test",
+ "isPrivkey": false
}
],
[
- "L2xSYmMeVo3Zek3ZTsv9xUrXVAmrWxJ8Ua4cw8pkfbQhcEFhkXT8",
- "ab2b4bcdfc91d34dee0ae2a8c6b6668dadaeb3a88b9859743156f462325187af",
+ "myXnpYbub28zgiJupDdZSWZtDbjcyfJVby",
+ "76a914c59ac57661b57daadd7c0caf7318c14f54c6c0fa88ac",
{
- "isCompressed": true,
- "isPrivkey": true,
- "chain": "main"
+ "chain": "signet",
+ "isPrivkey": false
}
],
[
- "92xFEve1Z9N8Z641KQQS7ByCSb8kGjsDzw6fAmjHN1LZGKQXyMq",
- "b4204389cef18bbe2b353623cbf93e8678fbc92a475b664ae98ed594e6cf0856",
+ "2MtLg8jS5jSXm9evMzTtvpLjy26dBmjFEoT",
+ "a9140c0007e89cea625d3bf9543baa5a470bb7e5b67287",
{
- "isCompressed": false,
- "isPrivkey": true,
- "chain": "test"
+ "chain": "signet",
+ "isPrivkey": false
}
],
[
- "92xFEve1Z9N8Z641KQQS7ByCSb8kGjsDzw6fAmjHN1LZGKQXyMq",
- "b4204389cef18bbe2b353623cbf93e8678fbc92a475b664ae98ed594e6cf0856",
+ "mzCyqdf2UNGdpgkD9NBgLcxdwXRg1i9buY",
+ "76a914cd04311bdd1ef9c5c24e41930e032aade82a863a88ac",
{
- "isCompressed": false,
- "isPrivkey": true,
- "chain": "regtest"
+ "chain": "regtest",
+ "isPrivkey": false
}
],
[
- "cVM65tdYu1YK37tNoAyGoJTR13VBYFva1vg9FLuPAsJijGvG6NEA",
- "e7b230133f1b5489843260236b06edca25f66adb1be455fbd38d4010d48faeef",
+ "2N3zGiwFku2vQjYnAqXv5Qu2ztfYRhh7tbF",
+ "a91475d56d75c88e704d6c72fbe84ac1505abf736b4087",
{
- "isCompressed": true,
- "isPrivkey": true,
- "chain": "test"
+ "chain": "regtest",
+ "isPrivkey": false
}
],
[
- "1JwMWBVLtiqtscbaRHai4pqHokhFCbtoB4",
- "76a914c4c1b72491ede1eedaca00618407ee0b772cad0d88ac",
+ "5JUHCgyxNSHg64wwju72eNsG6ajqo4Z2fHHw9iLDLfh69rSiL7w",
+ "5644d06d88855dacf3192a31df8f4acd8e4c155c52a86d2c1fa48303f5cff053",
{
- "isPrivkey": false,
- "chain": "main"
+ "chain": "main",
+ "isCompressed": false,
+ "isPrivkey": true
}
],
[
- "3QCzvfL4ZRvmJFiWWBVwxfdaNBT8EtxB5y",
- "a914f6fe69bcb548a829cce4c57bf6fff8af3a5981f987",
+ "L2kZaexG69VSriMe9T2m1jkS86iPe3xNbjcdfakRC1PHe7ay78Ji",
+ "a50ee94aefcabf5a5d7c85be5b3844dee03c5604861dbfc77fe388c91e5a30f8",
{
- "isPrivkey": false,
- "chain": "main"
+ "chain": "main",
+ "isCompressed": true,
+ "isPrivkey": true
}
],
[
- "mizXiucXRCsEriQCHUkCqef9ph9qtPbZZ6",
- "76a914261f83568a098a8638844bd7aeca039d5f2352c088ac",
+ "927JwT1ViCr5TD2ZX8CsMNhg17dXmou5xu4y2KiH54zD7i34UJq",
+ "4502a54c0026b0150281d41f40860d1e23870c63cdc32645bbed688f2ee41f64",
{
- "isPrivkey": false,
- "chain": "test"
+ "chain": "test",
+ "isCompressed": false,
+ "isPrivkey": true
}
],
[
- "2NEWDzHWwY5ZZp8CQWbB7ouNMLqCia6YRda",
- "a914e930e1834a4d234702773951d627cce82fbb5d2e87",
+ "cTpGGNPVy2Eagawohbr4aGtRJzpLnjxGsGYh9DUcBM45f3KdKGF6",
+ "ba005a0cb39587aab00bd54c848b59e8adaed47403228567ddc739c2a344ff59",
{
- "isPrivkey": false,
- "chain": "test"
+ "chain": "test",
+ "isCompressed": true,
+ "isPrivkey": true
}
],
[
- "5KQmDryMNDcisTzRp3zEq9e4awRmJrEVU1j5vFRTKpRNYPqYrMg",
- "d1fab7ab7385ad26872237f1eb9789aa25cc986bacc695e07ac571d6cdac8bc0",
+ "932PLCLA19yPNqV67qwHBSGjxi82LVzWBF7josL9ab4Q1kxgPGF",
+ "bd8677e076eb39770bf7e9f9e8d3f2cf257effab9b4c220fd3439ccfc208c984",
{
+ "chain": "signet",
"isCompressed": false,
- "isPrivkey": true,
- "chain": "main"
+ "isPrivkey": true
}
],
[
- "L39Fy7AC2Hhj95gh3Yb2AU5YHh1mQSAHgpNixvm27poizcJyLtUi",
- "b0bbede33ef254e8376aceb1510253fc3550efd0fcf84dcd0c9998b288f166b3",
+ "cViUpEy8URSsLjUvxwL7cEuNgCVqM7oKBzd1ZPbA4khcQsQJuj1j",
+ "f2b36ade8393e29dc71e52cb75ba1109ba210203cd7d0a5ae881ad6846516203",
{
+ "chain": "signet",
"isCompressed": true,
- "isPrivkey": true,
- "chain": "main"
+ "isPrivkey": true
}
],
[
- "91cTVUcgydqyZLgaANpf1fvL55FH53QMm4BsnCADVNYuWuqdVys",
- "037f4192c630f399d9271e26c575269b1d15be553ea1a7217f0cb8513cef41cb",
+ "92jddDjJCVDmJtgvBHQ9i58PMash8kwsYhRdNo22ea2MYPXdCBE",
+ "977bf8686f1bcad28f86c4c14afbd33215746bd19203647bf7ff9c6fddc9cc87",
{
+ "chain": "regtest",
"isCompressed": false,
- "isPrivkey": true,
- "chain": "test"
+ "isPrivkey": true
}
],
[
- "cQspfSzsgLeiJGB2u8vrAiWpCU4MxUT6JseWo2SjXy4Qbzn2fwDw",
- "6251e205e8ad508bab5596bee086ef16cd4b239e0cc0c5d7c4e6035441e7d5de",
+ "cVwAuMoUqRo399X7vXzuzQyPEvZJMXM8c82zHzRkFCxPCSGx8A6y",
+ "f93acbbce02b8cb9ddca3fad495441e324cc01eb640b0a7b4c9f0e31644c822a",
{
+ "chain": "regtest",
"isCompressed": true,
- "isPrivkey": true,
- "chain": "test"
+ "isPrivkey": true
}
],
[
- "19dcawoKcZdQz365WpXWMhX6QCUpR9SY4r",
- "76a9145eadaf9bb7121f0f192561a5a62f5e5f5421029288ac",
+ "bc1qz377zwe5awr68dnggengqx9vrjt05k98q3sw2n",
+ "0014147de13b34eb87a3b66846668018ac1c96fa58a7",
{
+ "chain": "main",
"isPrivkey": false,
- "chain": "main"
+ "tryCaseFlip": true
}
],
[
- "37Sp6Rv3y4kVd1nQ1JV5pfqXccHNyZm1x3",
- "a9143f210e7277c899c3a155cc1c90f4106cbddeec6e87",
+ "bc1qkmhskpdzg8kdkfywhu09kswwn9qan9vnkrf6mk40jvnr06s6sz5ssf82ya",
+ "0020b6ef0b05a241ecdb248ebf1e5b41ce9941d99593b0d3addaaf932637ea1a80a9",
{
+ "chain": "main",
"isPrivkey": false,
- "chain": "main"
+ "tryCaseFlip": true
}
],
[
- "myoqcgYiehufrsnnkqdqbp69dddVDMopJu",
- "76a914c8a3c2a09a298592c3e180f02487cd91ba3400b588ac",
+ "bc1ps8cndas60cntk8x79sg9f5e5jz7x050z8agyugln2ukkks23rryqpejzkc",
+ "512081f136f61a7e26bb1cde2c1054d33490bc67d1e23f504e23f3572d6b415118c8",
{
+ "chain": "main",
"isPrivkey": false,
- "chain": "test"
+ "tryCaseFlip": true
}
],
[
- "2N7FuwuUuoTBrDFdrAZ9KxBmtqMLxce9i1C",
- "a91499b31df7c9068d1481b596578ddbb4d3bd90baeb87",
+ "bc1zn4tsczge9l",
+ "52029d57",
{
+ "chain": "main",
"isPrivkey": false,
- "chain": "test"
+ "tryCaseFlip": true
}
],
[
- "5KL6zEaMtPRXZKo1bbMq7JDjjo1bJuQcsgL33je3oY8uSJCR5b4",
- "c7666842503db6dc6ea061f092cfb9c388448629a6fe868d068c42a488b478ae",
+ "tb1q6xw0wwd9n9d7ge87dryz4vm5vtahzhvz6yett3",
+ "0014d19cf739a5995be464fe68c82ab37462fb715d82",
{
- "isCompressed": false,
- "isPrivkey": true,
- "chain": "main"
+ "chain": "test",
+ "isPrivkey": false,
+ "tryCaseFlip": true
}
],
[
- "KwV9KAfwbwt51veZWNscRTeZs9CKpojyu1MsPnaKTF5kz69H1UN2",
- "07f0803fc5399e773555ab1e8939907e9badacc17ca129e67a2f5f2ff84351dd",
+ "tb1qwn9zq9fu5uk35ykpgsc7rz4uawy4yh0r5m5er26768h5ur50su3qj6evun",
+ "002074ca20153ca72d1a12c14431e18abceb89525de3a6e991ab5ed1ef4e0e8f8722",
{
- "isCompressed": true,
- "isPrivkey": true,
- "chain": "main"
+ "chain": "test",
+ "isPrivkey": false,
+ "tryCaseFlip": true
}
],
[
- "93N87D6uxSBzwXvpokpzg8FFmfQPmvX4xHoWQe3pLdYpbiwT5YV",
- "ea577acfb5d1d14d3b7b195c321566f12f87d2b77ea3a53f68df7ebf8604a801",
+ "tb1pmcdc5d8gr92rtemfsnhpeqanvs0nr82upn5dktxluz9n0qcv34lqxke0wq",
+ "5120de1b8a34e8195435e76984ee1c83b3641f319d5c0ce8db2cdfe08b37830c8d7e",
{
- "isCompressed": false,
- "isPrivkey": true,
- "chain": "test"
+ "chain": "test",
+ "isPrivkey": false,
+ "tryCaseFlip": true
}
],
[
- "cMxXusSihaX58wpJ3tNuuUcZEQGt6DKJ1wEpxys88FFaQCYjku9h",
- "0b3b34f0958d8a268193a9814da92c3e8b58b4a4378a542863e34ac289cd830c",
+ "tb1rgxjvtfzp0xczz6dlzqv8d5cmuykk4qkk",
+ "531041a4c5a44179b02169bf101876d31be1",
{
- "isCompressed": true,
- "isPrivkey": true,
- "chain": "test"
+ "chain": "test",
+ "isPrivkey": false,
+ "tryCaseFlip": true
}
],
[
- "13p1ijLwsnrcuyqcTvJXkq2ASdXqcnEBLE",
- "76a9141ed467017f043e91ed4c44b4e8dd674db211c4e688ac",
+ "tb1qa9dlyt6fydestul4y4wh72yshh044w32np8etk",
+ "0014e95bf22f49237305f3f5255d7f2890bddf5aba2a",
{
+ "chain": "signet",
"isPrivkey": false,
- "chain": "main"
+ "tryCaseFlip": true
}
],
[
- "3ALJH9Y951VCGcVZYAdpA3KchoP9McEj1G",
- "a9145ece0cadddc415b1980f001785947120acdb36fc87",
+ "tb1qu4p26n0033720xm0rjgkds5ehdwf039k2fgv75um5krrvfhrrj7qckl9r2",
+ "0020e542ad4def8c7ca79b6f1c9166c299bb5c97c4b65250cf539ba5863626e31cbc",
{
+ "chain": "signet",
"isPrivkey": false,
- "chain": "main"
+ "tryCaseFlip": true
}
],
[
- "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4",
- "0014751e76e8199196d454941c45d1b3a323f1433bd6",
+ "tb1pjyukm4n4flwd0ey3lrl06c9kalr60ggmlkcxq2rhhxmy4lvkmkpqexdzqy",
+ "512091396dd6754fdcd7e491f8fefd60b6efc7a7a11bfdb0602877b9b64afd96dd82",
{
+ "chain": "signet",
"isPrivkey": false,
- "chain": "main",
"tryCaseFlip": true
}
],
[
- "bcrt1qw508d6qejxtdg4y5r3zarvary0c5xw7kygt080",
- "0014751e76e8199196d454941c45d1b3a323f1433bd6",
+ "tb1r4k75s5syvewsvxufdc3xfhf4tw4u30alw39xny3dnxrl6hau7systymfdv",
+ "5320adbd485204665d061b896e2264dd355babc8bfbf744a69922d9987fd5fbcf409",
{
+ "chain": "signet",
"isPrivkey": false,
- "chain": "regtest",
"tryCaseFlip": true
}
],
[
- "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7",
- "00201863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262",
+ "bcrt1qnk3tdwwj47ppc4pqmxkjdusegedn9ru5gvccwa",
+ "00149da2b6b9d2af821c5420d9ad26f219465b328f94",
{
+ "chain": "regtest",
"isPrivkey": false,
- "chain": "test",
"tryCaseFlip": true
}
],
[
- "bc1pw508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7k7grplx",
- "5128751e76e8199196d454941c45d1b3a323f1433bd6751e76e8199196d454941c45d1b3a323f1433bd6",
+ "bcrt1qz7prfshfkwsxuk72pt6mzr6uumq4qllxe4vmwqt89tat48d362yqlykk6a",
+ "0020178234c2e9b3a06e5bca0af5b10f5ce6c1507fe6cd59b701672afaba9db1d288",
{
+ "chain": "regtest",
"isPrivkey": false,
- "chain": "main",
"tryCaseFlip": true
}
],
[
- "bc1sw50qa3jx3s",
- "6002751e",
+ "bcrt1pumee3wj80xvyr7wjmj7zsk26x5pn095aegy862yhx6f2j9sgc9hq6cj4cm",
+ "5120e6f398ba47799841f9d2dcbc28595a350337969dca087d28973692a91608c16e",
{
+ "chain": "regtest",
"isPrivkey": false,
- "chain": "main",
"tryCaseFlip": true
}
],
[
- "bc1zw508d6qejxtdg4y5r3zarvaryvg6kdaj",
- "5210751e76e8199196d454941c45d1b3a323",
+ "bcrt1szqz8hj64d2hhc6nt65v09jxal66pgff2xpcp9kj648qkk8kjzxelsts4dktd799g47uase",
+ "602810047bcb556aaf7c6a6bd518f2c8ddfeb414252a307012da5aa9c16b1ed211b3f82e156d96df14a8",
{
+ "chain": "regtest",
"isPrivkey": false,
- "chain": "main",
"tryCaseFlip": true
}
],
[
- "tb1qqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvsesrxh6hy",
- "0020000000c4a5cad46221b2a187905e5266362b99d5e91c6ce24d165dab93e86433",
+ "12agZTajtRE3STSchwWNWnrm467zzTQ916",
+ "76a9141156e00f70061e5faba8b71593a8c7554b47090c88ac",
+ {
+ "chain": "main",
+ "isPrivkey": false
+ }
+ ],
+ [
+ "3NXqB6iZiPYbKruNT3d9xNBTmtb73xMvvf",
+ "a914e49decc9e5d97e0547d3642f3a4795b13ae62bca87",
+ {
+ "chain": "main",
+ "isPrivkey": false
+ }
+ ],
+ [
+ "mjgt4BoCYxjzWvJFoh68x7cj5GeaKDYhyx",
+ "76a9142dc11fc7b8072f733f690ffb0591c00f4062295c88ac",
{
- "isPrivkey": false,
"chain": "test",
- "tryCaseFlip": true
+ "isPrivkey": false
}
],
[
- "bcrt1qqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvseswlauz7",
- "0020000000c4a5cad46221b2a187905e5266362b99d5e91c6ce24d165dab93e86433",
+ "2NCT6FdQ5MxorHgnFxLeHyGwTGRdkHcrJDH",
+ "a914d2a8ec992b0894a0d9391ca5d9c45c388c41be7e87",
{
- "isPrivkey": false,
- "chain": "regtest",
- "tryCaseFlip": true
+ "chain": "test",
+ "isPrivkey": false
+ }
+ ],
+ [
+ "mpomiA7wqDnMcxaNLC23eBuXAb4U6H4ZqW",
+ "76a91465e75e340415ed297c58d6a14d3c17ceeaa17bbd88ac",
+ {
+ "chain": "signet",
+ "isPrivkey": false
+ }
+ ],
+ [
+ "2N1pGAA5uatbU2PKvMA9BnJmHcK6yHfMiZa",
+ "a9145e008b6cc232164570befc23d216060bf4ea793b87",
+ {
+ "chain": "signet",
+ "isPrivkey": false
}
]
]
diff --git a/src/test/denialofservice_tests.cpp b/src/test/denialofservice_tests.cpp
index e75982bc6f..7557d4618a 100644
--- a/src/test/denialofservice_tests.cpp
+++ b/src/test/denialofservice_tests.cpp
@@ -67,9 +67,9 @@ BOOST_FIXTURE_TEST_SUITE(denialofservice_tests, TestingSetup)
BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction)
{
const CChainParams& chainparams = Params();
- auto connman = std::make_unique<CConnman>(0x1337, 0x1337);
- auto peerLogic = PeerManager::make(chainparams, *connman, nullptr, *m_node.scheduler,
- *m_node.chainman, *m_node.mempool, false);
+ auto connman = std::make_unique<CConnman>(0x1337, 0x1337, *m_node.addrman);
+ auto peerLogic = PeerManager::make(chainparams, *connman, *m_node.addrman, nullptr,
+ *m_node.scheduler, *m_node.chainman, *m_node.mempool, false);
// Mock an outbound peer
CAddress addr1(ip(0xa0b0c001), NODE_NONE);
@@ -117,8 +117,7 @@ BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction)
BOOST_CHECK(dummyNode1.fDisconnect == true);
SetMockTime(0);
- bool dummy;
- peerLogic->FinalizeNode(dummyNode1, dummy);
+ peerLogic->FinalizeNode(dummyNode1);
}
static void AddRandomOutboundPeer(std::vector<CNode *> &vNodes, PeerManager &peerLogic, CConnmanTest* connman)
@@ -137,9 +136,9 @@ static void AddRandomOutboundPeer(std::vector<CNode *> &vNodes, PeerManager &pee
BOOST_AUTO_TEST_CASE(stale_tip_peer_management)
{
const CChainParams& chainparams = Params();
- auto connman = std::make_unique<CConnmanTest>(0x1337, 0x1337);
- auto peerLogic = PeerManager::make(chainparams, *connman, nullptr, *m_node.scheduler,
- *m_node.chainman, *m_node.mempool, false);
+ auto connman = std::make_unique<CConnmanTest>(0x1337, 0x1337, *m_node.addrman);
+ auto peerLogic = PeerManager::make(chainparams, *connman, *m_node.addrman, nullptr,
+ *m_node.scheduler, *m_node.chainman, *m_node.mempool, false);
constexpr int max_outbound_full_relay = MAX_OUTBOUND_FULL_RELAY_CONNECTIONS;
CConnman::Options options;
@@ -199,9 +198,8 @@ BOOST_AUTO_TEST_CASE(stale_tip_peer_management)
BOOST_CHECK(vNodes[max_outbound_full_relay-1]->fDisconnect == true);
BOOST_CHECK(vNodes.back()->fDisconnect == false);
- bool dummy;
for (const CNode *node : vNodes) {
- peerLogic->FinalizeNode(*node, dummy);
+ peerLogic->FinalizeNode(*node);
}
connman->ClearNodes();
@@ -211,9 +209,9 @@ BOOST_AUTO_TEST_CASE(peer_discouragement)
{
const CChainParams& chainparams = Params();
auto banman = std::make_unique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
- auto connman = std::make_unique<CConnman>(0x1337, 0x1337);
- auto peerLogic = PeerManager::make(chainparams, *connman, banman.get(), *m_node.scheduler,
- *m_node.chainman, *m_node.mempool, false);
+ auto connman = std::make_unique<CConnman>(0x1337, 0x1337, *m_node.addrman);
+ auto peerLogic = PeerManager::make(chainparams, *connman, *m_node.addrman, banman.get(),
+ *m_node.scheduler, *m_node.chainman, *m_node.mempool, false);
banman->ClearBanned();
CAddress addr1(ip(0xa0b0c001), NODE_NONE);
@@ -249,18 +247,17 @@ BOOST_AUTO_TEST_CASE(peer_discouragement)
BOOST_CHECK(banman->IsDiscouraged(addr1)); // Expect both 1 and 2
BOOST_CHECK(banman->IsDiscouraged(addr2)); // to be discouraged now
- bool dummy;
- peerLogic->FinalizeNode(dummyNode1, dummy);
- peerLogic->FinalizeNode(dummyNode2, dummy);
+ peerLogic->FinalizeNode(dummyNode1);
+ peerLogic->FinalizeNode(dummyNode2);
}
BOOST_AUTO_TEST_CASE(DoS_bantime)
{
const CChainParams& chainparams = Params();
auto banman = std::make_unique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
- auto connman = std::make_unique<CConnman>(0x1337, 0x1337);
- auto peerLogic = PeerManager::make(chainparams, *connman, banman.get(), *m_node.scheduler,
- *m_node.chainman, *m_node.mempool, false);
+ auto connman = std::make_unique<CConnman>(0x1337, 0x1337, *m_node.addrman);
+ auto peerLogic = PeerManager::make(chainparams, *connman, *m_node.addrman, banman.get(),
+ *m_node.scheduler, *m_node.chainman, *m_node.mempool, false);
banman->ClearBanned();
int64_t nStartTime = GetTime();
@@ -279,8 +276,7 @@ BOOST_AUTO_TEST_CASE(DoS_bantime)
}
BOOST_CHECK(banman->IsDiscouraged(addr));
- bool dummy;
- peerLogic->FinalizeNode(dummyNode, dummy);
+ peerLogic->FinalizeNode(dummyNode);
}
class TxOrphanageTest : public TxOrphanage
diff --git a/src/test/fuzz/addrman.cpp b/src/test/fuzz/addrman.cpp
index b55f1c72b1..0baf30aef6 100644
--- a/src/test/fuzz/addrman.cpp
+++ b/src/test/fuzz/addrman.cpp
@@ -104,7 +104,7 @@ FUZZ_TARGET_INIT(addrman, initialize_addrman)
[&] {
const std::optional<CService> opt_service = ConsumeDeserializable<CService>(fuzzed_data_provider);
if (opt_service) {
- addr_man.SetServices(*opt_service, ServiceFlags{fuzzed_data_provider.ConsumeIntegral<uint64_t>()});
+ addr_man.SetServices(*opt_service, ConsumeWeakEnum(fuzzed_data_provider, ALL_SERVICE_FLAGS));
}
},
[&] {
diff --git a/src/test/fuzz/asmap_direct.cpp b/src/test/fuzz/asmap_direct.cpp
index 8b7822dc16..8ca4de3919 100644
--- a/src/test/fuzz/asmap_direct.cpp
+++ b/src/test/fuzz/asmap_direct.cpp
@@ -2,8 +2,9 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include <test/fuzz/fuzz.h>
+#include <netaddress.h>
#include <util/asmap.h>
+#include <test/fuzz/fuzz.h>
#include <cstdint>
#include <optional>
diff --git a/src/test/fuzz/bech32.cpp b/src/test/fuzz/bech32.cpp
index 95cd4b413f..ad3bf73af4 100644
--- a/src/test/fuzz/bech32.cpp
+++ b/src/test/fuzz/bech32.cpp
@@ -16,28 +16,28 @@
FUZZ_TARGET(bech32)
{
const std::string random_string(buffer.begin(), buffer.end());
- const std::pair<std::string, std::vector<uint8_t>> r1 = bech32::Decode(random_string);
- if (r1.first.empty()) {
- assert(r1.second.empty());
+ const auto r1 = bech32::Decode(random_string);
+ if (r1.hrp.empty()) {
+ assert(r1.encoding == bech32::Encoding::INVALID);
+ assert(r1.data.empty());
} else {
- const std::string& hrp = r1.first;
- const std::vector<uint8_t>& data = r1.second;
- const std::string reencoded = bech32::Encode(hrp, data);
+ assert(r1.encoding != bech32::Encoding::INVALID);
+ const std::string reencoded = bech32::Encode(r1.encoding, r1.hrp, r1.data);
assert(CaseInsensitiveEqual(random_string, reencoded));
}
std::vector<unsigned char> input;
ConvertBits<8, 5, true>([&](unsigned char c) { input.push_back(c); }, buffer.begin(), buffer.end());
- const std::string encoded = bech32::Encode("bc", input);
- assert(!encoded.empty());
- const std::pair<std::string, std::vector<uint8_t>> r2 = bech32::Decode(encoded);
- if (r2.first.empty()) {
- assert(r2.second.empty());
- } else {
- const std::string& hrp = r2.first;
- const std::vector<uint8_t>& data = r2.second;
- assert(hrp == "bc");
- assert(data == input);
+ if (input.size() + 3 + 6 <= 90) {
+ // If it's possible to encode input in Bech32(m) without exceeding the 90-character limit:
+ for (auto encoding : {bech32::Encoding::BECH32, bech32::Encoding::BECH32M}) {
+ const std::string encoded = bech32::Encode(encoding, "bc", input);
+ assert(!encoded.empty());
+ const auto r2 = bech32::Decode(encoded);
+ assert(r2.encoding == encoding);
+ assert(r2.hrp == "bc");
+ assert(r2.data == input);
+ }
}
}
diff --git a/src/test/fuzz/connman.cpp b/src/test/fuzz/connman.cpp
index ae77a45e44..e07f25dedf 100644
--- a/src/test/fuzz/connman.cpp
+++ b/src/test/fuzz/connman.cpp
@@ -25,40 +25,25 @@ FUZZ_TARGET_INIT(connman, initialize_connman)
{
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
SetMockTime(ConsumeTime(fuzzed_data_provider));
- CConnman connman{fuzzed_data_provider.ConsumeIntegral<uint64_t>(), fuzzed_data_provider.ConsumeIntegral<uint64_t>(), fuzzed_data_provider.ConsumeBool()};
- CAddress random_address;
+ CAddrMan addrman;
+ CConnman connman{fuzzed_data_provider.ConsumeIntegral<uint64_t>(), fuzzed_data_provider.ConsumeIntegral<uint64_t>(), addrman, fuzzed_data_provider.ConsumeBool()};
CNetAddr random_netaddr;
CNode random_node = ConsumeNode(fuzzed_data_provider);
- CService random_service;
CSubNet random_subnet;
std::string random_string;
while (fuzzed_data_provider.ConsumeBool()) {
CallOneOf(
fuzzed_data_provider,
[&] {
- random_address = ConsumeAddress(fuzzed_data_provider);
- },
- [&] {
random_netaddr = ConsumeNetAddr(fuzzed_data_provider);
},
[&] {
- random_service = ConsumeService(fuzzed_data_provider);
- },
- [&] {
random_subnet = ConsumeSubNet(fuzzed_data_provider);
},
[&] {
random_string = fuzzed_data_provider.ConsumeRandomLengthString(64);
},
[&] {
- std::vector<CAddress> addresses;
- while (fuzzed_data_provider.ConsumeBool()) {
- addresses.push_back(ConsumeAddress(fuzzed_data_provider));
- }
- // Limit nTimePenalty to int32_t to avoid signed integer overflow
- (void)connman.AddNewAddresses(addresses, ConsumeAddress(fuzzed_data_provider), fuzzed_data_provider.ConsumeIntegral<int32_t>());
- },
- [&] {
connman.AddNode(random_string);
},
[&] {
@@ -98,9 +83,6 @@ FUZZ_TARGET_INIT(connman, initialize_connman)
(void)connman.GetNodeCount(fuzzed_data_provider.PickValueInArray({ConnectionDirection::None, ConnectionDirection::In, ConnectionDirection::Out, ConnectionDirection::Both}));
},
[&] {
- connman.MarkAddressGood(random_address);
- },
- [&] {
(void)connman.OutboundTargetReached(fuzzed_data_provider.ConsumeBool());
},
[&] {
@@ -128,9 +110,6 @@ FUZZ_TARGET_INIT(connman, initialize_connman)
connman.SetNetworkActive(fuzzed_data_provider.ConsumeBool());
},
[&] {
- connman.SetServices(random_service, ConsumeWeakEnum(fuzzed_data_provider, ALL_SERVICE_FLAGS));
- },
- [&] {
connman.SetTryNewOutboundPeer(fuzzed_data_provider.ConsumeBool());
});
}
diff --git a/src/test/fuzz/cuckoocache.cpp b/src/test/fuzz/cuckoocache.cpp
index dc20dc3f62..a522c837ef 100644
--- a/src/test/fuzz/cuckoocache.cpp
+++ b/src/test/fuzz/cuckoocache.cpp
@@ -30,7 +30,7 @@ FUZZ_TARGET(cuckoocache)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
fuzzed_data_provider_ptr = &fuzzed_data_provider;
- CuckooCache::cache<bool, RandomHasher> cuckoo_cache{};
+ CuckooCache::cache<int, RandomHasher> cuckoo_cache{};
if (fuzzed_data_provider.ConsumeBool()) {
const size_t megabytes = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 16);
cuckoo_cache.setup_bytes(megabytes << 20);
diff --git a/src/test/fuzz/netbase_dns_lookup.cpp b/src/test/fuzz/netbase_dns_lookup.cpp
index 7be8b13743..cf2fa33744 100644
--- a/src/test/fuzz/netbase_dns_lookup.cpp
+++ b/src/test/fuzz/netbase_dns_lookup.cpp
@@ -18,7 +18,7 @@ FUZZ_TARGET(netbase_dns_lookup)
const std::string name = fuzzed_data_provider.ConsumeRandomLengthString(512);
const unsigned int max_results = fuzzed_data_provider.ConsumeIntegral<unsigned int>();
const bool allow_lookup = fuzzed_data_provider.ConsumeBool();
- const int default_port = fuzzed_data_provider.ConsumeIntegral<int>();
+ const uint16_t default_port = fuzzed_data_provider.ConsumeIntegral<uint16_t>();
auto fuzzed_dns_lookup_function = [&](const std::string&, bool) {
std::vector<CNetAddr> resolved_addresses;
diff --git a/src/test/fuzz/parse_numbers.cpp b/src/test/fuzz/parse_numbers.cpp
index 1ad5fb6a05..2c546e9b4a 100644
--- a/src/test/fuzz/parse_numbers.cpp
+++ b/src/test/fuzz/parse_numbers.cpp
@@ -21,6 +21,9 @@ FUZZ_TARGET(parse_numbers)
uint8_t u8;
(void)ParseUInt8(random_string, &u8);
+ uint16_t u16;
+ (void)ParseUInt16(random_string, &u16);
+
int32_t i32;
(void)ParseInt32(random_string, &i32);
(void)atoi(random_string);
diff --git a/src/test/fuzz/pow.cpp b/src/test/fuzz/pow.cpp
index 53726ca893..47b4323e81 100644
--- a/src/test/fuzz/pow.cpp
+++ b/src/test/fuzz/pow.cpp
@@ -34,7 +34,7 @@ FUZZ_TARGET_INIT(pow, initialize_pow)
}
CBlockIndex current_block{*block_header};
{
- CBlockIndex* previous_block = !blocks.empty() ? &blocks[fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, blocks.size() - 1)] : nullptr;
+ CBlockIndex* previous_block = blocks.empty() ? nullptr : &PickValue(fuzzed_data_provider, blocks);
const int current_height = (previous_block != nullptr && previous_block->nHeight != std::numeric_limits<int>::max()) ? previous_block->nHeight + 1 : 0;
if (fuzzed_data_provider.ConsumeBool()) {
current_block.pprev = previous_block;
@@ -66,9 +66,9 @@ FUZZ_TARGET_INIT(pow, initialize_pow)
}
}
{
- const CBlockIndex* to = &blocks[fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, blocks.size() - 1)];
- const CBlockIndex* from = &blocks[fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, blocks.size() - 1)];
- const CBlockIndex* tip = &blocks[fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, blocks.size() - 1)];
+ const CBlockIndex* to = &PickValue(fuzzed_data_provider, blocks);
+ const CBlockIndex* from = &PickValue(fuzzed_data_provider, blocks);
+ const CBlockIndex* tip = &PickValue(fuzzed_data_provider, blocks);
try {
(void)GetBlockProofEquivalentTime(*to, *from, *tip, consensus_params);
} catch (const uint_error&) {
diff --git a/src/test/fuzz/process_message.cpp b/src/test/fuzz/process_message.cpp
index 04fc6da9b1..96e1cfa08f 100644
--- a/src/test/fuzz/process_message.cpp
+++ b/src/test/fuzz/process_message.cpp
@@ -68,8 +68,8 @@ void fuzz_target(FuzzBufferType buffer, const std::string& LIMIT_TO_MESSAGE_TYPE
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
- ConnmanTestMsg& connman = *(ConnmanTestMsg*)g_setup->m_node.connman.get();
- TestChainState& chainstate = *(TestChainState*)&g_setup->m_node.chainman->ActiveChainstate();
+ ConnmanTestMsg& connman = *static_cast<ConnmanTestMsg*>(g_setup->m_node.connman.get());
+ TestChainState& chainstate = *static_cast<TestChainState*>(&g_setup->m_node.chainman->ActiveChainstate());
SetMockTime(1610000000); // any time to successfully reset ibd
chainstate.ResetIbd();
diff --git a/src/test/fuzz/process_messages.cpp b/src/test/fuzz/process_messages.cpp
index ee402dba38..203c0ef8e1 100644
--- a/src/test/fuzz/process_messages.cpp
+++ b/src/test/fuzz/process_messages.cpp
@@ -35,8 +35,8 @@ FUZZ_TARGET_INIT(process_messages, initialize_process_messages)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
- ConnmanTestMsg& connman = *(ConnmanTestMsg*)g_setup->m_node.connman.get();
- TestChainState& chainstate = *(TestChainState*)&g_setup->m_node.chainman->ActiveChainstate();
+ ConnmanTestMsg& connman = *static_cast<ConnmanTestMsg*>(g_setup->m_node.connman.get());
+ TestChainState& chainstate = *static_cast<TestChainState*>(&g_setup->m_node.chainman->ActiveChainstate());
SetMockTime(1610000000); // any time to successfully reset ibd
chainstate.ResetIbd();
@@ -65,7 +65,7 @@ FUZZ_TARGET_INIT(process_messages, initialize_process_messages)
net_msg.m_type = random_message_type;
net_msg.data = ConsumeRandomLengthByteVector(fuzzed_data_provider);
- CNode& random_node = *peers.at(fuzzed_data_provider.ConsumeIntegralInRange<int>(0, peers.size() - 1));
+ CNode& random_node = *PickValue(fuzzed_data_provider, peers);
(void)connman.ReceiveMsgFrom(random_node, net_msg);
random_node.fPauseSend = false;
diff --git a/src/test/fuzz/script.cpp b/src/test/fuzz/script.cpp
index 8219a04e49..e87ae5b04b 100644
--- a/src/test/fuzz/script.cpp
+++ b/src/test/fuzz/script.cpp
@@ -103,9 +103,11 @@ FUZZ_TARGET_INIT(script, initialize_script)
(void)ScriptToAsmStr(script, true);
UniValue o1(UniValue::VOBJ);
- ScriptPubKeyToUniv(script, o1, true);
+ ScriptPubKeyToUniv(script, o1, true, true);
+ ScriptPubKeyToUniv(script, o1, true, false);
UniValue o2(UniValue::VOBJ);
- ScriptPubKeyToUniv(script, o2, false);
+ ScriptPubKeyToUniv(script, o2, false, true);
+ ScriptPubKeyToUniv(script, o2, false, false);
UniValue o3(UniValue::VOBJ);
ScriptToUniv(script, o3, true);
UniValue o4(UniValue::VOBJ);
diff --git a/src/test/fuzz/socks5.cpp b/src/test/fuzz/socks5.cpp
index e5cc4cabe5..c3a6eed089 100644
--- a/src/test/fuzz/socks5.cpp
+++ b/src/test/fuzz/socks5.cpp
@@ -2,6 +2,7 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#include <netaddress.h>
#include <netbase.h>
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
@@ -38,7 +39,7 @@ FUZZ_TARGET_INIT(socks5, initialize_socks5)
// This Socks5(...) fuzzing harness would have caught CVE-2017-18350 within
// a few seconds of fuzzing.
(void)Socks5(fuzzed_data_provider.ConsumeRandomLengthString(512),
- fuzzed_data_provider.ConsumeIntegral<int>(),
+ fuzzed_data_provider.ConsumeIntegral<uint16_t>(),
fuzzed_data_provider.ConsumeBool() ? &proxy_credentials : nullptr,
fuzzed_sock);
}
diff --git a/src/test/fuzz/string.cpp b/src/test/fuzz/string.cpp
index 93b4948a2f..286375f7ae 100644
--- a/src/test/fuzz/string.cpp
+++ b/src/test/fuzz/string.cpp
@@ -5,6 +5,7 @@
#include <blockfilter.h>
#include <clientversion.h>
#include <logging.h>
+#include <netaddress.h>
#include <netbase.h>
#include <outputtype.h>
#include <rpc/client.h>
@@ -82,7 +83,7 @@ FUZZ_TARGET(string)
#ifndef WIN32
(void)ShellEscape(random_string_1);
#endif // WIN32
- int port_out;
+ uint16_t port_out;
std::string host_out;
SplitHostPort(random_string_1, port_out, host_out);
(void)TimingResistantEqual(random_string_1, random_string_2);
diff --git a/src/test/fuzz/transaction.cpp b/src/test/fuzz/transaction.cpp
index 41e1687405..17e4405a13 100644
--- a/src/test/fuzz/transaction.cpp
+++ b/src/test/fuzz/transaction.cpp
@@ -100,7 +100,9 @@ FUZZ_TARGET_INIT(transaction, initialize_transaction)
(void)IsWitnessStandard(tx, coins_view_cache);
UniValue u(UniValue::VOBJ);
- TxToUniv(tx, /* hashBlock */ {}, u);
+ TxToUniv(tx, /* hashBlock */ {}, /* include_addresses */ true, u);
+ TxToUniv(tx, /* hashBlock */ {}, /* include_addresses */ false, u);
static const uint256 u256_max(uint256S("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"));
- TxToUniv(tx, u256_max, u);
+ TxToUniv(tx, u256_max, /* include_addresses */ true, u);
+ TxToUniv(tx, u256_max, /* include_addresses */ false, u);
}
diff --git a/src/test/fuzz/tx_pool.cpp b/src/test/fuzz/tx_pool.cpp
new file mode 100644
index 0000000000..f84d6702a7
--- /dev/null
+++ b/src/test/fuzz/tx_pool.cpp
@@ -0,0 +1,285 @@
+// Copyright (c) 2021 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <consensus/validation.h>
+#include <test/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+#include <test/fuzz/util.h>
+#include <test/util/mining.h>
+#include <test/util/script.h>
+#include <test/util/setup_common.h>
+#include <util/rbf.h>
+#include <validation.h>
+#include <validationinterface.h>
+
+namespace {
+
+const TestingSetup* g_setup;
+std::vector<COutPoint> g_outpoints_coinbase_init_mature;
+std::vector<COutPoint> g_outpoints_coinbase_init_immature;
+
+struct MockedTxPool : public CTxMemPool {
+ void RollingFeeUpdate()
+ {
+ lastRollingFeeUpdate = GetTime();
+ blockSinceLastRollingFeeBump = true;
+ }
+};
+
+void initialize_tx_pool()
+{
+ static const auto testing_setup = MakeNoLogFileContext<const TestingSetup>();
+ g_setup = testing_setup.get();
+
+ for (int i = 0; i < 2 * COINBASE_MATURITY; ++i) {
+ CTxIn in = MineBlock(g_setup->m_node, P2WSH_OP_TRUE);
+ // Remember the txids to avoid expensive disk acess later on
+ auto& outpoints = i < COINBASE_MATURITY ?
+ g_outpoints_coinbase_init_mature :
+ g_outpoints_coinbase_init_immature;
+ outpoints.push_back(in.prevout);
+ }
+ SyncWithValidationInterfaceQueue();
+}
+
+struct TransactionsDelta final : public CValidationInterface {
+ std::set<CTransactionRef>& m_removed;
+ std::set<CTransactionRef>& m_added;
+
+ explicit TransactionsDelta(std::set<CTransactionRef>& r, std::set<CTransactionRef>& a)
+ : m_removed{r}, m_added{a} {}
+
+ void TransactionAddedToMempool(const CTransactionRef& tx, uint64_t /* mempool_sequence */) override
+ {
+ Assert(m_added.insert(tx).second);
+ }
+
+ void TransactionRemovedFromMempool(const CTransactionRef& tx, MemPoolRemovalReason reason, uint64_t /* mempool_sequence */) override
+ {
+ Assert(m_removed.insert(tx).second);
+ }
+};
+
+void SetMempoolConstraints(ArgsManager& args, FuzzedDataProvider& fuzzed_data_provider)
+{
+ args.ForceSetArg("-limitancestorcount",
+ ToString(fuzzed_data_provider.ConsumeIntegralInRange<unsigned>(0, 50)));
+ args.ForceSetArg("-limitancestorsize",
+ ToString(fuzzed_data_provider.ConsumeIntegralInRange<unsigned>(0, 202)));
+ args.ForceSetArg("-limitdescendantcount",
+ ToString(fuzzed_data_provider.ConsumeIntegralInRange<unsigned>(0, 50)));
+ args.ForceSetArg("-limitdescendantsize",
+ ToString(fuzzed_data_provider.ConsumeIntegralInRange<unsigned>(0, 202)));
+ args.ForceSetArg("-maxmempool",
+ ToString(fuzzed_data_provider.ConsumeIntegralInRange<unsigned>(0, 200)));
+ args.ForceSetArg("-mempoolexpiry",
+ ToString(fuzzed_data_provider.ConsumeIntegralInRange<unsigned>(0, 999)));
+}
+
+FUZZ_TARGET_INIT(tx_pool_standard, initialize_tx_pool)
+{
+ FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
+ const auto& node = g_setup->m_node;
+ auto& chainstate = node.chainman->ActiveChainstate();
+
+ SetMockTime(ConsumeTime(fuzzed_data_provider));
+ SetMempoolConstraints(*node.args, fuzzed_data_provider);
+
+ // All RBF-spendable outpoints
+ std::set<COutPoint> outpoints_rbf;
+ // All outpoints counting toward the total supply (subset of outpoints_rbf)
+ std::set<COutPoint> outpoints_supply;
+ for (const auto& outpoint : g_outpoints_coinbase_init_mature) {
+ Assert(outpoints_supply.insert(outpoint).second);
+ }
+ outpoints_rbf = outpoints_supply;
+
+ // The sum of the values of all spendable outpoints
+ constexpr CAmount SUPPLY_TOTAL{COINBASE_MATURITY * 50 * COIN};
+
+ CTxMemPool tx_pool_{/* estimator */ nullptr, /* check_ratio */ 1};
+ MockedTxPool& tx_pool = *static_cast<MockedTxPool*>(&tx_pool_);
+
+ // Helper to query an amount
+ const CCoinsViewMemPool amount_view{WITH_LOCK(::cs_main, return &chainstate.CoinsTip()), tx_pool};
+ const auto GetAmount = [&](const COutPoint& outpoint) {
+ Coin c;
+ Assert(amount_view.GetCoin(outpoint, c));
+ return c.out.nValue;
+ };
+
+ while (fuzzed_data_provider.ConsumeBool()) {
+ {
+ // Total supply is the mempool fee + all outpoints
+ CAmount supply_now{WITH_LOCK(tx_pool.cs, return tx_pool.GetTotalFee())};
+ for (const auto& op : outpoints_supply) {
+ supply_now += GetAmount(op);
+ }
+ Assert(supply_now == SUPPLY_TOTAL);
+ }
+ Assert(!outpoints_supply.empty());
+
+ // Create transaction to add to the mempool
+ const CTransactionRef tx = [&] {
+ CMutableTransaction tx_mut;
+ tx_mut.nVersion = CTransaction::CURRENT_VERSION;
+ tx_mut.nLockTime = fuzzed_data_provider.ConsumeBool() ? 0 : fuzzed_data_provider.ConsumeIntegral<uint32_t>();
+ const auto num_in = fuzzed_data_provider.ConsumeIntegralInRange<int>(1, outpoints_rbf.size());
+ const auto num_out = fuzzed_data_provider.ConsumeIntegralInRange<int>(1, outpoints_rbf.size() * 2);
+
+ CAmount amount_in{0};
+ for (int i = 0; i < num_in; ++i) {
+ // Pop random outpoint
+ auto pop = outpoints_rbf.begin();
+ std::advance(pop, fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, outpoints_rbf.size() - 1));
+ const auto outpoint = *pop;
+ outpoints_rbf.erase(pop);
+ amount_in += GetAmount(outpoint);
+
+ // Create input
+ const auto sequence = ConsumeSequence(fuzzed_data_provider);
+ const auto script_sig = CScript{};
+ const auto script_wit_stack = std::vector<std::vector<uint8_t>>{WITNESS_STACK_ELEM_OP_TRUE};
+ CTxIn in;
+ in.prevout = outpoint;
+ in.nSequence = sequence;
+ in.scriptSig = script_sig;
+ in.scriptWitness.stack = script_wit_stack;
+
+ tx_mut.vin.push_back(in);
+ }
+ const auto amount_fee = fuzzed_data_provider.ConsumeIntegralInRange<CAmount>(-1000, amount_in);
+ const auto amount_out = (amount_in - amount_fee) / num_out;
+ for (int i = 0; i < num_out; ++i) {
+ tx_mut.vout.emplace_back(amount_out, P2WSH_OP_TRUE);
+ }
+ const auto tx = MakeTransactionRef(tx_mut);
+ // Restore previously removed outpoints
+ for (const auto& in : tx->vin) {
+ Assert(outpoints_rbf.insert(in.prevout).second);
+ }
+ return tx;
+ }();
+
+ if (fuzzed_data_provider.ConsumeBool()) {
+ SetMockTime(ConsumeTime(fuzzed_data_provider));
+ }
+ if (fuzzed_data_provider.ConsumeBool()) {
+ SetMempoolConstraints(*node.args, fuzzed_data_provider);
+ }
+ if (fuzzed_data_provider.ConsumeBool()) {
+ tx_pool.RollingFeeUpdate();
+ }
+ if (fuzzed_data_provider.ConsumeBool()) {
+ const auto& txid = fuzzed_data_provider.ConsumeBool() ?
+ tx->GetHash() :
+ PickValue(fuzzed_data_provider, outpoints_rbf).hash;
+ const auto delta = fuzzed_data_provider.ConsumeIntegralInRange<CAmount>(-50 * COIN, +50 * COIN);
+ tx_pool.PrioritiseTransaction(txid, delta);
+ }
+
+ // Remember all removed and added transactions
+ std::set<CTransactionRef> removed;
+ std::set<CTransactionRef> added;
+ auto txr = std::make_shared<TransactionsDelta>(removed, added);
+ RegisterSharedValidationInterface(txr);
+ const bool bypass_limits = fuzzed_data_provider.ConsumeBool();
+ ::fRequireStandard = fuzzed_data_provider.ConsumeBool();
+ const auto res = WITH_LOCK(::cs_main, return AcceptToMemoryPool(chainstate, tx_pool, tx, bypass_limits));
+ const bool accepted = res.m_result_type == MempoolAcceptResult::ResultType::VALID;
+ SyncWithValidationInterfaceQueue();
+ UnregisterSharedValidationInterface(txr);
+
+ Assert(accepted != added.empty());
+ Assert(accepted == res.m_state.IsValid());
+ Assert(accepted != res.m_state.IsInvalid());
+ if (accepted) {
+ Assert(added.size() == 1); // For now, no package acceptance
+ Assert(tx == *added.begin());
+ } else {
+ // Do not consider rejected transaction removed
+ removed.erase(tx);
+ }
+
+ // Helper to insert spent and created outpoints of a tx into collections
+ using Sets = std::vector<std::reference_wrapper<std::set<COutPoint>>>;
+ const auto insert_tx = [](Sets created_by_tx, Sets consumed_by_tx, const auto& tx) {
+ for (size_t i{0}; i < tx.vout.size(); ++i) {
+ for (auto& set : created_by_tx) {
+ Assert(set.get().emplace(tx.GetHash(), i).second);
+ }
+ }
+ for (const auto& in : tx.vin) {
+ for (auto& set : consumed_by_tx) {
+ Assert(set.get().insert(in.prevout).second);
+ }
+ }
+ };
+ // Add created outpoints, remove spent outpoints
+ {
+ // Outpoints that no longer exist at all
+ std::set<COutPoint> consumed_erased;
+ // Outpoints that no longer count toward the total supply
+ std::set<COutPoint> consumed_supply;
+ for (const auto& removed_tx : removed) {
+ insert_tx(/* created_by_tx */ {consumed_erased}, /* consumed_by_tx */ {outpoints_supply}, /* tx */ *removed_tx);
+ }
+ for (const auto& added_tx : added) {
+ insert_tx(/* created_by_tx */ {outpoints_supply, outpoints_rbf}, /* consumed_by_tx */ {consumed_supply}, /* tx */ *added_tx);
+ }
+ for (const auto& p : consumed_erased) {
+ Assert(outpoints_supply.erase(p) == 1);
+ Assert(outpoints_rbf.erase(p) == 1);
+ }
+ for (const auto& p : consumed_supply) {
+ Assert(outpoints_supply.erase(p) == 1);
+ }
+ }
+ }
+ WITH_LOCK(::cs_main, tx_pool.check(chainstate));
+ const auto info_all = tx_pool.infoAll();
+ if (!info_all.empty()) {
+ const auto& tx_to_remove = *PickValue(fuzzed_data_provider, info_all).tx;
+ WITH_LOCK(tx_pool.cs, tx_pool.removeRecursive(tx_to_remove, /* dummy */ MemPoolRemovalReason::BLOCK));
+ std::vector<uint256> all_txids;
+ tx_pool.queryHashes(all_txids);
+ assert(all_txids.size() < info_all.size());
+ WITH_LOCK(::cs_main, tx_pool.check(chainstate));
+ }
+ SyncWithValidationInterfaceQueue();
+}
+
+FUZZ_TARGET_INIT(tx_pool, initialize_tx_pool)
+{
+ FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
+ const auto& node = g_setup->m_node;
+
+ std::vector<uint256> txids;
+ for (const auto& outpoint : g_outpoints_coinbase_init_mature) {
+ txids.push_back(outpoint.hash);
+ }
+ for (int i{0}; i <= 3; ++i) {
+ // Add some immature and non-existent outpoints
+ txids.push_back(g_outpoints_coinbase_init_immature.at(i).hash);
+ txids.push_back(ConsumeUInt256(fuzzed_data_provider));
+ }
+
+ CTxMemPool tx_pool{/* estimator */ nullptr, /* check_ratio */ 1};
+
+ while (fuzzed_data_provider.ConsumeBool()) {
+ const auto mut_tx = ConsumeTransaction(fuzzed_data_provider, txids);
+
+ const auto tx = MakeTransactionRef(mut_tx);
+ const bool bypass_limits = fuzzed_data_provider.ConsumeBool();
+ ::fRequireStandard = fuzzed_data_provider.ConsumeBool();
+ const auto res = WITH_LOCK(::cs_main, return AcceptToMemoryPool(node.chainman->ActiveChainstate(), tx_pool, tx, bypass_limits));
+ const bool accepted = res.m_result_type == MempoolAcceptResult::ResultType::VALID;
+ if (accepted) {
+ txids.push_back(tx->GetHash());
+ }
+
+ SyncWithValidationInterfaceQueue();
+ }
+}
+} // namespace
diff --git a/src/test/fuzz/util.cpp b/src/test/fuzz/util.cpp
index 0a541e4186..93418ab1ff 100644
--- a/src/test/fuzz/util.cpp
+++ b/src/test/fuzz/util.cpp
@@ -3,8 +3,11 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <test/fuzz/util.h>
+#include <test/util/script.h>
+#include <util/rbf.h>
#include <version.h>
+
void FillNode(FuzzedDataProvider& fuzzed_data_provider, CNode& node, bool init_version) noexcept
{
const ServiceFlags remote_services = ConsumeWeakEnum(fuzzed_data_provider, ALL_SERVICE_FLAGS);
@@ -23,3 +26,78 @@ void FillNode(FuzzedDataProvider& fuzzed_data_provider, CNode& node, bool init_v
node.m_tx_relay->fRelayTxes = filter_txs;
}
}
+
+CMutableTransaction ConsumeTransaction(FuzzedDataProvider& fuzzed_data_provider, const std::optional<std::vector<uint256>>& prevout_txids, const int max_num_in, const int max_num_out) noexcept
+{
+ CMutableTransaction tx_mut;
+ const auto p2wsh_op_true = fuzzed_data_provider.ConsumeBool();
+ tx_mut.nVersion = fuzzed_data_provider.ConsumeBool() ?
+ CTransaction::CURRENT_VERSION :
+ fuzzed_data_provider.ConsumeIntegral<int32_t>();
+ tx_mut.nLockTime = fuzzed_data_provider.ConsumeIntegral<uint32_t>();
+ const auto num_in = fuzzed_data_provider.ConsumeIntegralInRange<int>(0, max_num_in);
+ const auto num_out = fuzzed_data_provider.ConsumeIntegralInRange<int>(0, max_num_out);
+ for (int i = 0; i < num_in; ++i) {
+ const auto& txid_prev = prevout_txids ?
+ PickValue(fuzzed_data_provider, *prevout_txids) :
+ ConsumeUInt256(fuzzed_data_provider);
+ const auto index_out = fuzzed_data_provider.ConsumeIntegralInRange<uint32_t>(0, max_num_out);
+ const auto sequence = ConsumeSequence(fuzzed_data_provider);
+ const auto script_sig = p2wsh_op_true ? CScript{} : ConsumeScript(fuzzed_data_provider);
+ CScriptWitness script_wit;
+ if (p2wsh_op_true) {
+ script_wit.stack = std::vector<std::vector<uint8_t>>{WITNESS_STACK_ELEM_OP_TRUE};
+ } else {
+ script_wit = ConsumeScriptWitness(fuzzed_data_provider);
+ }
+ CTxIn in;
+ in.prevout = COutPoint{txid_prev, index_out};
+ in.nSequence = sequence;
+ in.scriptSig = script_sig;
+ in.scriptWitness = script_wit;
+
+ tx_mut.vin.push_back(in);
+ }
+ for (int i = 0; i < num_out; ++i) {
+ const auto amount = fuzzed_data_provider.ConsumeIntegralInRange<CAmount>(-10, 50 * COIN + 10);
+ const auto script_pk = p2wsh_op_true ?
+ P2WSH_OP_TRUE :
+ ConsumeScript(fuzzed_data_provider, /* max_length */ 128, /* maybe_p2wsh */ true);
+ tx_mut.vout.emplace_back(amount, script_pk);
+ }
+ return tx_mut;
+}
+
+CScriptWitness ConsumeScriptWitness(FuzzedDataProvider& fuzzed_data_provider, const size_t max_stack_elem_size) noexcept
+{
+ CScriptWitness ret;
+ const auto n_elements = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, max_stack_elem_size);
+ for (size_t i = 0; i < n_elements; ++i) {
+ ret.stack.push_back(ConsumeRandomLengthByteVector(fuzzed_data_provider));
+ }
+ return ret;
+}
+
+CScript ConsumeScript(FuzzedDataProvider& fuzzed_data_provider, const size_t max_length, const bool maybe_p2wsh) noexcept
+{
+ const std::vector<uint8_t> b = ConsumeRandomLengthByteVector(fuzzed_data_provider);
+ CScript r_script{b.begin(), b.end()};
+ if (maybe_p2wsh && fuzzed_data_provider.ConsumeBool()) {
+ uint256 script_hash;
+ CSHA256().Write(&r_script[0], r_script.size()).Finalize(script_hash.begin());
+ r_script.clear();
+ r_script << OP_0 << ToByteVector(script_hash);
+ }
+ return r_script;
+}
+
+uint32_t ConsumeSequence(FuzzedDataProvider& fuzzed_data_provider) noexcept
+{
+ return fuzzed_data_provider.ConsumeBool() ?
+ fuzzed_data_provider.PickValueInArray({
+ CTxIn::SEQUENCE_FINAL,
+ CTxIn::SEQUENCE_FINAL - 1,
+ MAX_BIP125_RBF_SEQUENCE,
+ }) :
+ fuzzed_data_provider.ConsumeIntegral<uint32_t>();
+}
diff --git a/src/test/fuzz/util.h b/src/test/fuzz/util.h
index cdddad82b3..d5c54911c5 100644
--- a/src/test/fuzz/util.h
+++ b/src/test/fuzz/util.h
@@ -48,6 +48,16 @@ void CallOneOf(FuzzedDataProvider& fuzzed_data_provider, Callables... callables)
return ((i++ == call_index ? callables() : void()), ...);
}
+template <typename Collection>
+auto& PickValue(FuzzedDataProvider& fuzzed_data_provider, Collection& col)
+{
+ const auto sz = col.size();
+ assert(sz >= 1);
+ auto it = col.begin();
+ std::advance(it, fuzzed_data_provider.ConsumeIntegralInRange<decltype(sz)>(0, sz - 1));
+ return *it;
+}
+
[[nodiscard]] inline std::vector<uint8_t> ConsumeRandomLengthByteVector(FuzzedDataProvider& fuzzed_data_provider, const size_t max_length = 4096) noexcept
{
const std::string s = fuzzed_data_provider.ConsumeRandomLengthString(max_length);
@@ -125,11 +135,13 @@ template <typename WeakEnumType, size_t size>
return fuzzed_data_provider.ConsumeIntegralInRange<int64_t>(time_min, time_max);
}
-[[nodiscard]] inline CScript ConsumeScript(FuzzedDataProvider& fuzzed_data_provider) noexcept
-{
- const std::vector<uint8_t> b = ConsumeRandomLengthByteVector(fuzzed_data_provider);
- return {b.begin(), b.end()};
-}
+[[nodiscard]] CMutableTransaction ConsumeTransaction(FuzzedDataProvider& fuzzed_data_provider, const std::optional<std::vector<uint256>>& prevout_txids, const int max_num_in = 10, const int max_num_out = 10) noexcept;
+
+[[nodiscard]] CScriptWitness ConsumeScriptWitness(FuzzedDataProvider& fuzzed_data_provider, const size_t max_stack_elem_size = 32) noexcept;
+
+[[nodiscard]] CScript ConsumeScript(FuzzedDataProvider& fuzzed_data_provider, const size_t max_length = 4096, const bool maybe_p2wsh = false) noexcept;
+
+[[nodiscard]] uint32_t ConsumeSequence(FuzzedDataProvider& fuzzed_data_provider) noexcept;
[[nodiscard]] inline CScriptNum ConsumeScriptNum(FuzzedDataProvider& fuzzed_data_provider) noexcept
{
diff --git a/src/test/fuzz/versionbits.cpp b/src/test/fuzz/versionbits.cpp
new file mode 100644
index 0000000000..88c1a1a9cb
--- /dev/null
+++ b/src/test/fuzz/versionbits.cpp
@@ -0,0 +1,351 @@
+// Copyright (c) 2020-2021 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 <chain.h>
+#include <chainparams.h>
+#include <consensus/params.h>
+#include <primitives/block.h>
+#include <versionbits.h>
+
+#include <test/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+#include <test/fuzz/util.h>
+
+#include <cstdint>
+#include <limits>
+#include <memory>
+#include <vector>
+
+namespace {
+class TestConditionChecker : public AbstractThresholdConditionChecker
+{
+private:
+ mutable ThresholdConditionCache m_cache;
+ const Consensus::Params dummy_params{};
+
+public:
+ const int64_t m_begin;
+ const int64_t m_end;
+ const int m_period;
+ const int m_threshold;
+ const int m_bit;
+
+ TestConditionChecker(int64_t begin, int64_t end, int period, int threshold, int bit)
+ : m_begin{begin}, m_end{end}, m_period{period}, m_threshold{threshold}, m_bit{bit}
+ {
+ assert(m_period > 0);
+ assert(0 <= m_threshold && m_threshold <= m_period);
+ assert(0 <= m_bit && m_bit < 32 && m_bit < VERSIONBITS_NUM_BITS);
+ }
+
+ bool Condition(const CBlockIndex* pindex, const Consensus::Params& params) const override { return Condition(pindex->nVersion); }
+ int64_t BeginTime(const Consensus::Params& params) const override { return m_begin; }
+ int64_t EndTime(const Consensus::Params& params) const override { return m_end; }
+ int Period(const Consensus::Params& params) const override { return m_period; }
+ int Threshold(const Consensus::Params& params) const override { return m_threshold; }
+
+ ThresholdState GetStateFor(const CBlockIndex* pindexPrev) const { return AbstractThresholdConditionChecker::GetStateFor(pindexPrev, dummy_params, m_cache); }
+ int GetStateSinceHeightFor(const CBlockIndex* pindexPrev) const { return AbstractThresholdConditionChecker::GetStateSinceHeightFor(pindexPrev, dummy_params, m_cache); }
+ BIP9Stats GetStateStatisticsFor(const CBlockIndex* pindexPrev) const { return AbstractThresholdConditionChecker::GetStateStatisticsFor(pindexPrev, dummy_params); }
+
+ bool Condition(int32_t version) const
+ {
+ uint32_t mask = ((uint32_t)1) << m_bit;
+ return (((version & VERSIONBITS_TOP_MASK) == VERSIONBITS_TOP_BITS) && (version & mask) != 0);
+ }
+
+ bool Condition(const CBlockIndex* pindex) const { return Condition(pindex->nVersion); }
+};
+
+/** Track blocks mined for test */
+class Blocks
+{
+private:
+ std::vector<std::unique_ptr<CBlockIndex>> m_blocks;
+ const uint32_t m_start_time;
+ const uint32_t m_interval;
+ const int32_t m_signal;
+ const int32_t m_no_signal;
+
+public:
+ Blocks(uint32_t start_time, uint32_t interval, int32_t signal, int32_t no_signal)
+ : m_start_time{start_time}, m_interval{interval}, m_signal{signal}, m_no_signal{no_signal} {}
+
+ size_t size() const { return m_blocks.size(); }
+
+ CBlockIndex* tip() const
+ {
+ return m_blocks.empty() ? nullptr : m_blocks.back().get();
+ }
+
+ CBlockIndex* mine_block(bool signal)
+ {
+ CBlockHeader header;
+ header.nVersion = signal ? m_signal : m_no_signal;
+ header.nTime = m_start_time + m_blocks.size() * m_interval;
+ header.nBits = 0x1d00ffff;
+
+ auto current_block = std::make_unique<CBlockIndex>(header);
+ current_block->pprev = tip();
+ current_block->nHeight = m_blocks.size();
+ current_block->BuildSkip();
+
+ return m_blocks.emplace_back(std::move(current_block)).get();
+ }
+};
+
+std::unique_ptr<const CChainParams> g_params;
+
+void initialize()
+{
+ // this is actually comparatively slow, so only do it once
+ g_params = CreateChainParams(ArgsManager{}, CBaseChainParams::MAIN);
+ assert(g_params != nullptr);
+}
+
+constexpr uint32_t MAX_START_TIME = 4102444800; // 2100-01-01
+
+FUZZ_TARGET_INIT(versionbits, initialize)
+{
+ const CChainParams& params = *g_params;
+ const int64_t interval = params.GetConsensus().nPowTargetSpacing;
+ assert(interval > 1); // need to be able to halve it
+ assert(interval < std::numeric_limits<int32_t>::max());
+
+ FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
+
+ // making period/max_periods larger slows these tests down significantly
+ const int period = 32;
+ const size_t max_periods = 16;
+ const size_t max_blocks = 2 * period * max_periods;
+
+ const int threshold = fuzzed_data_provider.ConsumeIntegralInRange(1, period);
+ assert(0 < threshold && threshold <= period); // must be able to both pass and fail threshold!
+
+ // too many blocks at 10min each might cause uint32_t time to overflow if
+ // block_start_time is at the end of the range above
+ assert(std::numeric_limits<uint32_t>::max() - MAX_START_TIME > interval * max_blocks);
+
+ const int64_t block_start_time = fuzzed_data_provider.ConsumeIntegralInRange<uint32_t>(params.GenesisBlock().nTime, MAX_START_TIME);
+
+ // what values for version will we use to signal / not signal?
+ const int32_t ver_signal = fuzzed_data_provider.ConsumeIntegral<int32_t>();
+ const int32_t ver_nosignal = fuzzed_data_provider.ConsumeIntegral<int32_t>();
+
+ // select deployment parameters: bit, start time, timeout
+ const int bit = fuzzed_data_provider.ConsumeIntegralInRange<int>(0, VERSIONBITS_NUM_BITS - 1);
+
+ bool always_active_test = false;
+ bool never_active_test = false;
+ int64_t start_time;
+ int64_t timeout;
+ if (fuzzed_data_provider.ConsumeBool()) {
+ // pick the timestamp to switch based on a block
+ // note states will change *after* these blocks because mediantime lags
+ int start_block = fuzzed_data_provider.ConsumeIntegralInRange<int>(0, period * (max_periods - 3));
+ int end_block = fuzzed_data_provider.ConsumeIntegralInRange<int>(start_block, period * (max_periods - 3));
+
+ start_time = block_start_time + start_block * interval;
+ timeout = block_start_time + end_block * interval;
+
+ assert(start_time <= timeout);
+
+ // allow for times to not exactly match a block
+ if (fuzzed_data_provider.ConsumeBool()) start_time += interval / 2;
+ if (fuzzed_data_provider.ConsumeBool()) timeout += interval / 2;
+
+ // this may make timeout too early; if so, don't run the test
+ if (start_time > timeout) return;
+ } else {
+ if (fuzzed_data_provider.ConsumeBool()) {
+ start_time = Consensus::BIP9Deployment::ALWAYS_ACTIVE;
+ timeout = Consensus::BIP9Deployment::NO_TIMEOUT;
+ always_active_test = true;
+ } else {
+ start_time = 1199145601; // January 1, 2008
+ timeout = 1230767999; // December 31, 2008
+ never_active_test = true;
+ }
+ }
+
+ TestConditionChecker checker(start_time, timeout, period, threshold, bit);
+
+ // Early exit if the versions don't signal sensibly for the deployment
+ if (!checker.Condition(ver_signal)) return;
+ if (checker.Condition(ver_nosignal)) return;
+ if (ver_nosignal < 0) return;
+
+ // TOP_BITS should ensure version will be positive and meet min
+ // version requirement
+ assert(ver_signal > 0);
+ assert(ver_signal >= VERSIONBITS_LAST_OLD_BLOCK_VERSION);
+
+ // Now that we have chosen time and versions, setup to mine blocks
+ Blocks blocks(block_start_time, interval, ver_signal, ver_nosignal);
+
+ /* Strategy:
+ * * we will mine a final period worth of blocks, with
+ * randomised signalling according to a mask
+ * * but before we mine those blocks, we will mine some
+ * randomised number of prior periods; with either all
+ * or no blocks in the period signalling
+ *
+ * We establish the mask first, then consume "bools" until
+ * we run out of fuzz data to work out how many prior periods
+ * there are and which ones will signal.
+ */
+
+ // establish the mask
+ const uint32_t signalling_mask = fuzzed_data_provider.ConsumeIntegral<uint32_t>();
+
+ // mine prior periods
+ while (fuzzed_data_provider.remaining_bytes() > 0) {
+ // all blocks in these periods either do or don't signal
+ bool signal = fuzzed_data_provider.ConsumeBool();
+ for (int b = 0; b < period; ++b) {
+ blocks.mine_block(signal);
+ }
+
+ // don't risk exceeding max_blocks or times may wrap around
+ if (blocks.size() + 2 * period > max_blocks) break;
+ }
+ // NOTE: fuzzed_data_provider may be fully consumed at this point and should not be used further
+
+ // now we mine the final period and check that everything looks sane
+
+ // count the number of signalling blocks
+ int blocks_sig = 0;
+
+ // get the info for the first block of the period
+ CBlockIndex* prev = blocks.tip();
+ const int exp_since = checker.GetStateSinceHeightFor(prev);
+ const ThresholdState exp_state = checker.GetStateFor(prev);
+ BIP9Stats last_stats = checker.GetStateStatisticsFor(prev);
+
+ int prev_next_height = (prev == nullptr ? 0 : prev->nHeight + 1);
+ assert(exp_since <= prev_next_height);
+
+ // mine (period-1) blocks and check state
+ for (int b = 1; b < period; ++b) {
+ const bool signal = (signalling_mask >> (b % 32)) & 1;
+ if (signal) ++blocks_sig;
+
+ CBlockIndex* current_block = blocks.mine_block(signal);
+
+ // verify that signalling attempt was interpreted correctly
+ assert(checker.Condition(current_block) == signal);
+
+ // state and since don't change within the period
+ const ThresholdState state = checker.GetStateFor(current_block);
+ const int since = checker.GetStateSinceHeightFor(current_block);
+ assert(state == exp_state);
+ assert(since == exp_since);
+
+ // GetStateStatistics may crash when state is not STARTED
+ if (state != ThresholdState::STARTED) continue;
+
+ // check that after mining this block stats change as expected
+ const BIP9Stats stats = checker.GetStateStatisticsFor(current_block);
+ assert(stats.period == period);
+ assert(stats.threshold == threshold);
+ assert(stats.elapsed == b);
+ assert(stats.count == last_stats.count + (signal ? 1 : 0));
+ assert(stats.possible == (stats.count + period >= stats.elapsed + threshold));
+ last_stats = stats;
+ }
+
+ if (exp_state == ThresholdState::STARTED) {
+ // double check that stats.possible is sane
+ if (blocks_sig >= threshold - 1) assert(last_stats.possible);
+ }
+
+ // mine the final block
+ bool signal = (signalling_mask >> (period % 32)) & 1;
+ if (signal) ++blocks_sig;
+ CBlockIndex* current_block = blocks.mine_block(signal);
+ assert(checker.Condition(current_block) == signal);
+
+ // GetStateStatistics is safe on a period boundary
+ // and has progressed to a new period
+ const BIP9Stats stats = checker.GetStateStatisticsFor(current_block);
+ assert(stats.period == period);
+ assert(stats.threshold == threshold);
+ assert(stats.elapsed == 0);
+ assert(stats.count == 0);
+ assert(stats.possible == true);
+
+ // More interesting is whether the state changed.
+ const ThresholdState state = checker.GetStateFor(current_block);
+ const int since = checker.GetStateSinceHeightFor(current_block);
+
+ // since is straightforward:
+ assert(since % period == 0);
+ assert(0 <= since && since <= current_block->nHeight + 1);
+ if (state == exp_state) {
+ assert(since == exp_since);
+ } else {
+ assert(since == current_block->nHeight + 1);
+ }
+
+ // state is where everything interesting is
+ switch (state) {
+ case ThresholdState::DEFINED:
+ assert(since == 0);
+ assert(exp_state == ThresholdState::DEFINED);
+ assert(current_block->GetMedianTimePast() < checker.m_begin);
+ assert(current_block->GetMedianTimePast() < checker.m_end);
+ break;
+ case ThresholdState::STARTED:
+ assert(current_block->GetMedianTimePast() >= checker.m_begin);
+ assert(current_block->GetMedianTimePast() < checker.m_end);
+ if (exp_state == ThresholdState::STARTED) {
+ assert(blocks_sig < threshold);
+ } else {
+ assert(exp_state == ThresholdState::DEFINED);
+ }
+ break;
+ case ThresholdState::LOCKED_IN:
+ assert(exp_state == ThresholdState::STARTED);
+ assert(current_block->GetMedianTimePast() < checker.m_end);
+ assert(blocks_sig >= threshold);
+ break;
+ case ThresholdState::ACTIVE:
+ assert(exp_state == ThresholdState::ACTIVE || exp_state == ThresholdState::LOCKED_IN);
+ break;
+ case ThresholdState::FAILED:
+ assert(current_block->GetMedianTimePast() >= checker.m_end);
+ assert(exp_state != ThresholdState::LOCKED_IN && exp_state != ThresholdState::ACTIVE);
+ break;
+ default:
+ assert(false);
+ }
+
+ if (blocks.size() >= period * max_periods) {
+ // we chose the timeout (and block times) so that by the time we have this many blocks it's all over
+ assert(state == ThresholdState::ACTIVE || state == ThresholdState::FAILED);
+ }
+
+ // "always active" has additional restrictions
+ if (always_active_test) {
+ assert(state == ThresholdState::ACTIVE);
+ assert(exp_state == ThresholdState::ACTIVE);
+ assert(since == 0);
+ } else {
+ // except for always active, the initial state is always DEFINED
+ assert(since > 0 || state == ThresholdState::DEFINED);
+ assert(exp_since > 0 || exp_state == ThresholdState::DEFINED);
+ }
+
+ // "never active" does too
+ if (never_active_test) {
+ assert(state == ThresholdState::FAILED);
+ assert(since == period);
+ if (exp_since == 0) {
+ assert(exp_state == ThresholdState::DEFINED);
+ } else {
+ assert(exp_state == ThresholdState::FAILED);
+ }
+ }
+}
+} // namespace
diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp
index 3b3b71ea2a..8eab26f3d5 100644
--- a/src/test/net_tests.cpp
+++ b/src/test/net_tests.cpp
@@ -8,6 +8,7 @@
#include <clientversion.h>
#include <cstdint>
#include <net.h>
+#include <netaddress.h>
#include <netbase.h>
#include <serialize.h>
#include <span.h>
@@ -91,7 +92,7 @@ BOOST_FIXTURE_TEST_SUITE(net_tests, BasicTestingSetup)
BOOST_AUTO_TEST_CASE(cnode_listen_port)
{
// test default
- uint16_t port = GetListenPort();
+ uint16_t port{GetListenPort()};
BOOST_CHECK(port == Params().GetDefaultPort());
// test set port
uint16_t altPort = 12345;
@@ -395,6 +396,60 @@ BOOST_AUTO_TEST_CASE(cnetaddr_basic)
BOOST_CHECK(!addr.SetSpecial("totally bogus"));
}
+BOOST_AUTO_TEST_CASE(cnetaddr_tostring_canonical_ipv6)
+{
+ // Test that CNetAddr::ToString formats IPv6 addresses with zero compression as described in
+ // RFC 5952 ("A Recommendation for IPv6 Address Text Representation").
+ const std::map<std::string, std::string> canonical_representations_ipv6{
+ {"0000:0000:0000:0000:0000:0000:0000:0000", "::"},
+ {"000:0000:000:00:0:00:000:0000", "::"},
+ {"000:000:000:000:000:000:000:000", "::"},
+ {"00:00:00:00:00:00:00:00", "::"},
+ {"0:0:0:0:0:0:0:0", "::"},
+ {"0:0:0:0:0:0:0:1", "::1"},
+ {"2001:0:0:1:0:0:0:1", "2001:0:0:1::1"},
+ {"2001:0db8:0:0:1:0:0:1", "2001:db8::1:0:0:1"},
+ {"2001:0db8:85a3:0000:0000:8a2e:0370:7334", "2001:db8:85a3::8a2e:370:7334"},
+ {"2001:0db8::0001", "2001:db8::1"},
+ {"2001:0db8::0001:0000", "2001:db8::1:0"},
+ {"2001:0db8::1:0:0:1", "2001:db8::1:0:0:1"},
+ {"2001:db8:0000:0:1::1", "2001:db8::1:0:0:1"},
+ {"2001:db8:0000:1:1:1:1:1", "2001:db8:0:1:1:1:1:1"},
+ {"2001:db8:0:0:0:0:2:1", "2001:db8::2:1"},
+ {"2001:db8:0:0:0::1", "2001:db8::1"},
+ {"2001:db8:0:0:1:0:0:1", "2001:db8::1:0:0:1"},
+ {"2001:db8:0:0:1::1", "2001:db8::1:0:0:1"},
+ {"2001:DB8:0:0:1::1", "2001:db8::1:0:0:1"},
+ {"2001:db8:0:0::1", "2001:db8::1"},
+ {"2001:db8:0:0:aaaa::1", "2001:db8::aaaa:0:0:1"},
+ {"2001:db8:0:1:1:1:1:1", "2001:db8:0:1:1:1:1:1"},
+ {"2001:db8:0::1", "2001:db8::1"},
+ {"2001:db8:85a3:0:0:8a2e:370:7334", "2001:db8:85a3::8a2e:370:7334"},
+ {"2001:db8::0:1", "2001:db8::1"},
+ {"2001:db8::0:1:0:0:1", "2001:db8::1:0:0:1"},
+ {"2001:DB8::1", "2001:db8::1"},
+ {"2001:db8::1", "2001:db8::1"},
+ {"2001:db8::1:0:0:1", "2001:db8::1:0:0:1"},
+ {"2001:db8::1:1:1:1:1", "2001:db8:0:1:1:1:1:1"},
+ {"2001:db8::aaaa:0:0:1", "2001:db8::aaaa:0:0:1"},
+ {"2001:db8:aaaa:bbbb:cccc:dddd:0:1", "2001:db8:aaaa:bbbb:cccc:dddd:0:1"},
+ {"2001:db8:aaaa:bbbb:cccc:dddd::1", "2001:db8:aaaa:bbbb:cccc:dddd:0:1"},
+ {"2001:db8:aaaa:bbbb:cccc:dddd:eeee:0001", "2001:db8:aaaa:bbbb:cccc:dddd:eeee:1"},
+ {"2001:db8:aaaa:bbbb:cccc:dddd:eeee:001", "2001:db8:aaaa:bbbb:cccc:dddd:eeee:1"},
+ {"2001:db8:aaaa:bbbb:cccc:dddd:eeee:01", "2001:db8:aaaa:bbbb:cccc:dddd:eeee:1"},
+ {"2001:db8:aaaa:bbbb:cccc:dddd:eeee:1", "2001:db8:aaaa:bbbb:cccc:dddd:eeee:1"},
+ {"2001:db8:aaaa:bbbb:cccc:dddd:eeee:aaaa", "2001:db8:aaaa:bbbb:cccc:dddd:eeee:aaaa"},
+ {"2001:db8:aaaa:bbbb:cccc:dddd:eeee:AAAA", "2001:db8:aaaa:bbbb:cccc:dddd:eeee:aaaa"},
+ {"2001:db8:aaaa:bbbb:cccc:dddd:eeee:AaAa", "2001:db8:aaaa:bbbb:cccc:dddd:eeee:aaaa"},
+ };
+ for (const auto& [input_address, expected_canonical_representation_output] : canonical_representations_ipv6) {
+ CNetAddr net_addr;
+ BOOST_REQUIRE(LookupHost(input_address, net_addr, false));
+ BOOST_REQUIRE(net_addr.IsIPv6());
+ BOOST_CHECK_EQUAL(net_addr.ToString(), expected_canonical_representation_output);
+ }
+}
+
BOOST_AUTO_TEST_CASE(cnetaddr_serialize_v1)
{
CNetAddr addr;
diff --git a/src/test/netbase_tests.cpp b/src/test/netbase_tests.cpp
index 66ad7bb5ea..33b56624a8 100644
--- a/src/test/netbase_tests.cpp
+++ b/src/test/netbase_tests.cpp
@@ -3,6 +3,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <net_permissions.h>
+#include <netaddress.h>
#include <netbase.h>
#include <protocol.h>
#include <serialize.h>
@@ -83,31 +84,31 @@ BOOST_AUTO_TEST_CASE(netbase_properties)
}
-bool static TestSplitHost(std::string test, std::string host, int port)
+bool static TestSplitHost(const std::string& test, const std::string& host, uint16_t port)
{
std::string hostOut;
- int portOut = -1;
+ uint16_t portOut{0};
SplitHostPort(test, portOut, hostOut);
return hostOut == host && port == portOut;
}
BOOST_AUTO_TEST_CASE(netbase_splithost)
{
- BOOST_CHECK(TestSplitHost("www.bitcoincore.org", "www.bitcoincore.org", -1));
- BOOST_CHECK(TestSplitHost("[www.bitcoincore.org]", "www.bitcoincore.org", -1));
+ BOOST_CHECK(TestSplitHost("www.bitcoincore.org", "www.bitcoincore.org", 0));
+ BOOST_CHECK(TestSplitHost("[www.bitcoincore.org]", "www.bitcoincore.org", 0));
BOOST_CHECK(TestSplitHost("www.bitcoincore.org:80", "www.bitcoincore.org", 80));
BOOST_CHECK(TestSplitHost("[www.bitcoincore.org]:80", "www.bitcoincore.org", 80));
- BOOST_CHECK(TestSplitHost("127.0.0.1", "127.0.0.1", -1));
+ BOOST_CHECK(TestSplitHost("127.0.0.1", "127.0.0.1", 0));
BOOST_CHECK(TestSplitHost("127.0.0.1:8333", "127.0.0.1", 8333));
- BOOST_CHECK(TestSplitHost("[127.0.0.1]", "127.0.0.1", -1));
+ BOOST_CHECK(TestSplitHost("[127.0.0.1]", "127.0.0.1", 0));
BOOST_CHECK(TestSplitHost("[127.0.0.1]:8333", "127.0.0.1", 8333));
- BOOST_CHECK(TestSplitHost("::ffff:127.0.0.1", "::ffff:127.0.0.1", -1));
+ BOOST_CHECK(TestSplitHost("::ffff:127.0.0.1", "::ffff:127.0.0.1", 0));
BOOST_CHECK(TestSplitHost("[::ffff:127.0.0.1]:8333", "::ffff:127.0.0.1", 8333));
BOOST_CHECK(TestSplitHost("[::]:8333", "::", 8333));
- BOOST_CHECK(TestSplitHost("::8333", "::8333", -1));
+ BOOST_CHECK(TestSplitHost("::8333", "::8333", 0));
BOOST_CHECK(TestSplitHost(":8333", "", 8333));
BOOST_CHECK(TestSplitHost("[]:8333", "", 8333));
- BOOST_CHECK(TestSplitHost("", "", -1));
+ BOOST_CHECK(TestSplitHost("", "", 0));
}
bool static TestParse(std::string src, std::string canon)
diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp
index f866c2a1f9..bfb3466dcf 100644
--- a/src/test/util/setup_common.cpp
+++ b/src/test/util/setup_common.cpp
@@ -4,6 +4,7 @@
#include <test/util/setup_common.h>
+#include <addrman.h>
#include <banman.h>
#include <chainparams.h>
#include <consensus/consensus.h>
@@ -155,6 +156,7 @@ ChainTestingSetup::~ChainTestingSetup()
GetMainSignals().UnregisterBackgroundSignalScheduler();
m_node.connman.reset();
m_node.banman.reset();
+ m_node.addrman.reset();
m_node.args = nullptr;
UnloadBlockIndex(m_node.mempool.get(), *m_node.chainman);
m_node.mempool.reset();
@@ -187,11 +189,12 @@ TestingSetup::TestingSetup(const std::string& chainName, const std::vector<const
throw std::runtime_error(strprintf("ActivateBestChain failed. (%s)", state.ToString()));
}
+ m_node.addrman = std::make_unique<CAddrMan>();
m_node.banman = std::make_unique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
- m_node.connman = std::make_unique<CConnman>(0x1337, 0x1337); // Deterministic randomness for tests.
- m_node.peerman = PeerManager::make(chainparams, *m_node.connman, m_node.banman.get(),
- *m_node.scheduler, *m_node.chainman, *m_node.mempool,
- false);
+ m_node.connman = std::make_unique<CConnman>(0x1337, 0x1337, *m_node.addrman); // Deterministic randomness for tests.
+ m_node.peerman = PeerManager::make(chainparams, *m_node.connman, *m_node.addrman,
+ m_node.banman.get(), *m_node.scheduler, *m_node.chainman,
+ *m_node.mempool, false);
{
CConnman::Options options;
options.m_msgproc = m_node.peerman.get();
diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp
index 98a322eae5..5ac09b05db 100644
--- a/src/test/util_tests.cpp
+++ b/src/test/util_tests.cpp
@@ -77,6 +77,9 @@ BOOST_AUTO_TEST_CASE(util_check)
const int two = *Assert(p_two);
Assert(two == 2);
Assert(true);
+ // Check that Assume can be used as unary expression
+ const bool result{Assume(two == 2)};
+ Assert(result);
}
BOOST_AUTO_TEST_CASE(util_criticalsection)
@@ -1450,7 +1453,6 @@ BOOST_AUTO_TEST_CASE(test_ParseInt32)
BOOST_CHECK(!ParseInt32("1a", &n));
BOOST_CHECK(!ParseInt32("aap", &n));
BOOST_CHECK(!ParseInt32("0x1", &n)); // no hex
- BOOST_CHECK(!ParseInt32("0x1", &n)); // no hex
BOOST_CHECK(!ParseInt32(STRING_WITH_EMBEDDED_NULL_CHAR, &n));
// Overflow and underflow
BOOST_CHECK(!ParseInt32("-2147483649", nullptr));
@@ -1513,7 +1515,6 @@ BOOST_AUTO_TEST_CASE(test_ParseUInt8)
BOOST_CHECK(!ParseUInt8("1a", &n));
BOOST_CHECK(!ParseUInt8("aap", &n));
BOOST_CHECK(!ParseUInt8("0x1", &n)); // no hex
- BOOST_CHECK(!ParseUInt8("0x1", &n)); // no hex
BOOST_CHECK(!ParseUInt8(STRING_WITH_EMBEDDED_NULL_CHAR, &n));
// Overflow and underflow
BOOST_CHECK(!ParseUInt8("-255", &n));
@@ -1523,6 +1524,41 @@ BOOST_AUTO_TEST_CASE(test_ParseUInt8)
BOOST_CHECK(!ParseUInt8("256", nullptr));
}
+BOOST_AUTO_TEST_CASE(test_ParseUInt16)
+{
+ uint16_t n;
+ // Valid values
+ BOOST_CHECK(ParseUInt16("1234", nullptr));
+ BOOST_CHECK(ParseUInt16("0", &n) && n == 0);
+ BOOST_CHECK(ParseUInt16("1234", &n) && n == 1234);
+ BOOST_CHECK(ParseUInt16("01234", &n) && n == 1234); // no octal
+ BOOST_CHECK(ParseUInt16("65535", &n) && n == static_cast<uint16_t>(65535));
+ BOOST_CHECK(ParseUInt16("+65535", &n) && n == 65535);
+ BOOST_CHECK(ParseUInt16("00000000000000000012", &n) && n == 12);
+ BOOST_CHECK(ParseUInt16("00000000000000000000", &n) && n == 0);
+ // Invalid values
+ BOOST_CHECK(!ParseUInt16("-00000000000000000000", &n));
+ BOOST_CHECK(!ParseUInt16("", &n));
+ BOOST_CHECK(!ParseUInt16(" 1", &n)); // no padding inside
+ BOOST_CHECK(!ParseUInt16(" -1", &n));
+ BOOST_CHECK(!ParseUInt16("++1", &n));
+ BOOST_CHECK(!ParseUInt16("+-1", &n));
+ BOOST_CHECK(!ParseUInt16("-+1", &n));
+ BOOST_CHECK(!ParseUInt16("--1", &n));
+ BOOST_CHECK(!ParseUInt16("-1", &n));
+ BOOST_CHECK(!ParseUInt16("1 ", &n));
+ BOOST_CHECK(!ParseUInt16("1a", &n));
+ BOOST_CHECK(!ParseUInt16("aap", &n));
+ BOOST_CHECK(!ParseUInt16("0x1", &n)); // no hex
+ BOOST_CHECK(!ParseUInt16(STRING_WITH_EMBEDDED_NULL_CHAR, &n));
+ // Overflow and underflow
+ BOOST_CHECK(!ParseUInt16("-65535", &n));
+ BOOST_CHECK(!ParseUInt16("65536", &n));
+ BOOST_CHECK(!ParseUInt16("-123", &n));
+ BOOST_CHECK(!ParseUInt16("-123", nullptr));
+ BOOST_CHECK(!ParseUInt16("65536", nullptr));
+}
+
BOOST_AUTO_TEST_CASE(test_ParseUInt32)
{
uint32_t n;
@@ -1551,7 +1587,6 @@ BOOST_AUTO_TEST_CASE(test_ParseUInt32)
BOOST_CHECK(!ParseUInt32("1a", &n));
BOOST_CHECK(!ParseUInt32("aap", &n));
BOOST_CHECK(!ParseUInt32("0x1", &n)); // no hex
- BOOST_CHECK(!ParseUInt32("0x1", &n)); // no hex
BOOST_CHECK(!ParseUInt32(STRING_WITH_EMBEDDED_NULL_CHAR, &n));
// Overflow and underflow
BOOST_CHECK(!ParseUInt32("-2147483648", &n));
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index faccd1ade0..67549fc13d 100644
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -895,7 +895,7 @@ std::optional<CTxMemPool::txiter> CTxMemPool::GetIter(const uint256& txid) const
{
auto it = mapTx.find(txid);
if (it != mapTx.end()) return it;
- return {};
+ return std::nullopt;
}
CTxMemPool::setEntries CTxMemPool::GetIterSet(const std::set<uint256>& hashes) const
diff --git a/src/txmempool.h b/src/txmempool.h
index 9d4ea760e7..c3a9bd851d 100644
--- a/src/txmempool.h
+++ b/src/txmempool.h
@@ -476,7 +476,7 @@ enum class MemPoolRemovalReason {
*/
class CTxMemPool
{
-private:
+protected:
const int m_check_ratio; //!< Value n means that 1 times in n we check.
std::atomic<unsigned int> nTransactionsUpdated{0}; //!< Used by getblocktemplate to trigger CreateNewBlock() invocation
CBlockPolicyEstimator* minerPolicyEstimator;
diff --git a/src/util/check.h b/src/util/check.h
index bc62da3440..e60088a2c6 100644
--- a/src/util/check.h
+++ b/src/util/check.h
@@ -69,7 +69,7 @@ T get_pure_r_value(T&& val)
#ifdef ABORT_ON_FAILED_ASSUME
#define Assume(val) Assert(val)
#else
-#define Assume(val) ((void)(val))
+#define Assume(val) ([&]() -> decltype(get_pure_r_value(val)) { auto&& check = (val); return std::forward<decltype(get_pure_r_value(val))>(check); }())
#endif
#endif // BITCOIN_UTIL_CHECK_H
diff --git a/src/util/strencodings.cpp b/src/util/strencodings.cpp
index f3d54a2ac9..4734de3e0b 100644
--- a/src/util/strencodings.cpp
+++ b/src/util/strencodings.cpp
@@ -107,23 +107,25 @@ std::vector<unsigned char> ParseHex(const std::string& str)
return ParseHex(str.c_str());
}
-void SplitHostPort(std::string in, int &portOut, std::string &hostOut) {
+void SplitHostPort(std::string in, uint16_t& portOut, std::string& hostOut)
+{
size_t colon = in.find_last_of(':');
// if a : is found, and it either follows a [...], or no other : is in the string, treat it as port separator
bool fHaveColon = colon != in.npos;
- bool fBracketed = fHaveColon && (in[0]=='[' && in[colon-1]==']'); // if there is a colon, and in[0]=='[', colon is not 0, so in[colon-1] is safe
- bool fMultiColon = fHaveColon && (in.find_last_of(':',colon-1) != in.npos);
- if (fHaveColon && (colon==0 || fBracketed || !fMultiColon)) {
- int32_t n;
- if (ParseInt32(in.substr(colon + 1), &n) && n > 0 && n < 0x10000) {
+ bool fBracketed = fHaveColon && (in[0] == '[' && in[colon - 1] == ']'); // if there is a colon, and in[0]=='[', colon is not 0, so in[colon-1] is safe
+ bool fMultiColon = fHaveColon && (in.find_last_of(':', colon - 1) != in.npos);
+ if (fHaveColon && (colon == 0 || fBracketed || !fMultiColon)) {
+ uint16_t n;
+ if (ParseUInt16(in.substr(colon + 1), &n)) {
in = in.substr(0, colon);
portOut = n;
}
}
- if (in.size()>0 && in[0] == '[' && in[in.size()-1] == ']')
- hostOut = in.substr(1, in.size()-2);
- else
+ if (in.size() > 0 && in[0] == '[' && in[in.size() - 1] == ']') {
+ hostOut = in.substr(1, in.size() - 2);
+ } else {
hostOut = in;
+ }
}
std::string EncodeBase64(Span<const unsigned char> input)
@@ -334,6 +336,18 @@ bool ParseUInt8(const std::string& str, uint8_t *out)
return true;
}
+bool ParseUInt16(const std::string& str, uint16_t* out)
+{
+ uint32_t u32;
+ if (!ParseUInt32(str, &u32) || u32 > std::numeric_limits<uint16_t>::max()) {
+ return false;
+ }
+ if (out != nullptr) {
+ *out = static_cast<uint16_t>(u32);
+ }
+ return true;
+}
+
bool ParseUInt32(const std::string& str, uint32_t *out)
{
if (!ParsePrechecks(str))
diff --git a/src/util/strencodings.h b/src/util/strencodings.h
index 98379e9138..26dc0a0ce3 100644
--- a/src/util/strencodings.h
+++ b/src/util/strencodings.h
@@ -65,7 +65,7 @@ std::string EncodeBase32(Span<const unsigned char> input, bool pad = true);
*/
std::string EncodeBase32(const std::string& str, bool pad = true);
-void SplitHostPort(std::string in, int& portOut, std::string& hostOut);
+void SplitHostPort(std::string in, uint16_t& portOut, std::string& hostOut);
int64_t atoi64(const std::string& str);
int atoi(const std::string& str);
@@ -116,6 +116,13 @@ constexpr inline bool IsSpace(char c) noexcept {
[[nodiscard]] bool ParseUInt8(const std::string& str, uint8_t *out);
/**
+ * Convert decimal string to unsigned 16-bit integer with strict parse error feedback.
+ * @returns true if the entire string could be parsed as valid integer,
+ * false if the entire string could not be parsed or if overflow or underflow occurred.
+ */
+[[nodiscard]] bool ParseUInt16(const std::string& str, uint16_t* out);
+
+/**
* Convert decimal string to unsigned 32-bit integer with strict parse error feedback.
* @returns true if the entire string could be parsed as valid integer,
* false if not the entire string could be parsed or when overflow or underflow occurred.
diff --git a/src/validation.cpp b/src/validation.cpp
index 74df13f462..d1b9efe7ba 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -2974,6 +2974,10 @@ bool CChainState::PreciousBlock(BlockValidationState& state, const CChainParams&
bool CChainState::InvalidateBlock(BlockValidationState& state, const CChainParams& chainparams, CBlockIndex *pindex)
{
+ // Genesis block can't be invalidated
+ assert(pindex);
+ if (pindex->nHeight == 0) return false;
+
CBlockIndex* to_mark_failed = pindex;
bool pindex_was_in_chain = false;
int disconnected = 0;
@@ -5182,7 +5186,7 @@ std::optional<uint256> ChainstateManager::SnapshotBlockhash() const {
// If a snapshot chainstate exists, it will always be our active.
return m_active_chainstate->m_from_snapshot_blockhash;
}
- return {};
+ return std::nullopt;
}
std::vector<CChainState*> ChainstateManager::GetAll()
diff --git a/src/wallet/load.cpp b/src/wallet/load.cpp
index 4543f6fb4c..6a59bc2b38 100644
--- a/src/wallet/load.cpp
+++ b/src/wallet/load.cpp
@@ -76,7 +76,7 @@ bool VerifyWallets(interfaces::Chain& chain)
bilingual_str error_string;
if (!MakeWalletDatabase(wallet_file, options, status, error_string)) {
if (status == DatabaseStatus::FAILED_NOT_FOUND) {
- chain.initWarning(Untranslated(strprintf("Skipping -wallet path that doesn't exist. %s\n", error_string.original)));
+ chain.initWarning(Untranslated(strprintf("Skipping -wallet path that doesn't exist. %s", error_string.original)));
} else {
chain.initError(error_string);
return false;
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index 6dc8d1de42..e70bbafde0 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -1741,7 +1741,7 @@ static RPCHelpMan gettransaction()
if (verbose) {
UniValue decoded(UniValue::VOBJ);
- TxToUniv(*wtx.tx, uint256(), decoded, false);
+ TxToUniv(*wtx.tx, uint256(), pwallet->chain().rpcEnableDeprecated("addresses"), decoded, false);
entry.pushKV("decoded", decoded);
}
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index d04279ab5e..b00fa851fd 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -238,7 +238,7 @@ std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const std::string&
{
auto result = WITH_LOCK(g_loading_wallet_mutex, return g_loading_wallet_set.insert(name));
if (!result.second) {
- error = Untranslated("Wallet already being loading.");
+ error = Untranslated("Wallet already loading.");
status = DatabaseStatus::FAILED_LOAD;
return nullptr;
}
diff --git a/test/functional/feature_anchors.py b/test/functional/feature_anchors.py
new file mode 100755
index 0000000000..a60a723b3e
--- /dev/null
+++ b/test/functional/feature_anchors.py
@@ -0,0 +1,85 @@
+#!/usr/bin/env python3
+# Copyright (c) 2020 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 Anchors functionality"""
+
+import os
+
+from test_framework.p2p import P2PInterface
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import assert_equal
+
+
+def check_node_connections(*, node, num_in, num_out):
+ info = node.getnetworkinfo()
+ assert_equal(info["connections_in"], num_in)
+ assert_equal(info["connections_out"], num_out)
+
+
+class AnchorsTest(BitcoinTestFramework):
+ def set_test_params(self):
+ self.num_nodes = 1
+
+ def setup_network(self):
+ self.setup_nodes()
+
+ def run_test(self):
+ self.log.info("Add 2 block-relay-only connections to node 0")
+ for i in range(2):
+ self.log.debug(f"block-relay-only: {i}")
+ self.nodes[0].add_outbound_p2p_connection(
+ P2PInterface(), p2p_idx=i, connection_type="block-relay-only"
+ )
+
+ self.log.info("Add 5 inbound connections to node 0")
+ for i in range(5):
+ self.log.debug(f"inbound: {i}")
+ self.nodes[0].add_p2p_connection(P2PInterface())
+
+ self.log.info("Check node 0 connections")
+ check_node_connections(node=self.nodes[0], num_in=5, num_out=2)
+
+ # 127.0.0.1
+ ip = "7f000001"
+
+ # Since the ip is always 127.0.0.1 for this case,
+ # we store only the port to identify the peers
+ block_relay_nodes_port = []
+ inbound_nodes_port = []
+ for p in self.nodes[0].getpeerinfo():
+ addr_split = p["addr"].split(":")
+ if p["connection_type"] == "block-relay-only":
+ block_relay_nodes_port.append(hex(int(addr_split[1]))[2:])
+ else:
+ inbound_nodes_port.append(hex(int(addr_split[1]))[2:])
+
+ self.log.info("Stop node 0")
+ self.stop_node(0)
+
+ node0_anchors_path = os.path.join(
+ self.nodes[0].datadir, "regtest", "anchors.dat"
+ )
+
+ # It should contain only the block-relay-only addresses
+ self.log.info("Check the addresses in anchors.dat")
+
+ with open(node0_anchors_path, "rb") as file_handler:
+ anchors = file_handler.read().hex()
+
+ for port in block_relay_nodes_port:
+ ip_port = ip + port
+ assert ip_port in anchors
+ for port in inbound_nodes_port:
+ ip_port = ip + port
+ assert ip_port not in anchors
+
+ self.log.info("Start node 0")
+ self.start_node(0)
+
+ self.log.info("When node starts, check if anchors.dat doesn't exist anymore")
+ assert not os.path.exists(node0_anchors_path)
+
+
+if __name__ == "__main__":
+ AnchorsTest().main()
diff --git a/test/functional/feature_rbf.py b/test/functional/feature_rbf.py
index c6f55c62b4..945880cc3b 100755
--- a/test/functional/feature_rbf.py
+++ b/test/functional/feature_rbf.py
@@ -33,12 +33,7 @@ def make_utxo(node, amount, confirmed=True, scriptPubKey=DUMMY_P2WPKH_SCRIPT):
txid = node.sendtoaddress(new_addr, satoshi_round((amount+fee)/COIN))
tx1 = node.getrawtransaction(txid, 1)
txid = int(txid, 16)
- i = None
-
- for i, txout in enumerate(tx1['vout']):
- if txout['scriptPubKey']['addresses'] == [new_addr]:
- break
- assert i is not None
+ i, _ = next(filter(lambda vout: new_addr == vout[1]['scriptPubKey']['address'], enumerate(tx1['vout'])))
tx2 = CTransaction()
tx2.vin = [CTxIn(COutPoint(txid, i))]
diff --git a/test/functional/feature_segwit.py b/test/functional/feature_segwit.py
index 7bd2fc7847..ad8767556b 100755
--- a/test/functional/feature_segwit.py
+++ b/test/functional/feature_segwit.py
@@ -523,7 +523,7 @@ class SegWitTest(BitcoinTestFramework):
v1_addr = program_to_witness(1, [3, 5])
v1_tx = self.nodes[0].createrawtransaction([getutxo(spendable_txid[0])], {v1_addr: 1})
v1_decoded = self.nodes[1].decoderawtransaction(v1_tx)
- assert_equal(v1_decoded['vout'][0]['scriptPubKey']['addresses'][0], v1_addr)
+ assert_equal(v1_decoded['vout'][0]['scriptPubKey']['address'], v1_addr)
assert_equal(v1_decoded['vout'][0]['scriptPubKey']['hex'], "51020305")
# Check that spendable outputs are really spendable
diff --git a/test/functional/feature_utxo_set_hash.py b/test/functional/feature_utxo_set_hash.py
index 6e6046d84d..ce00faffee 100755
--- a/test/functional/feature_utxo_set_hash.py
+++ b/test/functional/feature_utxo_set_hash.py
@@ -6,7 +6,6 @@
import struct
-from test_framework.blocktools import create_transaction
from test_framework.messages import (
CBlock,
COutPoint,
@@ -15,38 +14,30 @@ from test_framework.messages import (
from test_framework.muhash import MuHash3072
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal
+from test_framework.wallet import MiniWallet
class UTXOSetHashTest(BitcoinTestFramework):
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_wallet()
-
- def test_deterministic_hash_results(self):
- self.log.info("Test deterministic UTXO set hash results")
-
- # These depend on the setup_clean_chain option, the chain loaded from the cache
- assert_equal(self.nodes[0].gettxoutsetinfo()['hash_serialized_2'], "b32ec1dda5a53cd025b95387aad344a801825fe46a60ff952ce26528f01d3be8")
- assert_equal(self.nodes[0].gettxoutsetinfo("muhash")['muhash'], "dd5ad2a105c2d29495f577245c357409002329b9f4d6182c0af3dc2f462555c8")
-
def test_muhash_implementation(self):
self.log.info("Test MuHash implementation consistency")
node = self.nodes[0]
+ wallet = MiniWallet(node)
+ mocktime = node.getblockheader(node.getblockhash(0))['time'] + 1
+ node.setmocktime(mocktime)
# Generate 100 blocks and remove the first since we plan to spend its
# coinbase
- block_hashes = node.generate(100)
+ block_hashes = wallet.generate(1) + node.generate(99)
blocks = list(map(lambda block: FromHex(CBlock(), node.getblock(block, False)), block_hashes))
- spending = blocks.pop(0)
+ blocks.pop(0)
# Create a spending transaction and mine a block which includes it
- tx = create_transaction(node, spending.vtx[0].rehash(), node.getnewaddress(), amount=49)
- txid = node.sendrawtransaction(hexstring=tx.serialize_with_witness().hex(), maxfeerate=0)
-
- tx_block = node.generateblock(output=node.getnewaddress(), transactions=[txid])
+ txid = wallet.send_self_transfer(from_node=node)['txid']
+ tx_block = node.generateblock(output=wallet.get_address(), transactions=[txid])
blocks.append(FromHex(CBlock(), node.getblock(tx_block['hash'], False)))
# Serialize the outputs that should be in the UTXO set and add them to
@@ -77,8 +68,11 @@ class UTXOSetHashTest(BitcoinTestFramework):
assert_equal(finalized[::-1].hex(), node_muhash)
+ self.log.info("Test deterministic UTXO set hash results")
+ assert_equal(node.gettxoutsetinfo()['hash_serialized_2'], "5b1b44097406226c0eb8e1362cd17a1f346522cf9390a8175a57a5262cb1963f")
+ assert_equal(node.gettxoutsetinfo("muhash")['muhash'], "4b8803075d7151d06fad3e88b68ba726886794873fbfa841d12aefb2cc2b881b")
+
def run_test(self):
- self.test_deterministic_hash_results()
self.test_muhash_implementation()
diff --git a/test/functional/interface_rpc.py b/test/functional/interface_rpc.py
index 9c877aaeae..4d5666f414 100755
--- a/test/functional/interface_rpc.py
+++ b/test/functional/interface_rpc.py
@@ -8,6 +8,9 @@ import os
from test_framework.authproxy import JSONRPCException
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal, assert_greater_than_or_equal
+from threading import Thread
+import subprocess
+
def expect_http_status(expected_http_status, expected_rpc_code,
fcn, *args):
@@ -18,6 +21,16 @@ def expect_http_status(expected_http_status, expected_rpc_code,
assert_equal(exc.error["code"], expected_rpc_code)
assert_equal(exc.http_status, expected_http_status)
+
+def test_work_queue_getblock(node, got_exceeded_error):
+ while not got_exceeded_error:
+ try:
+ node.cli('getrpcinfo').send_cli()
+ except subprocess.CalledProcessError as e:
+ assert_equal(e.output, 'error: Server response: Work queue depth exceeded\n')
+ got_exceeded_error.append(True)
+
+
class RPCInterfaceTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 1
@@ -67,10 +80,23 @@ class RPCInterfaceTest(BitcoinTestFramework):
expect_http_status(404, -32601, self.nodes[0].invalidmethod)
expect_http_status(500, -8, self.nodes[0].getblockhash, 42)
+ def test_work_queue_exceeded(self):
+ self.log.info("Testing work queue exceeded...")
+ self.restart_node(0, ['-rpcworkqueue=1', '-rpcthreads=1'])
+ got_exceeded_error = []
+ threads = []
+ for _ in range(3):
+ t = Thread(target=test_work_queue_getblock, args=(self.nodes[0], got_exceeded_error))
+ t.start()
+ threads.append(t)
+ for t in threads:
+ t.join()
+
def run_test(self):
self.test_getrpcinfo()
self.test_batch_request()
self.test_http_status_codes()
+ self.test_work_queue_exceeded()
if __name__ == '__main__':
diff --git a/test/functional/mempool_package_onemore.py b/test/functional/mempool_package_onemore.py
index a9e2b000fb..884a2fef11 100755
--- a/test/functional/mempool_package_onemore.py
+++ b/test/functional/mempool_package_onemore.py
@@ -80,7 +80,7 @@ class MempoolPackagesTest(BitcoinTestFramework):
self.chain_transaction(self.nodes[0], [second_chain], [0], second_chain_value, fee, 1)
# Make sure we can RBF the chain which used our carve-out rule
- second_tx_outputs = {self.nodes[0].getrawtransaction(replacable_txid, True)["vout"][0]['scriptPubKey']['addresses'][0]: replacable_orig_value - (Decimal(1) / Decimal(100))}
+ second_tx_outputs = {self.nodes[0].getrawtransaction(replacable_txid, True)["vout"][0]['scriptPubKey']['address']: replacable_orig_value - (Decimal(1) / Decimal(100))}
second_tx = self.nodes[0].createrawtransaction([{'txid': chain[0][0], 'vout': 1}], second_tx_outputs)
signed_second_tx = self.nodes[0].signrawtransactionwithwallet(second_tx)
self.nodes[0].sendrawtransaction(signed_second_tx['hex'])
diff --git a/test/functional/p2p_feefilter.py b/test/functional/p2p_feefilter.py
index a2a122b352..52dc4de3bd 100755
--- a/test/functional/p2p_feefilter.py
+++ b/test/functional/p2p_feefilter.py
@@ -61,6 +61,7 @@ class FeeFilterTest(BitcoinTestFramework):
def run_test(self):
self.test_feefilter_forcerelay()
self.test_feefilter()
+ self.test_feefilter_blocksonly()
def test_feefilter_forcerelay(self):
self.log.info('Check that peers without forcerelay permission (default) get a feefilter message')
@@ -119,6 +120,19 @@ class FeeFilterTest(BitcoinTestFramework):
conn.wait_for_invs_to_match(txids)
conn.clear_invs()
+ def test_feefilter_blocksonly(self):
+ """Test that we don't send fee filters to block-relay-only peers and when we're in blocksonly mode."""
+ self.log.info("Check that we don't send fee filters to block-relay-only peers.")
+ feefilter_peer = self.nodes[0].add_outbound_p2p_connection(FeefilterConn(), p2p_idx=0, connection_type="block-relay-only")
+ feefilter_peer.sync_with_ping()
+ feefilter_peer.assert_feefilter_received(False)
+
+ self.log.info("Check that we don't send fee filters when in blocksonly mode.")
+ self.restart_node(0, ["-blocksonly"])
+ feefilter_peer = self.nodes[0].add_p2p_connection(FeefilterConn())
+ feefilter_peer.sync_with_ping()
+ feefilter_peer.assert_feefilter_received(False)
+
if __name__ == '__main__':
FeeFilterTest().main()
diff --git a/test/functional/p2p_filter.py b/test/functional/p2p_filter.py
index 8f64419138..4bee33f825 100755
--- a/test/functional/p2p_filter.py
+++ b/test/functional/p2p_filter.py
@@ -130,7 +130,7 @@ class FilterTest(BitcoinTestFramework):
filter_peer = P2PBloomFilter()
self.log.debug("Create a tx relevant to the peer before connecting")
- filter_address = self.nodes[0].decodescript(filter_peer.watch_script_pubkey)['addresses'][0]
+ filter_address = self.nodes[0].decodescript(filter_peer.watch_script_pubkey)['address']
txid = self.nodes[0].sendtoaddress(filter_address, 90)
self.log.debug("Send a mempool msg after connecting and check that the tx is received")
@@ -142,7 +142,7 @@ class FilterTest(BitcoinTestFramework):
def test_frelay_false(self, filter_peer):
self.log.info("Check that a node with fRelay set to false does not receive invs until the filter is set")
filter_peer.tx_received = False
- filter_address = self.nodes[0].decodescript(filter_peer.watch_script_pubkey)['addresses'][0]
+ filter_address = self.nodes[0].decodescript(filter_peer.watch_script_pubkey)['address']
self.nodes[0].sendtoaddress(filter_address, 90)
# Sync to make sure the reason filter_peer doesn't receive the tx is not p2p delays
filter_peer.sync_with_ping()
@@ -156,7 +156,7 @@ class FilterTest(BitcoinTestFramework):
filter_peer.send_and_ping(filter_peer.watch_filter_init)
# If fRelay is not already True, sending filterload sets it to True
assert self.nodes[0].getpeerinfo()[0]['relaytxes']
- filter_address = self.nodes[0].decodescript(filter_peer.watch_script_pubkey)['addresses'][0]
+ filter_address = self.nodes[0].decodescript(filter_peer.watch_script_pubkey)['address']
self.log.info('Check that we receive merkleblock and tx if the filter matches a tx in a block')
block_hash = self.nodes[0].generatetoaddress(1, filter_address)[0]
diff --git a/test/functional/rpc_addresses_deprecation.py b/test/functional/rpc_addresses_deprecation.py
new file mode 100644
index 0000000000..bc0559f3b5
--- /dev/null
+++ b/test/functional/rpc_addresses_deprecation.py
@@ -0,0 +1,58 @@
+#!/usr/bin/env python3
+# Copyright (c) 2020 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 deprecation of reqSigs and addresses RPC fields."""
+
+from io import BytesIO
+
+from test_framework.messages import CTransaction
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import (
+ assert_equal,
+ hex_str_to_bytes
+)
+
+
+class AddressesDeprecationTest(BitcoinTestFramework):
+ def set_test_params(self):
+ self.num_nodes = 2
+ self.extra_args = [[], ["-deprecatedrpc=addresses"]]
+
+ def skip_test_if_missing_module(self):
+ self.skip_if_no_wallet()
+
+ def run_test(self):
+ self.test_addresses_deprecation()
+
+ def test_addresses_deprecation(self):
+ node = self.nodes[0]
+ coin = node.listunspent().pop()
+
+ inputs = [{'txid': coin['txid'], 'vout': coin['vout']}]
+ outputs = {node.getnewaddress(): 0.99}
+ raw = node.createrawtransaction(inputs, outputs)
+ signed = node.signrawtransactionwithwallet(raw)['hex']
+
+ # This transaction is derived from test/util/data/txcreatemultisig1.json
+ tx = CTransaction()
+ tx.deserialize(BytesIO(hex_str_to_bytes(signed)))
+ tx.vout[0].scriptPubKey = hex_str_to_bytes("522102a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff39721021ac43c7ff740014c3b33737ede99c967e4764553d1b2b83db77c83b8715fa72d2102df2089105c77f266fa11a9d33f05c735234075f2e8780824c6b709415f9fb48553ae")
+ tx_signed = node.signrawtransactionwithwallet(tx.serialize().hex())['hex']
+ txid = node.sendrawtransaction(hexstring=tx_signed, maxfeerate=0)
+
+ self.log.info("Test RPCResult scriptPubKey no longer returns the fields addresses or reqSigs by default")
+ hash = node.generateblock(output=node.getnewaddress(), transactions=[txid])['hash']
+ # Ensure both nodes have the newly generated block on disk.
+ self.sync_blocks()
+ script_pub_key = node.getblock(blockhash=hash, verbose=2)['tx'][-1]['vout'][0]['scriptPubKey']
+ assert 'addresses' not in script_pub_key and 'reqSigs' not in script_pub_key
+
+ self.log.info("Test RPCResult scriptPubKey returns the addresses field with -deprecatedrpc=addresses")
+ script_pub_key = self.nodes[1].getblock(blockhash=hash, verbose=2)['tx'][-1]['vout'][0]['scriptPubKey']
+ assert_equal(script_pub_key['addresses'], ['mvKDK6D54HU8wQumJBLHY95eq5iHFqXSBz', 'mv3rHCQSwKp2BLSuMHD8uCS32LW5xiNAA5', 'mirrsyhAQYzo5CwVhcaYJKwUJu1WJRCRJe'])
+ assert_equal(script_pub_key['reqSigs'], 2)
+
+
+if __name__ == "__main__":
+ AddressesDeprecationTest().main()
diff --git a/test/functional/rpc_createmultisig.py b/test/functional/rpc_createmultisig.py
index 31baeba582..19f0d5765a 100755
--- a/test/functional/rpc_createmultisig.py
+++ b/test/functional/rpc_createmultisig.py
@@ -165,7 +165,7 @@ class RpcCreateMultiSigTest(BitcoinTestFramework):
txid = node0.sendtoaddress(madd, 40)
tx = node0.getrawtransaction(txid, True)
- vout = [v["n"] for v in tx["vout"] if madd in v["scriptPubKey"].get("addresses", [])]
+ vout = [v["n"] for v in tx["vout"] if madd == v["scriptPubKey"]["address"]]
assert len(vout) == 1
vout = vout[0]
scriptPubKey = tx["vout"][vout]["scriptPubKey"]["hex"]
diff --git a/test/functional/rpc_fundrawtransaction.py b/test/functional/rpc_fundrawtransaction.py
index 8c9755cc8c..5129ecb895 100755
--- a/test/functional/rpc_fundrawtransaction.py
+++ b/test/functional/rpc_fundrawtransaction.py
@@ -248,7 +248,7 @@ class RawTransactionsTest(BitcoinTestFramework):
rawtxfund = self.nodes[2].fundrawtransaction(rawtx, {'changeAddress': change, 'changePosition': 0})
dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
out = dec_tx['vout'][0]
- assert_equal(change, out['scriptPubKey']['addresses'][0])
+ assert_equal(change, out['scriptPubKey']['address'])
def test_change_type(self):
self.log.info("Test fundrawtxn with a provided change type")
@@ -288,7 +288,7 @@ class RawTransactionsTest(BitcoinTestFramework):
matchingOuts = 0
for i, out in enumerate(dec_tx['vout']):
totalOut += out['value']
- if out['scriptPubKey']['addresses'][0] in outputs:
+ if out['scriptPubKey']['address'] in outputs:
matchingOuts+=1
else:
assert_equal(i, rawtxfund['changepos'])
@@ -319,7 +319,7 @@ class RawTransactionsTest(BitcoinTestFramework):
matchingOuts = 0
for out in dec_tx['vout']:
totalOut += out['value']
- if out['scriptPubKey']['addresses'][0] in outputs:
+ if out['scriptPubKey']['address'] in outputs:
matchingOuts+=1
assert_equal(matchingOuts, 1)
@@ -353,7 +353,7 @@ class RawTransactionsTest(BitcoinTestFramework):
matchingOuts = 0
for out in dec_tx['vout']:
totalOut += out['value']
- if out['scriptPubKey']['addresses'][0] in outputs:
+ if out['scriptPubKey']['address'] in outputs:
matchingOuts+=1
assert_equal(matchingOuts, 2)
@@ -802,7 +802,7 @@ class RawTransactionsTest(BitcoinTestFramework):
changeaddress = ""
for out in res_dec['vout']:
if out['value'] > 1.0:
- changeaddress += out['scriptPubKey']['addresses'][0]
+ changeaddress += out['scriptPubKey']['address']
assert changeaddress != ""
nextaddr = self.nodes[3].getnewaddress()
# Now the change address key should be removed from the keypool.
diff --git a/test/functional/rpc_generateblock.py b/test/functional/rpc_generateblock.py
index 08ff0fba50..7424416484 100755
--- a/test/functional/rpc_generateblock.py
+++ b/test/functional/rpc_generateblock.py
@@ -27,13 +27,13 @@ class GenerateBlockTest(BitcoinTestFramework):
hash = node.generateblock(output=address, transactions=[])['hash']
block = node.getblock(blockhash=hash, verbose=2)
assert_equal(len(block['tx']), 1)
- assert_equal(block['tx'][0]['vout'][0]['scriptPubKey']['addresses'][0], address)
+ assert_equal(block['tx'][0]['vout'][0]['scriptPubKey']['address'], address)
self.log.info('Generate an empty block to a descriptor')
hash = node.generateblock('addr(' + address + ')', [])['hash']
block = node.getblock(blockhash=hash, verbosity=2)
assert_equal(len(block['tx']), 1)
- assert_equal(block['tx'][0]['vout'][0]['scriptPubKey']['addresses'][0], address)
+ assert_equal(block['tx'][0]['vout'][0]['scriptPubKey']['address'], address)
self.log.info('Generate an empty block to a combo descriptor with compressed pubkey')
combo_key = '0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798'
@@ -41,7 +41,7 @@ class GenerateBlockTest(BitcoinTestFramework):
hash = node.generateblock('combo(' + combo_key + ')', [])['hash']
block = node.getblock(hash, 2)
assert_equal(len(block['tx']), 1)
- assert_equal(block['tx'][0]['vout'][0]['scriptPubKey']['addresses'][0], combo_address)
+ assert_equal(block['tx'][0]['vout'][0]['scriptPubKey']['address'], combo_address)
self.log.info('Generate an empty block to a combo descriptor with uncompressed pubkey')
combo_key = '0408ef68c46d20596cc3f6ddf7c8794f71913add807f1dc55949fa805d764d191c0b7ce6894c126fce0babc6663042f3dde9b0cf76467ea315514e5a6731149c67'
@@ -49,7 +49,7 @@ class GenerateBlockTest(BitcoinTestFramework):
hash = node.generateblock('combo(' + combo_key + ')', [])['hash']
block = node.getblock(hash, 2)
assert_equal(len(block['tx']), 1)
- assert_equal(block['tx'][0]['vout'][0]['scriptPubKey']['addresses'][0], combo_address)
+ assert_equal(block['tx'][0]['vout'][0]['scriptPubKey']['address'], combo_address)
# Generate 110 blocks to spend
node.generatetoaddress(110, address)
diff --git a/test/functional/rpc_invalid_address_message.py b/test/functional/rpc_invalid_address_message.py
index 469d6bdb05..e362642f0f 100755
--- a/test/functional/rpc_invalid_address_message.py
+++ b/test/functional/rpc_invalid_address_message.py
@@ -12,8 +12,12 @@ from test_framework.util import (
)
BECH32_VALID = 'bcrt1qtmp74ayg7p24uslctssvjm06q5phz4yrxucgnv'
-BECH32_INVALID_SIZE = 'bcrt1sqqpl9r5c'
-BECH32_INVALID_PREFIX = 'bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4'
+BECH32_INVALID_BECH32 = 'bcrt1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vqdmchcc'
+BECH32_INVALID_BECH32M = 'bcrt1qw508d6qejxtdg4y5r3zarvary0c5xw7k35mrzd'
+BECH32_INVALID_VERSION = 'bcrt130xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vqynjegk'
+BECH32_INVALID_SIZE = 'bcrt1s0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7v8n0nx0muaewav25430mtr'
+BECH32_INVALID_V0_SIZE = 'bcrt1qw508d6qejxtdg4y5r3zarvary0c5xw7kqqq5k3my'
+BECH32_INVALID_PREFIX = 'bc1pw508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7k7grplx'
BASE58_VALID = 'mipcBbFg9gMiCh81Kj8tqqdgoZub1ZJRfn'
BASE58_INVALID_PREFIX = '17VZNX1SN5NtKa8UQFxwQbFeFc3iqRYhem'
@@ -40,6 +44,18 @@ class InvalidAddressErrorMessageTest(BitcoinTestFramework):
assert not info['isvalid']
assert_equal(info['error'], 'Invalid prefix for Bech32 address')
+ info = node.validateaddress(BECH32_INVALID_BECH32)
+ assert not info['isvalid']
+ assert_equal(info['error'], 'Version 1+ witness address must use Bech32m checksum')
+
+ info = node.validateaddress(BECH32_INVALID_BECH32M)
+ assert not info['isvalid']
+ assert_equal(info['error'], 'Version 0 witness address must use Bech32 checksum')
+
+ info = node.validateaddress(BECH32_INVALID_V0_SIZE)
+ assert not info['isvalid']
+ assert_equal(info['error'], 'Invalid Bech32 v0 address data size')
+
info = node.validateaddress(BECH32_VALID)
assert info['isvalid']
assert 'error' not in info
diff --git a/test/functional/rpc_psbt.py b/test/functional/rpc_psbt.py
index ed6abaed78..079a3bd3ba 100755
--- a/test/functional/rpc_psbt.py
+++ b/test/functional/rpc_psbt.py
@@ -158,17 +158,17 @@ class PSBTTest(BitcoinTestFramework):
p2sh_p2wpkh_pos = -1
decoded = self.nodes[0].decoderawtransaction(signed_tx)
for out in decoded['vout']:
- if out['scriptPubKey']['addresses'][0] == p2sh:
+ if out['scriptPubKey']['address'] == p2sh:
p2sh_pos = out['n']
- elif out['scriptPubKey']['addresses'][0] == p2wsh:
+ elif out['scriptPubKey']['address'] == p2wsh:
p2wsh_pos = out['n']
- elif out['scriptPubKey']['addresses'][0] == p2wpkh:
+ elif out['scriptPubKey']['address'] == p2wpkh:
p2wpkh_pos = out['n']
- elif out['scriptPubKey']['addresses'][0] == p2sh_p2wsh:
+ elif out['scriptPubKey']['address'] == p2sh_p2wsh:
p2sh_p2wsh_pos = out['n']
- elif out['scriptPubKey']['addresses'][0] == p2sh_p2wpkh:
+ elif out['scriptPubKey']['address'] == p2sh_p2wpkh:
p2sh_p2wpkh_pos = out['n']
- elif out['scriptPubKey']['addresses'][0] == p2pkh:
+ elif out['scriptPubKey']['address'] == p2pkh:
p2pkh_pos = out['n']
inputs = [{"txid": txid, "vout": p2wpkh_pos}, {"txid": txid, "vout": p2sh_p2wpkh_pos}, {"txid": txid, "vout": p2pkh_pos}]
diff --git a/test/functional/test_framework/messages.py b/test/functional/test_framework/messages.py
index a18a9ec109..5a9736a7a3 100755
--- a/test/functional/test_framework/messages.py
+++ b/test/functional/test_framework/messages.py
@@ -1045,13 +1045,11 @@ class msg_version:
self.nStartingHeight = struct.unpack("<i", f.read(4))[0]
- if self.nVersion >= 70001:
- # Relay field is optional for version 70001 onwards
- try:
- self.relay = struct.unpack("<b", f.read(1))[0]
- except:
- self.relay = 0
- else:
+ # Relay field is optional for version 70001 onwards
+ # But, unconditionally check it to match behaviour in bitcoind
+ try:
+ self.relay = struct.unpack("<b", f.read(1))[0]
+ except struct.error:
self.relay = 0
def serialize(self):
diff --git a/test/functional/test_framework/segwit_addr.py b/test/functional/test_framework/segwit_addr.py
index 00c0d8a919..861ca2b949 100644
--- a/test/functional/test_framework/segwit_addr.py
+++ b/test/functional/test_framework/segwit_addr.py
@@ -2,10 +2,18 @@
# Copyright (c) 2017 Pieter Wuille
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
-"""Reference implementation for Bech32 and segwit addresses."""
+"""Reference implementation for Bech32/Bech32m and segwit addresses."""
import unittest
+from enum import Enum
CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l"
+BECH32_CONST = 1
+BECH32M_CONST = 0x2bc830a3
+
+class Encoding(Enum):
+ """Enumeration type to list the various supported encodings."""
+ BECH32 = 1
+ BECH32M = 2
def bech32_polymod(values):
@@ -27,38 +35,45 @@ def bech32_hrp_expand(hrp):
def bech32_verify_checksum(hrp, data):
"""Verify a checksum given HRP and converted data characters."""
- return bech32_polymod(bech32_hrp_expand(hrp) + data) == 1
-
+ check = bech32_polymod(bech32_hrp_expand(hrp) + data)
+ if check == BECH32_CONST:
+ return Encoding.BECH32
+ elif check == BECH32M_CONST:
+ return Encoding.BECH32M
+ else:
+ return None
-def bech32_create_checksum(hrp, data):
+def bech32_create_checksum(encoding, hrp, data):
"""Compute the checksum values given HRP and data."""
values = bech32_hrp_expand(hrp) + data
- polymod = bech32_polymod(values + [0, 0, 0, 0, 0, 0]) ^ 1
+ const = BECH32M_CONST if encoding == Encoding.BECH32M else BECH32_CONST
+ polymod = bech32_polymod(values + [0, 0, 0, 0, 0, 0]) ^ const
return [(polymod >> 5 * (5 - i)) & 31 for i in range(6)]
-def bech32_encode(hrp, data):
- """Compute a Bech32 string given HRP and data values."""
- combined = data + bech32_create_checksum(hrp, data)
+def bech32_encode(encoding, hrp, data):
+ """Compute a Bech32 or Bech32m string given HRP and data values."""
+ combined = data + bech32_create_checksum(encoding, hrp, data)
return hrp + '1' + ''.join([CHARSET[d] for d in combined])
def bech32_decode(bech):
- """Validate a Bech32 string, and determine HRP and data."""
+ """Validate a Bech32/Bech32m string, and determine HRP and data."""
if ((any(ord(x) < 33 or ord(x) > 126 for x in bech)) or
(bech.lower() != bech and bech.upper() != bech)):
- return (None, None)
+ return (None, None, None)
bech = bech.lower()
pos = bech.rfind('1')
if pos < 1 or pos + 7 > len(bech) or len(bech) > 90:
- return (None, None)
+ return (None, None, None)
if not all(x in CHARSET for x in bech[pos+1:]):
- return (None, None)
+ return (None, None, None)
hrp = bech[:pos]
data = [CHARSET.find(x) for x in bech[pos+1:]]
- if not bech32_verify_checksum(hrp, data):
- return (None, None)
- return (hrp, data[:-6])
+ encoding = bech32_verify_checksum(hrp, data)
+ if encoding is None:
+ return (None, None, None)
+ return (encoding, hrp, data[:-6])
def convertbits(data, frombits, tobits, pad=True):
@@ -86,7 +101,7 @@ def convertbits(data, frombits, tobits, pad=True):
def decode_segwit_address(hrp, addr):
"""Decode a segwit address."""
- hrpgot, data = bech32_decode(addr)
+ encoding, hrpgot, data = bech32_decode(addr)
if hrpgot != hrp:
return (None, None)
decoded = convertbits(data[1:], 5, 8, False)
@@ -96,12 +111,15 @@ def decode_segwit_address(hrp, addr):
return (None, None)
if data[0] == 0 and len(decoded) != 20 and len(decoded) != 32:
return (None, None)
+ if (data[0] == 0 and encoding != Encoding.BECH32) or (data[0] != 0 and encoding != Encoding.BECH32M):
+ return (None, None)
return (data[0], decoded)
def encode_segwit_address(hrp, witver, witprog):
"""Encode a segwit address."""
- ret = bech32_encode(hrp, [witver] + convertbits(witprog, 8, 5))
+ encoding = Encoding.BECH32 if witver == 0 else Encoding.BECH32M
+ ret = bech32_encode(encoding, hrp, [witver] + convertbits(witprog, 8, 5))
if decode_segwit_address(hrp, ret) == (None, None):
return None
return ret
@@ -119,3 +137,5 @@ class TestFrameworkScript(unittest.TestCase):
# P2WSH
test_python_bech32('bcrt1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq3xueyj')
test_python_bech32('bcrt1qft5p2uhsdcdc3l2ua4ap5qqfg4pjaqlp250x7us7a8qqhrxrxfsqseac85')
+ # P2TR
+ test_python_bech32('bcrt1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vqc8gma6')
diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py
index d335d4ea79..5c774934be 100644
--- a/test/functional/test_framework/util.py
+++ b/test/functional/test_framework/util.py
@@ -543,7 +543,7 @@ def find_vout_for_address(node, txid, addr):
"""
tx = node.getrawtransaction(txid, True)
for i in range(len(tx["vout"])):
- if any([addr == a for a in tx["vout"][i]["scriptPubKey"]["addresses"]]):
+ if addr == tx["vout"][i]["scriptPubKey"]["address"]:
return i
raise RuntimeError("Vout not found for address: txid=%s, addr=%s" % (txid, addr))
diff --git a/test/functional/test_framework/wallet.py b/test/functional/test_framework/wallet.py
index 38fbf3c1a6..a906a21dd0 100644
--- a/test/functional/test_framework/wallet.py
+++ b/test/functional/test_framework/wallet.py
@@ -49,6 +49,9 @@ class MiniWallet:
self._utxos.append({'txid': cb_tx['txid'], 'vout': 0, 'value': cb_tx['vout'][0]['value']})
return blocks
+ def get_address(self):
+ return self._address
+
def get_utxo(self, *, txid=''):
"""
Returns a utxo and marks it as spent (pops it from the internal list)
diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py
index 79ad2cf161..001d161612 100755
--- a/test/functional/test_runner.py
+++ b/test/functional/test_runner.py
@@ -279,6 +279,7 @@ BASE_SCRIPTS = [
'p2p_ping.py',
'rpc_scantxoutset.py',
'feature_logging.py',
+ 'feature_anchors.py',
'p2p_node_network_limited.py',
'p2p_permissions.py',
'feature_blocksdir.py',
@@ -286,6 +287,7 @@ BASE_SCRIPTS = [
'feature_config_args.py',
'feature_settings.py',
'rpc_getdescriptorinfo.py',
+ 'rpc_addresses_deprecation.py',
'rpc_help.py',
'feature_help.py',
'feature_shutdown.py',
diff --git a/test/functional/wallet_address_types.py b/test/functional/wallet_address_types.py
index 2db5eae33b..b3bee1876d 100755
--- a/test/functional/wallet_address_types.py
+++ b/test/functional/wallet_address_types.py
@@ -210,7 +210,7 @@ class AddressTypeTest(BitcoinTestFramework):
assert_equal(len(tx["vout"]), len(destinations) + 1)
# Make sure the destinations are included, and remove them:
- output_addresses = [vout['scriptPubKey']['addresses'][0] for vout in tx["vout"]]
+ output_addresses = [vout['scriptPubKey']['address'] for vout in tx["vout"]]
change_addresses = [d for d in output_addresses if d not in destinations]
assert_equal(len(change_addresses), 1)
diff --git a/test/functional/wallet_avoidreuse.py b/test/functional/wallet_avoidreuse.py
index bc4fa90e83..1d3736d9b1 100755
--- a/test/functional/wallet_avoidreuse.py
+++ b/test/functional/wallet_avoidreuse.py
@@ -253,7 +253,7 @@ class AvoidReuseTest(BitcoinTestFramework):
if second_addr_type == "p2sh-segwit":
new_fundaddr = fund_decoded["segwit"]["p2sh-segwit"]
elif second_addr_type == "bech32":
- new_fundaddr = fund_decoded["segwit"]["addresses"][0]
+ new_fundaddr = fund_decoded["segwit"]["address"]
else:
new_fundaddr = fundaddr
assert_equal(second_addr_type, "legacy")
diff --git a/test/functional/wallet_basic.py b/test/functional/wallet_basic.py
index 4a589f0393..dc6f8ed9c4 100755
--- a/test/functional/wallet_basic.py
+++ b/test/functional/wallet_basic.py
@@ -600,7 +600,7 @@ class WalletTest(BitcoinTestFramework):
destination = self.nodes[1].getnewaddress()
txid = self.nodes[0].sendtoaddress(destination, 0.123)
tx = self.nodes[0].decoderawtransaction(self.nodes[0].gettransaction(txid)['hex'])
- output_addresses = [vout['scriptPubKey']['addresses'][0] for vout in tx["vout"]]
+ output_addresses = [vout['scriptPubKey']['address'] for vout in tx["vout"]]
assert len(output_addresses) > 1
for address in output_addresses:
ischange = self.nodes[0].getaddressinfo(address)['ischange']
diff --git a/test/functional/wallet_bumpfee.py b/test/functional/wallet_bumpfee.py
index 5fc8438e8f..0d1b6c54ce 100755
--- a/test/functional/wallet_bumpfee.py
+++ b/test/functional/wallet_bumpfee.py
@@ -535,7 +535,7 @@ def test_change_script_match(self, rbf_node, dest_address):
def get_change_address(tx):
tx_details = rbf_node.getrawtransaction(tx, 1)
- txout_addresses = [txout['scriptPubKey']['addresses'][0] for txout in tx_details["vout"]]
+ txout_addresses = [txout['scriptPubKey']['address'] for txout in tx_details["vout"]]
return [address for address in txout_addresses if rbf_node.getaddressinfo(address)["ischange"]]
# Check that there is only one change output
diff --git a/test/functional/wallet_hd.py b/test/functional/wallet_hd.py
index d45cf05689..23d132df41 100755
--- a/test/functional/wallet_hd.py
+++ b/test/functional/wallet_hd.py
@@ -132,7 +132,7 @@ class WalletHDTest(BitcoinTestFramework):
keypath = ""
for out in outs:
if out['value'] != 1:
- keypath = self.nodes[1].getaddressinfo(out['scriptPubKey']['addresses'][0])['hdkeypath']
+ keypath = self.nodes[1].getaddressinfo(out['scriptPubKey']['address'])['hdkeypath']
if self.options.descriptors:
assert_equal(keypath[0:14], "m/84'/1'/0'/1/")
diff --git a/test/functional/wallet_labels.py b/test/functional/wallet_labels.py
index 883b97561e..551eb72720 100755
--- a/test/functional/wallet_labels.py
+++ b/test/functional/wallet_labels.py
@@ -138,13 +138,13 @@ class WalletLabelsTest(BitcoinTestFramework):
node.createwallet(wallet_name='watch_only', disable_private_keys=True)
wallet_watch_only = node.get_wallet_rpc('watch_only')
BECH32_VALID = {
- '✔️_VER15_PROG40': 'bcrt10qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqn2cjv3',
- '✔️_VER16_PROG03': 'bcrt1sqqqqqjq8pdp',
- '✔️_VER16_PROB02': 'bcrt1sqqqqqjq8pv',
+ '✔️_VER15_PROG40': 'bcrt10qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqxkg7fn',
+ '✔️_VER16_PROG03': 'bcrt1sqqqqq8uhdgr',
+ '✔️_VER16_PROB02': 'bcrt1sqqqq4wstyw',
}
BECH32_INVALID = {
- '❌_VER15_PROG41': 'bcrt10qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzc7xyq',
- '❌_VER16_PROB01': 'bcrt1sqqpl9r5c',
+ '❌_VER15_PROG41': 'bcrt1sqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqajlxj8',
+ '❌_VER16_PROB01': 'bcrt1sqq5r4036',
}
for l in BECH32_VALID:
ad = BECH32_VALID[l]
diff --git a/test/functional/wallet_multiwallet.py b/test/functional/wallet_multiwallet.py
index bf24b9c7b3..71d1b96a95 100755
--- a/test/functional/wallet_multiwallet.py
+++ b/test/functional/wallet_multiwallet.py
@@ -34,7 +34,7 @@ def test_load_unload(node, name):
node.loadwallet(name)
node.unloadwallet(name)
except JSONRPCException as e:
- if e.error['code'] == -4 and 'Wallet already being loading' in e.error['message']:
+ if e.error['code'] == -4 and 'Wallet already loading' in e.error['message']:
got_loading_error = True
return
diff --git a/test/functional/wallet_send.py b/test/functional/wallet_send.py
index 880341fdd9..53553dcd80 100755
--- a/test/functional/wallet_send.py
+++ b/test/functional/wallet_send.py
@@ -389,10 +389,10 @@ class WalletSendTest(BitcoinTestFramework):
assert res["complete"]
res = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, add_to_wallet=False, change_address=change_address, change_position=0)
assert res["complete"]
- assert_equal(self.nodes[0].decodepsbt(res["psbt"])["tx"]["vout"][0]["scriptPubKey"]["addresses"], [change_address])
+ assert_equal(self.nodes[0].decodepsbt(res["psbt"])["tx"]["vout"][0]["scriptPubKey"]["address"], change_address)
res = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, add_to_wallet=False, change_type="legacy", change_position=0)
assert res["complete"]
- change_address = self.nodes[0].decodepsbt(res["psbt"])["tx"]["vout"][0]["scriptPubKey"]["addresses"][0]
+ change_address = self.nodes[0].decodepsbt(res["psbt"])["tx"]["vout"][0]["scriptPubKey"]["address"]
assert change_address[0] == "m" or change_address[0] == "n"
self.log.info("Set lock time...")
diff --git a/test/functional/wallet_txn_clone.py b/test/functional/wallet_txn_clone.py
index 6fc1d13c53..84ff9ad772 100755
--- a/test/functional/wallet_txn_clone.py
+++ b/test/functional/wallet_txn_clone.py
@@ -65,8 +65,8 @@ class TxnMallTest(BitcoinTestFramework):
# Construct a clone of tx1, to be malleated
rawtx1 = self.nodes[0].getrawtransaction(txid1, 1)
clone_inputs = [{"txid": rawtx1["vin"][0]["txid"], "vout": rawtx1["vin"][0]["vout"], "sequence": rawtx1["vin"][0]["sequence"]}]
- clone_outputs = {rawtx1["vout"][0]["scriptPubKey"]["addresses"][0]: rawtx1["vout"][0]["value"],
- rawtx1["vout"][1]["scriptPubKey"]["addresses"][0]: rawtx1["vout"][1]["value"]}
+ clone_outputs = {rawtx1["vout"][0]["scriptPubKey"]["address"]: rawtx1["vout"][0]["value"],
+ rawtx1["vout"][1]["scriptPubKey"]["address"]: rawtx1["vout"][1]["value"]}
clone_locktime = rawtx1["locktime"]
clone_raw = self.nodes[0].createrawtransaction(clone_inputs, clone_outputs, clone_locktime)
diff --git a/test/util/data/tt-delin1-out.json b/test/util/data/tt-delin1-out.json
index 9fc2ddc376..c5b9f6df01 100644
--- a/test/util/data/tt-delin1-out.json
+++ b/test/util/data/tt-delin1-out.json
@@ -195,11 +195,8 @@
"scriptPubKey": {
"asm": "OP_DUP OP_HASH160 8fd139bb39ced713f231c58a4d07bf6954d1c201 OP_EQUALVERIFY OP_CHECKSIG",
"hex": "76a9148fd139bb39ced713f231c58a4d07bf6954d1c20188ac",
- "reqSigs": 1,
- "type": "pubkeyhash",
- "addresses": [
- "1E7SGgAZFCHDnVZLuRViX3gUmxpMfdvd2o"
- ]
+ "address": "1E7SGgAZFCHDnVZLuRViX3gUmxpMfdvd2o",
+ "type": "pubkeyhash"
}
},
{
@@ -208,11 +205,8 @@
"scriptPubKey": {
"asm": "OP_DUP OP_HASH160 6c772e9cf96371bba3da8cb733da70a2fcf20078 OP_EQUALVERIFY OP_CHECKSIG",
"hex": "76a9146c772e9cf96371bba3da8cb733da70a2fcf2007888ac",
- "reqSigs": 1,
- "type": "pubkeyhash",
- "addresses": [
- "1AtWkdmfmYkErU16d3KYykJUbEp9MAj9Sb"
- ]
+ "address": "1AtWkdmfmYkErU16d3KYykJUbEp9MAj9Sb",
+ "type": "pubkeyhash"
}
}
],
diff --git a/test/util/data/tt-delout1-out.json b/test/util/data/tt-delout1-out.json
index 922d048900..3863416430 100644
--- a/test/util/data/tt-delout1-out.json
+++ b/test/util/data/tt-delout1-out.json
@@ -204,11 +204,8 @@
"scriptPubKey": {
"asm": "OP_DUP OP_HASH160 8fd139bb39ced713f231c58a4d07bf6954d1c201 OP_EQUALVERIFY OP_CHECKSIG",
"hex": "76a9148fd139bb39ced713f231c58a4d07bf6954d1c20188ac",
- "reqSigs": 1,
- "type": "pubkeyhash",
- "addresses": [
- "1E7SGgAZFCHDnVZLuRViX3gUmxpMfdvd2o"
- ]
+ "address": "1E7SGgAZFCHDnVZLuRViX3gUmxpMfdvd2o",
+ "type": "pubkeyhash"
}
}
],
diff --git a/test/util/data/tt-locktime317000-out.json b/test/util/data/tt-locktime317000-out.json
index c97206f1ea..62e785f7d0 100644
--- a/test/util/data/tt-locktime317000-out.json
+++ b/test/util/data/tt-locktime317000-out.json
@@ -204,11 +204,8 @@
"scriptPubKey": {
"asm": "OP_DUP OP_HASH160 8fd139bb39ced713f231c58a4d07bf6954d1c201 OP_EQUALVERIFY OP_CHECKSIG",
"hex": "76a9148fd139bb39ced713f231c58a4d07bf6954d1c20188ac",
- "reqSigs": 1,
- "type": "pubkeyhash",
- "addresses": [
- "1E7SGgAZFCHDnVZLuRViX3gUmxpMfdvd2o"
- ]
+ "address": "1E7SGgAZFCHDnVZLuRViX3gUmxpMfdvd2o",
+ "type": "pubkeyhash"
}
},
{
@@ -217,11 +214,8 @@
"scriptPubKey": {
"asm": "OP_DUP OP_HASH160 6c772e9cf96371bba3da8cb733da70a2fcf20078 OP_EQUALVERIFY OP_CHECKSIG",
"hex": "76a9146c772e9cf96371bba3da8cb733da70a2fcf2007888ac",
- "reqSigs": 1,
- "type": "pubkeyhash",
- "addresses": [
- "1AtWkdmfmYkErU16d3KYykJUbEp9MAj9Sb"
- ]
+ "address": "1AtWkdmfmYkErU16d3KYykJUbEp9MAj9Sb",
+ "type": "pubkeyhash"
}
}
],
diff --git a/test/util/data/txcreate1.json b/test/util/data/txcreate1.json
index ca9eacd546..96d77ef273 100644
--- a/test/util/data/txcreate1.json
+++ b/test/util/data/txcreate1.json
@@ -42,11 +42,8 @@
"scriptPubKey": {
"asm": "OP_DUP OP_HASH160 1fc11f39be1729bf973a7ab6a615ca4729d64574 OP_EQUALVERIFY OP_CHECKSIG",
"hex": "76a9141fc11f39be1729bf973a7ab6a615ca4729d6457488ac",
- "reqSigs": 1,
- "type": "pubkeyhash",
- "addresses": [
- "13tuJJDR2RgArmgfv6JScSdreahzgc4T6o"
- ]
+ "address": "13tuJJDR2RgArmgfv6JScSdreahzgc4T6o",
+ "type": "pubkeyhash"
}
},
{
@@ -55,11 +52,8 @@
"scriptPubKey": {
"asm": "OP_DUP OP_HASH160 f2d4db28cad6502226ee484ae24505c2885cb12d OP_EQUALVERIFY OP_CHECKSIG",
"hex": "76a914f2d4db28cad6502226ee484ae24505c2885cb12d88ac",
- "reqSigs": 1,
- "type": "pubkeyhash",
- "addresses": [
- "1P8yWvZW8jVihP1bzHeqfE4aoXNX8AVa46"
- ]
+ "address": "1P8yWvZW8jVihP1bzHeqfE4aoXNX8AVa46",
+ "type": "pubkeyhash"
}
}
],
diff --git a/test/util/data/txcreatedata1.json b/test/util/data/txcreatedata1.json
index 39909c2e3f..87fc7e9cf7 100644
--- a/test/util/data/txcreatedata1.json
+++ b/test/util/data/txcreatedata1.json
@@ -24,11 +24,8 @@
"scriptPubKey": {
"asm": "OP_DUP OP_HASH160 1fc11f39be1729bf973a7ab6a615ca4729d64574 OP_EQUALVERIFY OP_CHECKSIG",
"hex": "76a9141fc11f39be1729bf973a7ab6a615ca4729d6457488ac",
- "reqSigs": 1,
- "type": "pubkeyhash",
- "addresses": [
- "13tuJJDR2RgArmgfv6JScSdreahzgc4T6o"
- ]
+ "address": "13tuJJDR2RgArmgfv6JScSdreahzgc4T6o",
+ "type": "pubkeyhash"
}
},
{
diff --git a/test/util/data/txcreatedata2.json b/test/util/data/txcreatedata2.json
index 2958006e58..d03b1c8244 100644
--- a/test/util/data/txcreatedata2.json
+++ b/test/util/data/txcreatedata2.json
@@ -24,11 +24,8 @@
"scriptPubKey": {
"asm": "OP_DUP OP_HASH160 1fc11f39be1729bf973a7ab6a615ca4729d64574 OP_EQUALVERIFY OP_CHECKSIG",
"hex": "76a9141fc11f39be1729bf973a7ab6a615ca4729d6457488ac",
- "reqSigs": 1,
- "type": "pubkeyhash",
- "addresses": [
- "13tuJJDR2RgArmgfv6JScSdreahzgc4T6o"
- ]
+ "address": "13tuJJDR2RgArmgfv6JScSdreahzgc4T6o",
+ "type": "pubkeyhash"
}
},
{
diff --git a/test/util/data/txcreatedata_seq0.json b/test/util/data/txcreatedata_seq0.json
index a6656b5ad5..8a123f1ba8 100644
--- a/test/util/data/txcreatedata_seq0.json
+++ b/test/util/data/txcreatedata_seq0.json
@@ -24,11 +24,8 @@
"scriptPubKey": {
"asm": "OP_DUP OP_HASH160 1fc11f39be1729bf973a7ab6a615ca4729d64574 OP_EQUALVERIFY OP_CHECKSIG",
"hex": "76a9141fc11f39be1729bf973a7ab6a615ca4729d6457488ac",
- "reqSigs": 1,
- "type": "pubkeyhash",
- "addresses": [
- "13tuJJDR2RgArmgfv6JScSdreahzgc4T6o"
- ]
+ "address": "13tuJJDR2RgArmgfv6JScSdreahzgc4T6o",
+ "type": "pubkeyhash"
}
}
],
diff --git a/test/util/data/txcreatedata_seq1.json b/test/util/data/txcreatedata_seq1.json
index e5980427b1..006fd7259f 100644
--- a/test/util/data/txcreatedata_seq1.json
+++ b/test/util/data/txcreatedata_seq1.json
@@ -33,11 +33,8 @@
"scriptPubKey": {
"asm": "OP_DUP OP_HASH160 1fc11f39be1729bf973a7ab6a615ca4729d64574 OP_EQUALVERIFY OP_CHECKSIG",
"hex": "76a9141fc11f39be1729bf973a7ab6a615ca4729d6457488ac",
- "reqSigs": 1,
- "type": "pubkeyhash",
- "addresses": [
- "13tuJJDR2RgArmgfv6JScSdreahzgc4T6o"
- ]
+ "address": "13tuJJDR2RgArmgfv6JScSdreahzgc4T6o",
+ "type": "pubkeyhash"
}
}
],
diff --git a/test/util/data/txcreatemultisig1.json b/test/util/data/txcreatemultisig1.json
index c32e755db1..baa290c2b1 100644
--- a/test/util/data/txcreatemultisig1.json
+++ b/test/util/data/txcreatemultisig1.json
@@ -15,13 +15,7 @@
"scriptPubKey": {
"asm": "2 02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397 021ac43c7ff740014c3b33737ede99c967e4764553d1b2b83db77c83b8715fa72d 02df2089105c77f266fa11a9d33f05c735234075f2e8780824c6b709415f9fb485 3 OP_CHECKMULTISIG",
"hex": "522102a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff39721021ac43c7ff740014c3b33737ede99c967e4764553d1b2b83db77c83b8715fa72d2102df2089105c77f266fa11a9d33f05c735234075f2e8780824c6b709415f9fb48553ae",
- "reqSigs": 2,
- "type": "multisig",
- "addresses": [
- "1FoG2386FG2tAJS9acMuiDsKy67aGg9MKz",
- "1FXtz9KU8JNmQDyHdiEm5HDiALuP3zdHvV",
- "14LuavcBbXZYJ6Tsz3cAUQj9SuQoL2xCQX"
- ]
+ "type": "multisig"
}
}
],
diff --git a/test/util/data/txcreatemultisig2.json b/test/util/data/txcreatemultisig2.json
index f97d265894..6685512587 100644
--- a/test/util/data/txcreatemultisig2.json
+++ b/test/util/data/txcreatemultisig2.json
@@ -15,11 +15,8 @@
"scriptPubKey": {
"asm": "OP_HASH160 1c6fbaf46d64221e80cbae182c33ddf81b9294ac OP_EQUAL",
"hex": "a9141c6fbaf46d64221e80cbae182c33ddf81b9294ac87",
- "reqSigs": 1,
- "type": "scripthash",
- "addresses": [
- "34HNh57oBCRKkxNyjTuWAJkTbuGh6jg2Ms"
- ]
+ "address": "34HNh57oBCRKkxNyjTuWAJkTbuGh6jg2Ms",
+ "type": "scripthash"
}
}
],
diff --git a/test/util/data/txcreatemultisig3.json b/test/util/data/txcreatemultisig3.json
index b355d7b191..be96f4c704 100644
--- a/test/util/data/txcreatemultisig3.json
+++ b/test/util/data/txcreatemultisig3.json
@@ -15,11 +15,8 @@
"scriptPubKey": {
"asm": "0 e15a86a23178f433d514dbbce042e87d72662b8b5edcacfd2e37ab7a2d135f05",
"hex": "0020e15a86a23178f433d514dbbce042e87d72662b8b5edcacfd2e37ab7a2d135f05",
- "reqSigs": 1,
- "type": "witness_v0_scripthash",
- "addresses": [
- "bc1qu9dgdg330r6r84g5mw7wqshg04exv2uttmw2elfwx74h5tgntuzs44gyfg"
- ]
+ "address": "bc1qu9dgdg330r6r84g5mw7wqshg04exv2uttmw2elfwx74h5tgntuzs44gyfg",
+ "type": "witness_v0_scripthash"
}
}
],
diff --git a/test/util/data/txcreatemultisig4.json b/test/util/data/txcreatemultisig4.json
index a00dbe3f5d..08831ecdca 100644
--- a/test/util/data/txcreatemultisig4.json
+++ b/test/util/data/txcreatemultisig4.json
@@ -15,11 +15,8 @@
"scriptPubKey": {
"asm": "OP_HASH160 6edf12858999f0dae74f9c692e6694ee3621b2ac OP_EQUAL",
"hex": "a9146edf12858999f0dae74f9c692e6694ee3621b2ac87",
- "reqSigs": 1,
- "type": "scripthash",
- "addresses": [
- "3BoFUz1StqcNcgUTZE5cC1eFhuYFzj3fGH"
- ]
+ "address": "3BoFUz1StqcNcgUTZE5cC1eFhuYFzj3fGH",
+ "type": "scripthash"
}
}
],
diff --git a/test/util/data/txcreatemultisig5.json b/test/util/data/txcreatemultisig5.json
index ea07822ddd..93048cf261 100644
--- a/test/util/data/txcreatemultisig5.json
+++ b/test/util/data/txcreatemultisig5.json
@@ -15,11 +15,8 @@
"scriptPubKey": {
"asm": "OP_HASH160 a4051c02398868af83f28f083208fae99a769263 OP_EQUAL",
"hex": "a914a4051c02398868af83f28f083208fae99a76926387",
- "reqSigs": 1,
- "type": "scripthash",
- "addresses": [
- "3GeGs1eHUxPz5YyuFe9WPpXid2UsUb5Jos"
- ]
+ "address": "3GeGs1eHUxPz5YyuFe9WPpXid2UsUb5Jos",
+ "type": "scripthash"
}
}
],
diff --git a/test/util/data/txcreateoutpubkey2.json b/test/util/data/txcreateoutpubkey2.json
index c0ee181ede..52168a889b 100644
--- a/test/util/data/txcreateoutpubkey2.json
+++ b/test/util/data/txcreateoutpubkey2.json
@@ -15,11 +15,8 @@
"scriptPubKey": {
"asm": "0 a2516e770582864a6a56ed21a102044e388c62e3",
"hex": "0014a2516e770582864a6a56ed21a102044e388c62e3",
- "reqSigs": 1,
- "type": "witness_v0_keyhash",
- "addresses": [
- "bc1q5fgkuac9s2ry56jka5s6zqsyfcugcchry5cwu0"
- ]
+ "address": "bc1q5fgkuac9s2ry56jka5s6zqsyfcugcchry5cwu0",
+ "type": "witness_v0_keyhash"
}
}
],
diff --git a/test/util/data/txcreateoutpubkey3.json b/test/util/data/txcreateoutpubkey3.json
index 4d904df3c8..fce210f8a3 100644
--- a/test/util/data/txcreateoutpubkey3.json
+++ b/test/util/data/txcreateoutpubkey3.json
@@ -15,11 +15,8 @@
"scriptPubKey": {
"asm": "OP_HASH160 a5ab14c9804d0d8bf02f1aea4e82780733ad0a83 OP_EQUAL",
"hex": "a914a5ab14c9804d0d8bf02f1aea4e82780733ad0a8387",
- "reqSigs": 1,
- "type": "scripthash",
- "addresses": [
- "3GnzN8FqgvYGYdhj8NW6UNxxVv3Uj1ApQn"
- ]
+ "address": "3GnzN8FqgvYGYdhj8NW6UNxxVv3Uj1ApQn",
+ "type": "scripthash"
}
}
],
diff --git a/test/util/data/txcreatescript2.json b/test/util/data/txcreatescript2.json
index 32dd644579..2cde70fdf7 100644
--- a/test/util/data/txcreatescript2.json
+++ b/test/util/data/txcreatescript2.json
@@ -15,11 +15,8 @@
"scriptPubKey": {
"asm": "OP_HASH160 71ed53322d470bb96657deb786b94f97dd46fb15 OP_EQUAL",
"hex": "a91471ed53322d470bb96657deb786b94f97dd46fb1587",
- "reqSigs": 1,
- "type": "scripthash",
- "addresses": [
- "3C5QarEGh9feKbDJ3QbMf2YNjnMoiPDhNp"
- ]
+ "address": "3C5QarEGh9feKbDJ3QbMf2YNjnMoiPDhNp",
+ "type": "scripthash"
}
}
],
diff --git a/test/util/data/txcreatescript3.json b/test/util/data/txcreatescript3.json
index b9192d9a82..7a282faf4f 100644
--- a/test/util/data/txcreatescript3.json
+++ b/test/util/data/txcreatescript3.json
@@ -15,11 +15,8 @@
"scriptPubKey": {
"asm": "0 0bfe935e70c321c7ca3afc75ce0d0ca2f98b5422e008bb31c00c6d7f1f1c0ad6",
"hex": "00200bfe935e70c321c7ca3afc75ce0d0ca2f98b5422e008bb31c00c6d7f1f1c0ad6",
- "reqSigs": 1,
- "type": "witness_v0_scripthash",
- "addresses": [
- "bc1qp0lfxhnscvsu0j36l36uurgv5tuck4pzuqytkvwqp3kh78cupttqyf705v"
- ]
+ "address": "bc1qp0lfxhnscvsu0j36l36uurgv5tuck4pzuqytkvwqp3kh78cupttqyf705v",
+ "type": "witness_v0_scripthash"
}
}
],
diff --git a/test/util/data/txcreatescript4.json b/test/util/data/txcreatescript4.json
index 2271ecfa0a..298b37bb4a 100644
--- a/test/util/data/txcreatescript4.json
+++ b/test/util/data/txcreatescript4.json
@@ -15,11 +15,8 @@
"scriptPubKey": {
"asm": "OP_HASH160 6a2c482f4985f57e702f325816c90e3723ca81ae OP_EQUAL",
"hex": "a9146a2c482f4985f57e702f325816c90e3723ca81ae87",
- "reqSigs": 1,
- "type": "scripthash",
- "addresses": [
- "3BNQbeFeJJGMAyDxPwWPuqxPMrjsFLjk3f"
- ]
+ "address": "3BNQbeFeJJGMAyDxPwWPuqxPMrjsFLjk3f",
+ "type": "scripthash"
}
}
],
diff --git a/test/util/data/txcreatesignv1.json b/test/util/data/txcreatesignv1.json
index 7a06aa9ffe..ca5e003110 100644
--- a/test/util/data/txcreatesignv1.json
+++ b/test/util/data/txcreatesignv1.json
@@ -24,11 +24,8 @@
"scriptPubKey": {
"asm": "OP_DUP OP_HASH160 5834479edbbe0539b31ffd3a8f8ebadc2165ed01 OP_EQUALVERIFY OP_CHECKSIG",
"hex": "76a9145834479edbbe0539b31ffd3a8f8ebadc2165ed0188ac",
- "reqSigs": 1,
- "type": "pubkeyhash",
- "addresses": [
- "193P6LtvS4nCnkDvM9uXn1gsSRqh4aDAz7"
- ]
+ "address": "193P6LtvS4nCnkDvM9uXn1gsSRqh4aDAz7",
+ "type": "pubkeyhash"
}
}
],