Compare commits

...

17 commits

Author SHA1 Message Date
Hennadii Stepanov
61b15138bc
Merge 7e80030a95 into 65714c162c 2025-04-29 00:42:37 +02:00
Ava Chow
65714c162c
Merge bitcoin/bitcoin#32327: test: Add missing check for empty stderr in util tester
Some checks are pending
CI / test each commit (push) Waiting to run
CI / macOS 14 native, arm64, no depends, sqlite only, gui (push) Waiting to run
CI / macOS 14 native, arm64, fuzz (push) Waiting to run
CI / Windows native, VS 2022 (push) Waiting to run
CI / Windows native, fuzz, VS 2022 (push) Waiting to run
CI / Linux->Windows cross, no tests (push) Waiting to run
CI / Windows, test cross-built (push) Blocked by required conditions
CI / ASan + LSan + UBSan + integer, no depends, USDT (push) Waiting to run
fadf12a56c test: Add missing check for empty stderr in util tester (MarcoFalke)

Pull request description:

  Now that wine support was removed from the CI in 25b56fd9b4, it can probably be removed from the util tester as well.

  If someone really needs this, they can comment the new check out, or submit a patch to add an option/env var to silence the new check.

ACKs for top commit:
  achow101:
    ACK fadf12a56c
  i-am-yuvi:
    tACK fadf12a56c
  BrandonOdiwuor:
    Code Review ACK fadf12a56c
  ismaelsadeeq:
    Tested ACK fadf12a56c

Tree-SHA512: d9e4d7a7f724e114391070ea7f17b585a7e4c4f3221c3bf510eeb11df6ccd089b881ab5654adfef8d3a1f8fa7ec6bf5e3a3feeb0cdfe724a8f3e5a146c388e66
2025-04-28 14:43:32 -07:00
merge-script
a4eee6d50b
Merge bitcoin/bitcoin#29124: test: Test that migration automatically repairs corrupted metadata with doubled derivation path
c7e2b9e264 tests: Test migration cleans up bad inactive chain derivation path (Ava Chow)

Pull request description:

  A bug in 0.21.x and 22.x resulted in some wallets having invalid derivation paths that are the concatenation of two derivation paths. These appear only when inactive hd chains are topped up.

  Since key metadata is a legacy wallet only record, migrating legacy wallets to descriptor wallets will fix this issue as all key metadata records are deleted. The derivation path information is derived on-the-fly from the descriptor that is produced for the inactive hd chain.

  Thus we only need a test to verify that the derivation paths are good, and that all key metadata records are deleted from the migrated wallet.

ACKs for top commit:
  murchandamus:
    re-ACK c7e2b9e264 via range-diff:
  rkrux:
    re-ACK c7e2b9e264
  furszy:
    utACK c7e2b9e264

Tree-SHA512: 3117c4a43798972109fe2d3539341a8b69db70c6457fcabdd019e6044834dc4b17212abbc006d7b8008f560dce4b7856142b057981b9404f406d58fa0955cbd9
2025-04-28 17:13:42 -04:00
Ava Chow
af6cffa36d
Merge bitcoin/bitcoin#32350: test: Slim down previous releases bdb check
fa58f40b89 test: Slim down previous releases bdb check (MarcoFalke)

Pull request description:

  The check iterates over several previous BDB-only releases to check that descriptor wallets are considered "corrupt" when loading. It is unclear why this needs to be done for more than one release.

  Avoid the confusion by removing the unused releases from the test and from the download script.

ACKs for top commit:
  achow101:
    ACK fa58f40b89
  rkrux:
    ACK fa58f40b89

Tree-SHA512: 8084392481bfe1fba9b80bb865ffbdfa454e9e6e14e02c39fa3f61c1a596b1def2c531c5da1c7566e5fddb77ac7e56f19feabaaf9b5af043fa6c230d9e2370b5
2025-04-28 12:56:22 -07:00
Ava Chow
33e6538b30
Merge bitcoin/bitcoin#32360: test: Force named args for RPCOverloadWrapper optional args
fa48be3ba4 test: Force named args for RPCOverloadWrapper optional args (MarcoFalke)
aaaa45399c test: Remove unused createwallet_passthrough (MarcoFalke)
cccc1f4e91 test: Remove unused RPCOverloadWrapper is_cli field (MarcoFalke)

Pull request description:

  This can avoid bugs and makes the test code easier to read, because the
  order of positional args does not have to be known or assumed.

  Also, contains two commits to remove dead code.

ACKs for top commit:
  achow101:
    ACK fa48be3ba4
  rkrux:
    tACK fa48be3ba4
  janb84:
    tACK [fa48be3](fa48be3ba4)

Tree-SHA512: d938fbc18be5035ad0d0e1ad2bf7297b2b66ede3bb2d3f10b8d27aa2a19d27a897b024a5f5a2a1cceca467837890729c26054928cb06acbe282b9e9eea94ae69
2025-04-28 12:41:00 -07:00
merge-script
3a29ba33dc
Merge bitcoin/bitcoin#32357: depends: Fix cross-compiling qt package from macOS to Windows
Some checks are pending
CI / test each commit (push) Waiting to run
CI / macOS 14 native, arm64, no depends, sqlite only, gui (push) Waiting to run
CI / macOS 14 native, arm64, fuzz (push) Waiting to run
CI / Windows native, VS 2022 (push) Waiting to run
CI / Windows native, fuzz, VS 2022 (push) Waiting to run
CI / Linux->Windows cross, no tests (push) Waiting to run
CI / Windows, test cross-built (push) Blocked by required conditions
CI / ASan + LSan + UBSan + integer, no depends, USDT (push) Waiting to run
35e57fbe33 depends: Fix cross-compiling `qt` package from macOS to Windows (Hennadii Stepanov)

Pull request description:

  Native packages cannot be used during cross-compiling. However, Qt still unconditionally tries to find them, which causes issues in some cases, such as when [cross-compiling from macOS to Windows](https://github.com/bitcoin/bitcoin/issues/32346).

  This PR explicitly disables this unnecessary Qt behaviour.

  Fixes https://github.com/bitcoin/bitcoin/issues/32346.

  Here is a full workflow on my macOS Sequoia 15.4.1 (Intel):
  ```
  % brew install make cmake ninja mingw-w64 nsis
  % gmake -C depends -j 10 HOST=x86_64-w64-mingw32
  % cmake -B build --toolchain depends/x86_64-w64-mingw32/toolchain.cmake
  % cmake --build build -j 10 -t deploy
  ```

ACKs for top commit:
  shahsb:
    ACK 35e57fbe33
  fanquake:
    ACK 35e57fbe33

Tree-SHA512: 2822fb49bc84dd094dbd189d8a9ca0f023e1e48127db7beaefb9db92de53df63bb0f399c9c430c33941f9a9ee6976b9161d80467d889f7717385b9d1ea9fee43
2025-04-28 16:15:13 +01:00
MarcoFalke
fa48be3ba4
test: Force named args for RPCOverloadWrapper optional args
This can avoid bugs and makes the test code easier to read, because the
order of positional args does not have to be known or assumed.
2025-04-28 15:15:05 +02:00
MarcoFalke
aaaa45399c
test: Remove unused createwallet_passthrough 2025-04-28 15:14:52 +02:00
merge-script
f409444d02
Merge bitcoin/bitcoin#32071: build: Drop option to disable hardening.
77e553ab6a build: refactor: hardening flags -> core_interface (David Gumberg)
00ba3ba303 build: Drop option for disabling hardening (David Gumberg)
f57db75e91 build: Use `-z noseparate-code` on NetBSD < 11.0 (David Gumberg)

Pull request description:

  Follow up to #32038 which dropped `NO_HARDEN` from depends builds, this PR drops the `ENABLE_HARDENING` build option since disabling hardening of binaries should not be a supported or maintained use case. With this change, hardening flags are always enabled.

  Individual hardening flags and options can still be disabled by appending flags, e.g.:

  ```bash
  cmake -B build \
    -DAPPEND_CPPFLAGS='-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0 -fno-stack-protector -fcf-protection=none -fno-stack-clash-protection' \
    -DAPPEND_LDFLAGS='-Wl,-z,lazy -Wl,-z,norelro -Wl,-z,noseparate-code'
  ```

  There is an issue with NetBSD 10.0's dynamic linker that makes one of the hardening linker flags, `-z separate-code`, [problematic](https://github.com/bitcoin/bitcoin/pull/28724#issuecomment-2589347934), so this PR also introduces a check to prevent the use of this flag in NetBSD versions < 11.0, (where this issue is [fixed](acf7fb3abf)). The fix for this [might be backported](https://mail-index.netbsd.org/tech-userlevel/2023/01/05/msg013670.html) to NetBSD 10.0.

  I suggest reviewing the diff with whitespace changes hidden (`git diff -w` or using github's hide whitespace option)

ACKs for top commit:
  hebasto:
    re-ACK 77e553ab6a.
  laanwj:
    re-ACK 77e553ab6a
  janb84:
    ACK [77e553a](77e553ab6a)
  vasild:
    ACK 77e553ab6a
  musaHaruna:
    tested ACK [77e553](77e553ab6a)

Tree-SHA512: b149fb0371d12312c140255bf674c2bdc9f5272a5750a5b9ec5f192323364bb2ea8e164af13b9ab981ab3aa7ceb91b7a64785081e7458470e81c2f5228abf7b1
2025-04-28 13:32:16 +01:00
MarcoFalke
cccc1f4e91
test: Remove unused RPCOverloadWrapper is_cli field 2025-04-28 10:18:59 +02:00
Hennadii Stepanov
35e57fbe33 depends: Fix cross-compiling qt package from macOS to Windows 2025-04-26 17:13:16 +01:00
Ava Chow
c7e2b9e264 tests: Test migration cleans up bad inactive chain derivation path
A bug in 0.21.x and 22.x resulted in some wallets having invalid
derivation paths that are the concatenation of two derivation paths.
These appear only when inactive hd chains are topped up.

Since key metadata is a legacy wallet only record, migrating legacy
wallets to descriptor wallets will fix this issue as all key metadata
records are deleted. The derivation path information is derived
on-the-fly from the descriptor that is produced for the inactive hd
chain.

Thus we only need a test to verify that the derivation paths are good,
and that all key metadata records are deleted from the migrated wallet.
2025-04-25 09:12:53 -07:00
MarcoFalke
fa58f40b89
test: Slim down previous releases bdb check 2025-04-25 16:04:07 +02:00
MarcoFalke
fadf12a56c
test: Add missing check for empty stderr in util tester 2025-04-22 17:54:38 +02:00
David Gumberg
77e553ab6a build: refactor: hardening flags -> core_interface 2025-03-24 13:38:12 -07:00
David Gumberg
00ba3ba303 build: Drop option for disabling hardening
Building unhardened executables is not a supported use case that should
be maintained and those that want unhardened executables can still
override them by appending disable flags.

For example:

cmake -B build -DAPPEND_CPPFLAGS='-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0 -fno-stack-protector -fcf-protection=none -fno-stack-clash-protection' -DAPPEND_LDFLAGS='-Wl,-z,lazy -Wl,-z,norelro -Wl,-z,noseparate-code'
2025-03-24 13:37:49 -07:00
David Gumberg
f57db75e91 build: Use -z noseparate-code on NetBSD < 11.0
This can be dropped once Bitcoin Core no longer supports NetBSD 10.0 or
if upstream fix is backported.

NetBSD's dynamic linker ld.elf_so < 11.0 supports exactly 2 `PT_LOAD`
segments and binaries linked with `-z separate-code` have 4 `PT_LOAD`
segments.

https://github.com/bitcoin/bitcoin/pull/28724#issuecomment-2589347934
https://mail-index.netbsd.org/tech-userlevel/2023/01/05/msg013666.html
2025-03-24 13:37:10 -07:00
11 changed files with 187 additions and 130 deletions

View file

@ -128,7 +128,6 @@ if(WITH_BDB)
endif() endif()
cmake_dependent_option(BUILD_WALLET_TOOL "Build bitcoin-wallet tool." ${BUILD_TESTS} "ENABLE_WALLET" OFF) cmake_dependent_option(BUILD_WALLET_TOOL "Build bitcoin-wallet tool." ${BUILD_TESTS} "ENABLE_WALLET" OFF)
option(ENABLE_HARDENING "Attempt to harden the resulting executables." ON)
option(REDUCE_EXPORTS "Attempt to reduce exported symbols in the resulting executables." OFF) option(REDUCE_EXPORTS "Attempt to reduce exported symbols in the resulting executables." OFF)
option(WERROR "Treat compiler warnings as errors." OFF) option(WERROR "Treat compiler warnings as errors." OFF)
option(WITH_CCACHE "Attempt to use ccache for compiling." ON) option(WITH_CCACHE "Attempt to use ccache for compiling." ON)
@ -502,13 +501,10 @@ try_append_cxx_flags("-fmacro-prefix-map=A=B" TARGET core_interface SKIP_LINK
# -fstack-reuse=none for all gcc builds. (Only gcc understands this flag). # -fstack-reuse=none for all gcc builds. (Only gcc understands this flag).
try_append_cxx_flags("-fstack-reuse=none" TARGET core_interface) try_append_cxx_flags("-fstack-reuse=none" TARGET core_interface)
if(ENABLE_HARDENING)
add_library(hardening_interface INTERFACE)
target_link_libraries(core_interface INTERFACE hardening_interface)
if(MSVC) if(MSVC)
try_append_linker_flag("/DYNAMICBASE" TARGET hardening_interface) try_append_linker_flag("/DYNAMICBASE" TARGET core_interface)
try_append_linker_flag("/HIGHENTROPYVA" TARGET hardening_interface) try_append_linker_flag("/HIGHENTROPYVA" TARGET core_interface)
try_append_linker_flag("/NXCOMPAT" TARGET hardening_interface) try_append_linker_flag("/NXCOMPAT" TARGET core_interface)
else() else()
# _FORTIFY_SOURCE requires that there is some level of optimization, # _FORTIFY_SOURCE requires that there is some level of optimization,
@ -522,42 +518,53 @@ if(ENABLE_HARDENING)
}" }"
) )
if(cxx_supports_fortify_source) if(cxx_supports_fortify_source)
target_compile_options(hardening_interface INTERFACE target_compile_options(core_interface INTERFACE
-U_FORTIFY_SOURCE -U_FORTIFY_SOURCE
-D_FORTIFY_SOURCE=3 -D_FORTIFY_SOURCE=3
) )
endif() endif()
unset(cxx_supports_fortify_source) unset(cxx_supports_fortify_source)
try_append_cxx_flags("-Wstack-protector" TARGET hardening_interface SKIP_LINK) try_append_cxx_flags("-Wstack-protector" TARGET core_interface SKIP_LINK)
try_append_cxx_flags("-fstack-protector-all" TARGET hardening_interface) try_append_cxx_flags("-fstack-protector-all" TARGET core_interface)
try_append_cxx_flags("-fcf-protection=full" TARGET hardening_interface) try_append_cxx_flags("-fcf-protection=full" TARGET core_interface)
if(MINGW) if(MINGW)
# stack-clash-protection is a no-op for Windows. # stack-clash-protection is a no-op for Windows.
# See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90458 for more details. # See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90458 for more details.
else() else()
try_append_cxx_flags("-fstack-clash-protection" TARGET hardening_interface) try_append_cxx_flags("-fstack-clash-protection" TARGET core_interface)
endif() endif()
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64") if(CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64")
if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
try_append_cxx_flags("-mbranch-protection=bti" TARGET hardening_interface SKIP_LINK) try_append_cxx_flags("-mbranch-protection=bti" TARGET core_interface SKIP_LINK)
else() else()
try_append_cxx_flags("-mbranch-protection=standard" TARGET hardening_interface SKIP_LINK) try_append_cxx_flags("-mbranch-protection=standard" TARGET core_interface SKIP_LINK)
endif() endif()
endif() endif()
try_append_linker_flag("-Wl,--enable-reloc-section" TARGET hardening_interface) try_append_linker_flag("-Wl,--enable-reloc-section" TARGET core_interface)
try_append_linker_flag("-Wl,--dynamicbase" TARGET hardening_interface) try_append_linker_flag("-Wl,--dynamicbase" TARGET core_interface)
try_append_linker_flag("-Wl,--nxcompat" TARGET hardening_interface) try_append_linker_flag("-Wl,--nxcompat" TARGET core_interface)
try_append_linker_flag("-Wl,--high-entropy-va" TARGET hardening_interface) try_append_linker_flag("-Wl,--high-entropy-va" TARGET core_interface)
try_append_linker_flag("-Wl,-z,relro" TARGET hardening_interface) try_append_linker_flag("-Wl,-z,relro" TARGET core_interface)
try_append_linker_flag("-Wl,-z,now" TARGET hardening_interface) try_append_linker_flag("-Wl,-z,now" TARGET core_interface)
try_append_linker_flag("-Wl,-z,separate-code" TARGET hardening_interface) # TODO: This can be dropped once Bitcoin Core no longer supports
if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") # NetBSD 10.0 or if upstream fix is backported.
try_append_linker_flag("-Wl,-fixup_chains" TARGET hardening_interface) # NetBSD's dynamic linker ld.elf_so < 11.0 supports exactly 2
# `PT_LOAD` segments and binaries linked with `-z separate-code`
# have 4 `PT_LOAD` segments.
# Relevant discussions:
# - https://github.com/bitcoin/bitcoin/pull/28724#issuecomment-2589347934
# - https://mail-index.netbsd.org/tech-userlevel/2023/01/05/msg013666.html
if(CMAKE_SYSTEM_NAME STREQUAL "NetBSD" AND CMAKE_SYSTEM_VERSION VERSION_LESS 11.0)
try_append_linker_flag("-Wl,-z,noseparate-code" TARGET core_interface)
else()
try_append_linker_flag("-Wl,-z,separate-code" TARGET core_interface)
endif() endif()
if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
try_append_linker_flag("-Wl,-fixup_chains" TARGET core_interface)
endif() endif()
endif() endif()
@ -703,7 +710,6 @@ message("Cross compiling ....................... ${cross_status}")
message("C++ compiler .......................... ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}, ${CMAKE_CXX_COMPILER}") message("C++ compiler .......................... ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}, ${CMAKE_CXX_COMPILER}")
include(FlagsSummary) include(FlagsSummary)
flags_summary() flags_summary()
message("Attempt to harden executables ......... ${ENABLE_HARDENING}")
message("Treat compiler warnings as errors ..... ${WERROR}") message("Treat compiler warnings as errors ..... ${WERROR}")
message("Use ccache for compiling .............. ${WITH_CCACHE}") message("Use ccache for compiling .............. ${WITH_CCACHE}")
message("\n") message("\n")

View file

@ -77,7 +77,6 @@
"BUILD_UTIL_CHAINSTATE": "ON", "BUILD_UTIL_CHAINSTATE": "ON",
"BUILD_WALLET_TOOL": "ON", "BUILD_WALLET_TOOL": "ON",
"ENABLE_EXTERNAL_SIGNER": "ON", "ENABLE_EXTERNAL_SIGNER": "ON",
"ENABLE_HARDENING": "ON",
"ENABLE_WALLET": "ON", "ENABLE_WALLET": "ON",
"WARN_INCOMPATIBLE_BDB": "OFF", "WARN_INCOMPATIBLE_BDB": "OFF",
"WITH_BDB": "ON", "WITH_BDB": "ON",

View file

@ -190,6 +190,14 @@ ifneq ($(host),$(build))
$(package)_cmake_opts += -DCMAKE_SYSTEM_NAME=$($(host_os)_cmake_system_name) $(package)_cmake_opts += -DCMAKE_SYSTEM_NAME=$($(host_os)_cmake_system_name)
$(package)_cmake_opts += -DCMAKE_SYSTEM_VERSION=$($(host_os)_cmake_system_version) $(package)_cmake_opts += -DCMAKE_SYSTEM_VERSION=$($(host_os)_cmake_system_version)
$(package)_cmake_opts += -DCMAKE_SYSTEM_PROCESSOR=$(host_arch) $(package)_cmake_opts += -DCMAKE_SYSTEM_PROCESSOR=$(host_arch)
# Native packages cannot be used during cross-compiling. However,
# Qt still unconditionally tries to find them, which causes issues
# in some cases, such as when cross-compiling from macOS to Windows.
# Explicitly disable this unnecessary Qt behaviour.
$(package)_cmake_opts += -DCMAKE_DISABLE_FIND_PACKAGE_Libb2=TRUE
$(package)_cmake_opts += -DCMAKE_DISABLE_FIND_PACKAGE_WrapSystemDoubleConversion=TRUE
$(package)_cmake_opts += -DCMAKE_DISABLE_FIND_PACKAGE_WrapSystemMd4c=TRUE
$(package)_cmake_opts += -DCMAKE_DISABLE_FIND_PACKAGE_WrapZSTD=TRUE
endif endif
ifeq ($(host_os),darwin) ifeq ($(host_os),darwin)
$(package)_cmake_opts += -DCMAKE_INSTALL_NAME_TOOL=true $(package)_cmake_opts += -DCMAKE_INSTALL_NAME_TOOL=true

View file

@ -111,7 +111,7 @@ class PSBTTest(BitcoinTestFramework):
# Mine a transaction that credits the offline address # Mine a transaction that credits the offline address
offline_addr = offline_node.getnewaddress(address_type="bech32m") offline_addr = offline_node.getnewaddress(address_type="bech32m")
online_addr = w2.getnewaddress(address_type="bech32m") online_addr = w2.getnewaddress(address_type="bech32m")
wonline.importaddress(offline_addr, "", False) wonline.importaddress(offline_addr, label="", rescan=False)
mining_wallet = mining_node.get_wallet_rpc(self.default_wallet_name) mining_wallet = mining_node.get_wallet_rpc(self.default_wallet_name)
mining_wallet.sendtoaddress(address=offline_addr, amount=1.0) mining_wallet.sendtoaddress(address=offline_addr, amount=1.0)
self.generate(mining_node, nblocks=1, sync_fun=lambda: self.sync_all([online_node, mining_node])) self.generate(mining_node, nblocks=1, sync_fun=lambda: self.sync_all([online_node, mining_node]))
@ -312,9 +312,9 @@ class PSBTTest(BitcoinTestFramework):
wmulti = self.nodes[2].get_wallet_rpc('wmulti') wmulti = self.nodes[2].get_wallet_rpc('wmulti')
# Create all the addresses # Create all the addresses
p2sh = wmulti.addmultisigaddress(2, [pubkey0, pubkey1, pubkey2], "", "legacy")['address'] p2sh = wmulti.addmultisigaddress(2, [pubkey0, pubkey1, pubkey2], label="", address_type="legacy")["address"]
p2wsh = wmulti.addmultisigaddress(2, [pubkey0, pubkey1, pubkey2], "", "bech32")['address'] p2wsh = wmulti.addmultisigaddress(2, [pubkey0, pubkey1, pubkey2], label="", address_type="bech32")["address"]
p2sh_p2wsh = wmulti.addmultisigaddress(2, [pubkey0, pubkey1, pubkey2], "", "p2sh-segwit")['address'] p2sh_p2wsh = wmulti.addmultisigaddress(2, [pubkey0, pubkey1, pubkey2], label="", address_type="p2sh-segwit")["address"]
p2wpkh = self.nodes[1].getnewaddress("", "bech32") p2wpkh = self.nodes[1].getnewaddress("", "bech32")
p2pkh = self.nodes[1].getnewaddress("", "legacy") p2pkh = self.nodes[1].getnewaddress("", "legacy")
p2sh_p2wpkh = self.nodes[1].getnewaddress("", "p2sh-segwit") p2sh_p2wpkh = self.nodes[1].getnewaddress("", "p2sh-segwit")

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# Copyright (c) 2017-2022 The Bitcoin Core developers # Copyright (c) 2017-present The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying # Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php. # file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Class for bitcoind node under test""" """Class for bitcoind node under test"""
@ -209,7 +209,7 @@ class TestNode():
def __getattr__(self, name): def __getattr__(self, name):
"""Dispatches any unrecognised messages to the RPC connection or a CLI instance.""" """Dispatches any unrecognised messages to the RPC connection or a CLI instance."""
if self.use_cli: if self.use_cli:
return getattr(RPCOverloadWrapper(self.cli, True), name) return getattr(RPCOverloadWrapper(self.cli), name)
else: else:
assert self.rpc_connected and self.rpc is not None, self._node_msg("Error: no RPC connection") assert self.rpc_connected and self.rpc is not None, self._node_msg("Error: no RPC connection")
return getattr(RPCOverloadWrapper(self.rpc), name) return getattr(RPCOverloadWrapper(self.rpc), name)
@ -374,7 +374,7 @@ class TestNode():
def get_wallet_rpc(self, wallet_name): def get_wallet_rpc(self, wallet_name):
if self.use_cli: if self.use_cli:
return RPCOverloadWrapper(self.cli("-rpcwallet={}".format(wallet_name)), True) return RPCOverloadWrapper(self.cli("-rpcwallet={}".format(wallet_name)))
else: else:
assert self.rpc_connected and self.rpc, self._node_msg("RPC not connected") assert self.rpc_connected and self.rpc, self._node_msg("RPC not connected")
wallet_path = "wallet/{}".format(urllib.parse.quote(wallet_name)) wallet_path = "wallet/{}".format(urllib.parse.quote(wallet_name))
@ -925,17 +925,13 @@ class TestNodeCLI():
return cli_stdout.rstrip("\n") return cli_stdout.rstrip("\n")
class RPCOverloadWrapper(): class RPCOverloadWrapper():
def __init__(self, rpc, cli=False): def __init__(self, rpc):
self.rpc = rpc self.rpc = rpc
self.is_cli = cli
def __getattr__(self, name): def __getattr__(self, name):
return getattr(self.rpc, name) return getattr(self.rpc, name)
def createwallet_passthrough(self, *args, **kwargs): def importprivkey(self, privkey, *, label=None, rescan=None):
return self.__getattr__("createwallet")(*args, **kwargs)
def importprivkey(self, privkey, label=None, rescan=None):
wallet_info = self.getwalletinfo() wallet_info = self.getwalletinfo()
if 'descriptors' not in wallet_info or ('descriptors' in wallet_info and not wallet_info['descriptors']): if 'descriptors' not in wallet_info or ('descriptors' in wallet_info and not wallet_info['descriptors']):
return self.__getattr__('importprivkey')(privkey, label, rescan) return self.__getattr__('importprivkey')(privkey, label, rescan)
@ -943,13 +939,13 @@ class RPCOverloadWrapper():
req = [{ req = [{
'desc': desc, 'desc': desc,
'timestamp': 0 if rescan else 'now', 'timestamp': 0 if rescan else 'now',
'label': label if label else '' 'label': label if label else '',
}] }]
import_res = self.importdescriptors(req) import_res = self.importdescriptors(req)
if not import_res[0]['success']: if not import_res[0]['success']:
raise JSONRPCException(import_res[0]['error']) raise JSONRPCException(import_res[0]['error'])
def addmultisigaddress(self, nrequired, keys, label=None, address_type=None): def addmultisigaddress(self, nrequired, keys, *, label=None, address_type=None):
wallet_info = self.getwalletinfo() wallet_info = self.getwalletinfo()
if 'descriptors' not in wallet_info or ('descriptors' in wallet_info and not wallet_info['descriptors']): if 'descriptors' not in wallet_info or ('descriptors' in wallet_info and not wallet_info['descriptors']):
return self.__getattr__('addmultisigaddress')(nrequired, keys, label, address_type) return self.__getattr__('addmultisigaddress')(nrequired, keys, label, address_type)
@ -957,14 +953,14 @@ class RPCOverloadWrapper():
req = [{ req = [{
'desc': cms['descriptor'], 'desc': cms['descriptor'],
'timestamp': 0, 'timestamp': 0,
'label': label if label else '' 'label': label if label else '',
}] }]
import_res = self.importdescriptors(req) import_res = self.importdescriptors(req)
if not import_res[0]['success']: if not import_res[0]['success']:
raise JSONRPCException(import_res[0]['error']) raise JSONRPCException(import_res[0]['error'])
return cms return cms
def importpubkey(self, pubkey, label=None, rescan=None): def importpubkey(self, pubkey, *, label=None, rescan=None):
wallet_info = self.getwalletinfo() wallet_info = self.getwalletinfo()
if 'descriptors' not in wallet_info or ('descriptors' in wallet_info and not wallet_info['descriptors']): if 'descriptors' not in wallet_info or ('descriptors' in wallet_info and not wallet_info['descriptors']):
return self.__getattr__('importpubkey')(pubkey, label, rescan) return self.__getattr__('importpubkey')(pubkey, label, rescan)
@ -972,13 +968,13 @@ class RPCOverloadWrapper():
req = [{ req = [{
'desc': desc, 'desc': desc,
'timestamp': 0 if rescan else 'now', 'timestamp': 0 if rescan else 'now',
'label': label if label else '' 'label': label if label else '',
}] }]
import_res = self.importdescriptors(req) import_res = self.importdescriptors(req)
if not import_res[0]['success']: if not import_res[0]['success']:
raise JSONRPCException(import_res[0]['error']) raise JSONRPCException(import_res[0]['error'])
def importaddress(self, address, label=None, rescan=None, p2sh=None): def importaddress(self, address, *, label=None, rescan=None, p2sh=None):
wallet_info = self.getwalletinfo() wallet_info = self.getwalletinfo()
if 'descriptors' not in wallet_info or ('descriptors' in wallet_info and not wallet_info['descriptors']): if 'descriptors' not in wallet_info or ('descriptors' in wallet_info and not wallet_info['descriptors']):
return self.__getattr__('importaddress')(address, label, rescan, p2sh) return self.__getattr__('importaddress')(address, label, rescan, p2sh)
@ -992,13 +988,13 @@ class RPCOverloadWrapper():
reqs = [{ reqs = [{
'desc': desc, 'desc': desc,
'timestamp': 0 if rescan else 'now', 'timestamp': 0 if rescan else 'now',
'label': label if label else '' 'label': label if label else '',
}] }]
if is_hex and p2sh: if is_hex and p2sh:
reqs.append({ reqs.append({
'desc': descsum_create('p2sh(raw(' + address + '))'), 'desc': descsum_create('p2sh(raw(' + address + '))'),
'timestamp': 0 if rescan else 'now', 'timestamp': 0 if rescan else 'now',
'label': label if label else '' 'label': label if label else '',
}) })
import_res = self.importdescriptors(reqs) import_res = self.importdescriptors(reqs)
for res in import_res: for res in import_res:

View file

@ -344,7 +344,7 @@ class AddressTypeTest(BitcoinTestFramework):
self.test_address(3, self.nodes[3].getrawchangeaddress(), multisig=False, typ='bech32') self.test_address(3, self.nodes[3].getrawchangeaddress(), multisig=False, typ='bech32')
self.log.info('test invalid address type arguments') self.log.info('test invalid address type arguments')
assert_raises_rpc_error(-5, "Unknown address type ''", self.nodes[3].addmultisigaddress, 2, [compressed_1, compressed_2], None, '') assert_raises_rpc_error(-5, "Unknown address type ''", self.nodes[3].addmultisigaddress, 2, [compressed_1, compressed_2], address_type="")
assert_raises_rpc_error(-5, "Unknown address type ''", self.nodes[3].getnewaddress, None, '') assert_raises_rpc_error(-5, "Unknown address type ''", self.nodes[3].getnewaddress, None, '')
assert_raises_rpc_error(-5, "Unknown address type ''", self.nodes[3].getrawchangeaddress, '') assert_raises_rpc_error(-5, "Unknown address type ''", self.nodes[3].getrawchangeaddress, '')
assert_raises_rpc_error(-5, "Unknown address type 'bech23'", self.nodes[3].getrawchangeaddress, 'bech23') assert_raises_rpc_error(-5, "Unknown address type 'bech23'", self.nodes[3].getrawchangeaddress, 'bech23')

View file

@ -26,11 +26,12 @@ from test_framework.util import (
assert_raises_rpc_error, assert_raises_rpc_error,
) )
LAST_KEYPOOL_INDEX = 9 # Index of the last derived address with the keypool size of 10
class BackwardsCompatibilityTest(BitcoinTestFramework): class BackwardsCompatibilityTest(BitcoinTestFramework):
def set_test_params(self): def set_test_params(self):
self.setup_clean_chain = True self.setup_clean_chain = True
self.num_nodes = 10 self.num_nodes = 8
# Add new version after each release: # Add new version after each release:
self.extra_args = [ self.extra_args = [
["-addresstype=bech32", "-whitelist=noban@127.0.0.1"], # Pre-release: use to mine blocks. noban for immediate tx relay ["-addresstype=bech32", "-whitelist=noban@127.0.0.1"], # Pre-release: use to mine blocks. noban for immediate tx relay
@ -38,11 +39,9 @@ class BackwardsCompatibilityTest(BitcoinTestFramework):
["-nowallet", "-walletrbf=1", "-addresstype=bech32", "-whitelist=noban@127.0.0.1"], # v25.0 ["-nowallet", "-walletrbf=1", "-addresstype=bech32", "-whitelist=noban@127.0.0.1"], # v25.0
["-nowallet", "-walletrbf=1", "-addresstype=bech32", "-whitelist=noban@127.0.0.1"], # v24.0.1 ["-nowallet", "-walletrbf=1", "-addresstype=bech32", "-whitelist=noban@127.0.0.1"], # v24.0.1
["-nowallet", "-walletrbf=1", "-addresstype=bech32", "-whitelist=noban@127.0.0.1"], # v23.0 ["-nowallet", "-walletrbf=1", "-addresstype=bech32", "-whitelist=noban@127.0.0.1"], # v23.0
["-nowallet", "-walletrbf=1", "-addresstype=bech32", "-whitelist=noban@127.0.0.1"], # v22.0 ["-nowallet", "-walletrbf=1", "-addresstype=bech32", "-whitelist=noban@127.0.0.1", f"-keypool={LAST_KEYPOOL_INDEX + 1}"], # v22.0
["-nowallet", "-walletrbf=1", "-addresstype=bech32", "-whitelist=noban@127.0.0.1"], # v0.21.0 ["-nowallet", "-walletrbf=1", "-addresstype=bech32", "-whitelist=noban@127.0.0.1"], # v0.21.0
["-nowallet", "-walletrbf=1", "-addresstype=bech32", "-whitelist=noban@127.0.0.1"], # v0.20.1 ["-nowallet", "-walletrbf=1", "-addresstype=bech32", "-whitelist=noban@127.0.0.1"], # v0.20.1
["-nowallet", "-walletrbf=1", "-addresstype=bech32", "-whitelist=noban@127.0.0.1"], # v0.19.1
["-nowallet", "-walletrbf=1", "-addresstype=bech32", "-whitelist=127.0.0.1"], # v0.18.1
] ]
self.wallet_names = [self.default_wallet_name] self.wallet_names = [self.default_wallet_name]
@ -60,8 +59,6 @@ class BackwardsCompatibilityTest(BitcoinTestFramework):
220000, 220000,
210000, 210000,
200100, 200100,
190100,
180100,
]) ])
self.start_nodes() self.start_nodes()
@ -85,21 +82,98 @@ class BackwardsCompatibilityTest(BitcoinTestFramework):
node_major, _, _ = self.split_version(node) node_major, _, _ = self.split_version(node)
return node_major >= major return node_major >= major
def test_v22_inactivehdchain_path(self):
self.log.info("Testing inactive hd chain bad derivation path cleanup")
# 0.21.x and 22.x would both produce bad derivation paths when topping up an inactive hd chain
# Make sure that this is being automatically cleaned up by migration
node_master = self.nodes[1]
node_v22 = self.nodes[self.num_nodes - 5]
wallet_name = "bad_deriv_path"
node_v22.createwallet(wallet_name=wallet_name, descriptors=False)
bad_deriv_wallet = node_v22.get_wallet_rpc(wallet_name)
# Make a dump of the wallet to get an unused address
dump_path = node_v22.wallets_path / f"{wallet_name}.dump"
bad_deriv_wallet.dumpwallet(dump_path)
addr = None
seed = None
with open(dump_path, encoding="utf8") as f:
for line in f:
if f"hdkeypath=m/0'/0'/{LAST_KEYPOOL_INDEX}'" in line:
addr = line.split(" ")[4].split("=")[1]
elif " hdseed=1 " in line:
seed = line.split(" ")[0]
assert addr is not None
assert seed is not None
# Rotate seed and unload
bad_deriv_wallet.sethdseed()
bad_deriv_wallet.unloadwallet()
# Receive at addr to trigger inactive chain topup on next load
self.nodes[0].sendtoaddress(addr, 1)
self.generate(self.nodes[0], 1, sync_fun=self.no_op)
self.sync_all(nodes=[self.nodes[0], node_master, node_v22])
node_v22.loadwallet(wallet_name)
# Dump again to find bad hd keypath
bad_deriv_path = f"m/0'/0'/{LAST_KEYPOOL_INDEX}'/0'/0'/{LAST_KEYPOOL_INDEX + 1}'"
good_deriv_path = f"m/0h/0h/{LAST_KEYPOOL_INDEX + 1}h"
os.unlink(dump_path)
bad_deriv_wallet.dumpwallet(dump_path)
bad_path_addr = None
with open(dump_path, encoding="utf8") as f:
for line in f:
if f"hdkeypath={bad_deriv_path}" in line:
bad_path_addr = line.split(" ")[4].split("=")[1]
assert bad_path_addr is not None
assert_equal(bad_deriv_wallet.getaddressinfo(bad_path_addr)["hdkeypath"], bad_deriv_path)
# Verify that this bad derivation path addr is actually at m/0'/0'/10' by making a new wallet with the same seed but larger keypool
node_v22.createwallet(wallet_name="path_verify", descriptors=False, blank=True)
verify_wallet = node_v22.get_wallet_rpc("path_verify")
verify_wallet.sethdseed(True, seed)
# Bad addr is after keypool, so need to generate it by refilling
verify_wallet.keypoolrefill(LAST_KEYPOOL_INDEX + 2)
assert_equal(verify_wallet.getaddressinfo(bad_path_addr)["hdkeypath"], good_deriv_path.replace("h", "'"))
# Migrate with master
# Since all keymeta records are now deleted after migration, the derivation path
# should now be correct as it is derived on-the-fly from the inactive hd chain's descriptor
backup_path = node_v22.wallets_path / f"{wallet_name}.bak"
bad_deriv_wallet.backupwallet(backup_path)
wallet_dir_master = os.path.join(node_master.wallets_path, wallet_name)
os.makedirs(wallet_dir_master, exist_ok=True)
shutil.copy(backup_path, os.path.join(wallet_dir_master, "wallet.dat"))
node_master.migratewallet(wallet_name)
bad_deriv_wallet_master = node_master.get_wallet_rpc(wallet_name)
assert_equal(bad_deriv_wallet_master.getaddressinfo(bad_path_addr)["hdkeypath"], good_deriv_path)
bad_deriv_wallet_master.unloadwallet()
# If we have sqlite3, verify that there are no keymeta records
try:
import sqlite3
wallet_db = node_master.wallets_path / wallet_name / "wallet.dat"
conn = sqlite3.connect(wallet_db)
with conn:
# Retrieve all records that have the "keymeta" prefix. The remaining key data varies for each record.
keymeta_rec = conn.execute("SELECT value FROM main where key >= x'076b65796d657461' AND key < x'076b65796d657462'").fetchone()
assert_equal(keymeta_rec, None)
conn.close()
except ImportError:
self.log.warning("sqlite3 module not available, skipping lack of keymeta records check")
def run_test(self): def run_test(self):
node_miner = self.nodes[0] node_miner = self.nodes[0]
node_master = self.nodes[1] node_master = self.nodes[1]
node_v21 = self.nodes[self.num_nodes - 4] node_v21 = self.nodes[self.num_nodes - 2]
node_v18 = self.nodes[self.num_nodes - 1] node_v20 = self.nodes[self.num_nodes - 1] # bdb only
legacy_nodes = self.nodes[2:] # Nodes that support legacy wallets legacy_nodes = self.nodes[2:] # Nodes that support legacy wallets
legacy_only_nodes = self.nodes[-3:] # Nodes that only support legacy wallets descriptors_nodes = self.nodes[2:-1] # Nodes that support descriptor wallets
descriptors_nodes = self.nodes[2:-3] # Nodes that support descriptor wallets
self.generatetoaddress(node_miner, COINBASE_MATURITY + 1, node_miner.getnewaddress()) self.generatetoaddress(node_miner, COINBASE_MATURITY + 1, node_miner.getnewaddress())
# Sanity check the test framework: # Sanity check the test framework:
res = node_v18.getblockchaininfo() assert_equal(node_v20.getblockchaininfo()["blocks"], COINBASE_MATURITY + 1)
assert_equal(res['blocks'], COINBASE_MATURITY + 1)
self.log.info("Test wallet backwards compatibility...") self.log.info("Test wallet backwards compatibility...")
# Create a number of wallets and open them in older versions: # Create a number of wallets and open them in older versions:
@ -206,13 +280,11 @@ class BackwardsCompatibilityTest(BitcoinTestFramework):
) )
# Check that descriptor wallets don't work on legacy only nodes # Check that descriptor wallets don't work on legacy only nodes
self.log.info("Test descriptor wallet incompatibility on:") self.log.info("Test descriptor wallet incompatibility on v0.20")
for node in legacy_only_nodes:
self.log.info(f"- {node.version}")
# Descriptor wallets appear to be corrupted wallets to old software # Descriptor wallets appear to be corrupted wallets to old software
assert self.major_version_less_than(node, 21) assert self.major_version_equals(node_v20, 20)
for wallet_name in ["w1", "w2", "w3"]: for wallet_name in ["w1", "w2", "w3"]:
assert_raises_rpc_error(-4, "Wallet file verification failed: wallet.dat corrupt, salvage failed", node.loadwallet, wallet_name) assert_raises_rpc_error(-4, "Wallet file verification failed: wallet.dat corrupt, salvage failed", node_v20.loadwallet, wallet_name)
# w1 cannot be opened by 0.21 since it contains a taproot descriptor # w1 cannot be opened by 0.21 since it contains a taproot descriptor
self.log.info("Test that 0.21 cannot open wallet containing tr() descriptors") self.log.info("Test that 0.21 cannot open wallet containing tr() descriptors")
@ -308,5 +380,7 @@ class BackwardsCompatibilityTest(BitcoinTestFramework):
# Legacy wallets are no longer supported. Trying to load these should result in an error # Legacy wallets are no longer supported. Trying to load these should result in an error
assert_raises_rpc_error(-18, "The wallet appears to be a Legacy wallet, please use the wallet migration tool (migratewallet RPC)", node_master.restorewallet, wallet_name, backup_path) assert_raises_rpc_error(-18, "The wallet appears to be a Legacy wallet, please use the wallet migration tool (migratewallet RPC)", node_master.restorewallet, wallet_name, backup_path)
self.test_v22_inactivehdchain_path()
if __name__ == '__main__': if __name__ == '__main__':
BackwardsCompatibilityTest(__file__).main() BackwardsCompatibilityTest(__file__).main()

View file

@ -192,7 +192,7 @@ class RawTransactionsTest(BitcoinTestFramework):
watchonly_address = self.nodes[0].getnewaddress() watchonly_address = self.nodes[0].getnewaddress()
watchonly_pubkey = self.nodes[0].getaddressinfo(watchonly_address)["pubkey"] watchonly_pubkey = self.nodes[0].getaddressinfo(watchonly_address)["pubkey"]
self.watchonly_amount = Decimal(200) self.watchonly_amount = Decimal(200)
wwatch.importpubkey(watchonly_pubkey, "", True) wwatch.importpubkey(watchonly_pubkey, label="", rescan=True)
self.watchonly_utxo = self.create_outpoints(self.nodes[0], outputs=[{watchonly_address: self.watchonly_amount}])[0] self.watchonly_utxo = self.create_outpoints(self.nodes[0], outputs=[{watchonly_address: self.watchonly_amount}])[0]
# Lock UTXO so nodes[0] doesn't accidentally spend it # Lock UTXO so nodes[0] doesn't accidentally spend it

View file

@ -49,7 +49,7 @@ class WalletLabelsTest(BitcoinTestFramework):
assert_equal(response[0]['error']['message'], "Invalid label name") assert_equal(response[0]['error']['message'], "Invalid label name")
for rpc_call in rpc_calls: for rpc_call in rpc_calls:
assert_raises_rpc_error(-11, "Invalid label name", *rpc_call, "*") assert_raises_rpc_error(-11, "Invalid label name", *rpc_call, label="*")
def run_test(self): def run_test(self):
# Check that there's no UTXO on the node # Check that there's no UTXO on the node

View file

@ -24,34 +24,7 @@ SHA256_SUMS = {
"d86fc90824a85c38b25c8488115178d5785dbc975f5ff674f9f5716bc8ad6e65": {"tag": "v0.14.3", "tarball": "bitcoin-0.14.3-arm-linux-gnueabihf.tar.gz"}, "d86fc90824a85c38b25c8488115178d5785dbc975f5ff674f9f5716bc8ad6e65": {"tag": "v0.14.3", "tarball": "bitcoin-0.14.3-arm-linux-gnueabihf.tar.gz"},
"1b0a7408c050e3d09a8be8e21e183ef7ee570385dc41216698cc3ab392a484e7": {"tag": "v0.14.3", "tarball": "bitcoin-0.14.3-osx64.tar.gz"}, "1b0a7408c050e3d09a8be8e21e183ef7ee570385dc41216698cc3ab392a484e7": {"tag": "v0.14.3", "tarball": "bitcoin-0.14.3-osx64.tar.gz"},
"706e0472dbc933ed2757650d54cbcd780fd3829ebf8f609b32780c7eedebdbc9": {"tag": "v0.14.3", "tarball": "bitcoin-0.14.3-x86_64-linux-gnu.tar.gz"}, "706e0472dbc933ed2757650d54cbcd780fd3829ebf8f609b32780c7eedebdbc9": {"tag": "v0.14.3", "tarball": "bitcoin-0.14.3-x86_64-linux-gnu.tar.gz"},
#
"d40f18b4e43c6e6370ef7db9131f584fbb137276ec2e3dba67a4b267f81cb644": {"tag": "v0.15.2", "tarball": "bitcoin-0.15.2-aarch64-linux-gnu.tar.gz"},
"54fb877a148a6ad189a1e1ab1ff8b11181e58ff2aaf430da55b3fd46ae549a6b": {"tag": "v0.15.2", "tarball": "bitcoin-0.15.2-arm-linux-gnueabihf.tar.gz"},
"87e9340ff3d382d543b2b69112376077f0c8b4f7450d372e83b68f5a1e22b2df": {"tag": "v0.15.2", "tarball": "bitcoin-0.15.2-osx64.tar.gz"},
"566be44190fd76daa01f13d428939dadfb8e3daacefc8fa17f433cad28f73bd5": {"tag": "v0.15.2", "tarball": "bitcoin-0.15.2-x86_64-linux-gnu.tar.gz"},
#
"0768c6c15caffbaca6524824c9563b42c24f70633c681c2744649158aa3fd484": {"tag": "v0.16.3", "tarball": "bitcoin-0.16.3-aarch64-linux-gnu.tar.gz"},
"fb2818069854a6ad20ea03b28b55dbd35d8b1f7d453e90b83eace5d0098a2a87": {"tag": "v0.16.3", "tarball": "bitcoin-0.16.3-arm-linux-gnueabihf.tar.gz"},
"78c3bff3b619a19aed575961ea43cc9e142959218835cf51aede7f0b764fc25d": {"tag": "v0.16.3", "tarball": "bitcoin-0.16.3-osx64.tar.gz"},
"5d422a9d544742bc0df12427383f9c2517433ce7b58cf672b9a9b17c2ef51e4f": {"tag": "v0.16.3", "tarball": "bitcoin-0.16.3-x86_64-linux-gnu.tar.gz"},
#
"5a6b35d1a348a402f2d2d6ab5aed653a1a1f13bc63aaaf51605e3501b0733b7a": {"tag": "v0.17.2", "tarball": "bitcoin-0.17.2-aarch64-linux-gnu.tar.gz"},
"d1913a5d19c8e8da4a67d1bd5205d03c8614dfd2e02bba2fe3087476643a729e": {"tag": "v0.17.2", "tarball": "bitcoin-0.17.2-arm-linux-gnueabihf.tar.gz"},
"a783ba20706dbfd5b47fbedf42165fce70fbbc7d78003305d964f6b3da14887f": {"tag": "v0.17.2", "tarball": "bitcoin-0.17.2-osx64.tar.gz"},
"943f9362b9f11130177839116f48f809d83478b4c28591d486ee9a7e35179da6": {"tag": "v0.17.2", "tarball": "bitcoin-0.17.2-x86_64-linux-gnu.tar.gz"},
#
"88f343af72803b851c7da13874cc5525026b0b55e63e1b5e1298390c4688adc6": {"tag": "v0.18.1", "tarball": "bitcoin-0.18.1-aarch64-linux-gnu.tar.gz"},
"cc7d483e4b20c5dabd4dcaf304965214cf4934bcc029ca99cbc9af00d3771a1f": {"tag": "v0.18.1", "tarball": "bitcoin-0.18.1-arm-linux-gnueabihf.tar.gz"},
"b7bbcee7a7540f711b171d6981f939ca8482005fde22689bc016596d80548bb1": {"tag": "v0.18.1", "tarball": "bitcoin-0.18.1-osx64.tar.gz"},
"425ee5ec631ae8da71ebc1c3f5c0269c627cf459379b9b030f047107a28e3ef8": {"tag": "v0.18.1", "tarball": "bitcoin-0.18.1-riscv64-linux-gnu.tar.gz"},
"600d1db5e751fa85903e935a01a74f5cc57e1e7473c15fd3e17ed21e202cfe5a": {"tag": "v0.18.1", "tarball": "bitcoin-0.18.1-x86_64-linux-gnu.tar.gz"},
#
"3a80431717842672df682bdb619e66523b59541483297772a7969413be3502ff": {"tag": "v0.19.1", "tarball": "bitcoin-0.19.1-aarch64-linux-gnu.tar.gz"},
"657f28213823d240dd3324d14829702f9ad6f0710f8bdd1c379cb3c447197f48": {"tag": "v0.19.1", "tarball": "bitcoin-0.19.1-arm-linux-gnueabihf.tar.gz"},
"1ae1b87de26487075cd2fd22e0d4ead87d969bd55c44f2f1d873ecdc6147ebb3": {"tag": "v0.19.1", "tarball": "bitcoin-0.19.1-osx64.tar.gz"},
"aa7a9563b48aa79252c8e7b6a41c07a5441bd9f14c5e4562cc72720ea6cb0ee5": {"tag": "v0.19.1", "tarball": "bitcoin-0.19.1-riscv64-linux-gnu.tar.gz"},
"5fcac9416e486d4960e1a946145566350ca670f9aaba99de6542080851122e4c": {"tag": "v0.19.1", "tarball": "bitcoin-0.19.1-x86_64-linux-gnu.tar.gz"},
#
"60c93e3462c303eb080be7cf623f1a7684b37fd47a018ad3848bc23e13c84e1c": {"tag": "v0.20.1", "tarball": "bitcoin-0.20.1-aarch64-linux-gnu.tar.gz"}, "60c93e3462c303eb080be7cf623f1a7684b37fd47a018ad3848bc23e13c84e1c": {"tag": "v0.20.1", "tarball": "bitcoin-0.20.1-aarch64-linux-gnu.tar.gz"},
"55b577e0fb306fb429d4be6c9316607753e8543e5946b542d75d876a2f08654c": {"tag": "v0.20.1", "tarball": "bitcoin-0.20.1-arm-linux-gnueabihf.tar.gz"}, "55b577e0fb306fb429d4be6c9316607753e8543e5946b542d75d876a2f08654c": {"tag": "v0.20.1", "tarball": "bitcoin-0.20.1-arm-linux-gnueabihf.tar.gz"},
"b9024dde373ea7dad707363e07ec7e265383204127539ae0c234bff3a61da0d1": {"tag": "v0.20.1", "tarball": "bitcoin-0.20.1-osx64.tar.gz"}, "b9024dde373ea7dad707363e07ec7e265383204127539ae0c234bff3a61da0d1": {"tag": "v0.20.1", "tarball": "bitcoin-0.20.1-osx64.tar.gz"},

View file

@ -1,6 +1,6 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# Copyright 2014 BitPay Inc. # Copyright 2014 BitPay Inc.
# Copyright 2016-2017 The Bitcoin Core developers # Copyright 2016-present The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying # Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php. # file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test framework for bitcoin utils. """Test framework for bitcoin utils.
@ -155,15 +155,16 @@ def bctest(testDir, testObj, buildenv):
if "error_txt" in testObj: if "error_txt" in testObj:
want_error = testObj["error_txt"] want_error = testObj["error_txt"]
# Compare error text # A partial match instead of an exact match makes writing tests easier
# TODO: ideally, we'd compare the strings exactly and also assert # and should be sufficient.
# That stderr is empty if no errors are expected. However, bitcoin-tx
# emits DISPLAY errors when running as a windows application on
# linux through wine. Just assert that the expected error text appears
# somewhere in stderr.
if want_error not in res.stderr: if want_error not in res.stderr:
logging.error(f"Error mismatch:\nExpected: {want_error}\nReceived: {res.stderr.rstrip()}\nres: {str(res)}") logging.error(f"Error mismatch:\nExpected: {want_error}\nReceived: {res.stderr.rstrip()}\nres: {str(res)}")
raise Exception raise Exception
else:
if res.stderr:
logging.error(f"Unexpected error received: {res.stderr.rstrip()}\nres: {str(res)}")
raise Exception
def parse_output(a, fmt): def parse_output(a, fmt):
"""Parse the output according to specified format. """Parse the output according to specified format.