mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-01-22 00:00:55 +01:00
Compare commits
30 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d3a3522560 | ||
|
|
b01a5bea7d | ||
|
|
1343f43518 | ||
|
|
db244c6342 | ||
|
|
0dfbe96583 | ||
|
|
d8340dd03b | ||
|
|
9795e0ba5e | ||
|
|
248d14cb63 | ||
|
|
e78961db59 | ||
|
|
1416d09cba | ||
|
|
9077f214f5 | ||
|
|
dccacf0bf7 | ||
|
|
43596499b2 | ||
|
|
805f98b79a | ||
|
|
cb5512da23 | ||
|
|
01f8ee48ef | ||
|
|
1c98029b39 | ||
|
|
77979e0172 | ||
|
|
67b6d99aea | ||
|
|
defdc15023 | ||
|
|
7f1357de51 | ||
|
|
0db69a3d50 | ||
|
|
0df8f98d65 | ||
|
|
66b2b109eb | ||
|
|
a537cb0b87 | ||
|
|
c2e9214eff | ||
|
|
3116ccd790 | ||
|
|
89a5a416de | ||
|
|
b36dff9fa8 | ||
|
|
8af2d2f762 |
26
.cirrus.yml
26
.cirrus.yml
@@ -189,14 +189,12 @@ task:
|
||||
task:
|
||||
name: 'ARM [unit tests, no functional tests] [bullseye]'
|
||||
<< : *GLOBAL_TASK_TEMPLATE
|
||||
arm_container:
|
||||
image: debian:bullseye
|
||||
cpu: 2
|
||||
memory: 8G
|
||||
container:
|
||||
docker_arguments:
|
||||
CI_IMAGE_NAME_TAG: debian:bullseye
|
||||
FILE_ENV: "./ci/test/00_setup_env_arm.sh"
|
||||
env:
|
||||
<< : *CIRRUS_EPHEMERAL_WORKER_TEMPLATE_ENV
|
||||
FILE_ENV: "./ci/test/00_setup_env_arm.sh"
|
||||
QEMU_USER_CMD: "" # Disable qemu and run the test natively
|
||||
|
||||
task:
|
||||
name: 'Win64 [unit tests, no gui tests, no boost::process, no functional tests] [jammy]'
|
||||
@@ -322,19 +320,3 @@ task:
|
||||
CI_USE_APT_INSTALL: "no"
|
||||
PACKAGE_MANAGER_INSTALL: "echo" # Nothing to do
|
||||
FILE_ENV: "./ci/test/00_setup_env_mac_native_arm64.sh"
|
||||
|
||||
task:
|
||||
name: 'ARM64 Android APK [focal]'
|
||||
<< : *BASE_TEMPLATE
|
||||
android_sdk_cache:
|
||||
folder: "depends/SDKs/android"
|
||||
fingerprint_key: "ANDROID_API_LEVEL=28 ANDROID_BUILD_TOOLS_VERSION=28.0.3 ANDROID_NDK_VERSION=23.2.8568313"
|
||||
depends_sources_cache:
|
||||
folder: "depends/sources"
|
||||
fingerprint_script: git rev-list -1 HEAD ./depends
|
||||
<< : *MAIN_TEMPLATE
|
||||
container:
|
||||
image: ubuntu:focal
|
||||
env:
|
||||
<< : *CIRRUS_EPHEMERAL_WORKER_TEMPLATE_ENV
|
||||
FILE_ENV: "./ci/test/00_setup_env_android.sh"
|
||||
|
||||
@@ -31,7 +31,9 @@ if [ -z "$DANGER_RUN_CI_ON_HOST" ]; then
|
||||
|
||||
if [ -n "${RESTART_CI_DOCKER_BEFORE_RUN}" ] ; then
|
||||
echo "Restart docker before run to stop and clear all containers started with --rm"
|
||||
systemctl restart docker
|
||||
podman container stop --all # Similar to "systemctl restart docker"
|
||||
echo "Prune all dangling images"
|
||||
docker image prune --force
|
||||
fi
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
AC_PREREQ([2.69])
|
||||
define(_CLIENT_VERSION_MAJOR, 24)
|
||||
define(_CLIENT_VERSION_MINOR, 1)
|
||||
define(_CLIENT_VERSION_MINOR, 2)
|
||||
define(_CLIENT_VERSION_BUILD, 0)
|
||||
define(_CLIENT_VERSION_RC, 3)
|
||||
define(_CLIENT_VERSION_RC, 0)
|
||||
define(_CLIENT_VERSION_IS_RELEASE, true)
|
||||
define(_COPYRIGHT_YEAR, 2022)
|
||||
define(_COPYRIGHT_HOLDERS,[The %s developers])
|
||||
|
||||
@@ -22,6 +22,8 @@ $(package)_patches += rcc_hardcode_timestamp.patch
|
||||
$(package)_patches += duplicate_lcqpafonts.patch
|
||||
$(package)_patches += fast_fixed_dtoa_no_optimize.patch
|
||||
$(package)_patches += guix_cross_lib_path.patch
|
||||
$(package)_patches += fix-macos-linker.patch
|
||||
$(package)_patches += memory_resource.patch
|
||||
|
||||
$(package)_qttranslations_file_name=qttranslations-$($(package)_suffix)
|
||||
$(package)_qttranslations_sha256_hash=c92af4171397a0ed272330b4fa0669790fcac8d050b07c8b8cc565ebeba6735e
|
||||
@@ -231,6 +233,7 @@ endef
|
||||
define $(package)_preprocess_cmds
|
||||
cp $($(package)_patch_dir)/qt.pro qt.pro && \
|
||||
cp $($(package)_patch_dir)/qttools_src.pro qttools/src/src.pro && \
|
||||
patch -p1 -i $($(package)_patch_dir)/fix-macos-linker.patch && \
|
||||
patch -p1 -i $($(package)_patch_dir)/dont_hardcode_pwd.patch && \
|
||||
patch -p1 -i $($(package)_patch_dir)/fix_qt_pkgconfig.patch && \
|
||||
patch -p1 -i $($(package)_patch_dir)/fix_android_jni_static.patch && \
|
||||
@@ -239,6 +242,7 @@ define $(package)_preprocess_cmds
|
||||
patch -p1 -i $($(package)_patch_dir)/qtbase-moc-ignore-gcc-macro.patch && \
|
||||
patch -p1 -i $($(package)_patch_dir)/fix_montery_include.patch && \
|
||||
patch -p1 -i $($(package)_patch_dir)/use_android_ndk23.patch && \
|
||||
patch -p1 -i $($(package)_patch_dir)/memory_resource.patch && \
|
||||
patch -p1 -i $($(package)_patch_dir)/rcc_hardcode_timestamp.patch && \
|
||||
patch -p1 -i $($(package)_patch_dir)/duplicate_lcqpafonts.patch && \
|
||||
patch -p1 -i $($(package)_patch_dir)/fast_fixed_dtoa_no_optimize.patch && \
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package=xcb_proto
|
||||
$(package)_version=1.14.1
|
||||
$(package)_version=1.15.2
|
||||
$(package)_download_path=https://xorg.freedesktop.org/archive/individual/proto
|
||||
$(package)_file_name=xcb-proto-$($(package)_version).tar.xz
|
||||
$(package)_sha256_hash=f04add9a972ac334ea11d9d7eb4fc7f8883835da3e4859c9afa971efdf57fcc3
|
||||
$(package)_sha256_hash=7072beb1f680a2fe3f9e535b797c146d22528990c72f63ddb49d2f350a3653ed
|
||||
|
||||
define $(package)_config_cmds
|
||||
$($(package)_autoconf)
|
||||
|
||||
55
depends/patches/qt/fix-macos-linker.patch
Normal file
55
depends/patches/qt/fix-macos-linker.patch
Normal file
@@ -0,0 +1,55 @@
|
||||
qmake: Don't error out if QMAKE_DEFAULT_LIBDIRS is empty on macOS
|
||||
|
||||
The new linker in Xcode 15 doesn't provide any default linker or
|
||||
framework paths when requested via -v, but still seems to use the
|
||||
default paths documented in the ld man page.
|
||||
|
||||
We trust that linker will do the right thing, even if we don't
|
||||
know of its default linker paths.
|
||||
|
||||
We also need to opt out of the default fallback logic to
|
||||
set the libdirs to /lib and /usr/lib.
|
||||
|
||||
This may result in UnixMakefileGenerator::findLibraries finding
|
||||
different libraries than expected, if additional paths are
|
||||
passed with -L, which will then take precedence for qmake,
|
||||
even if the linker itself will use the library from the
|
||||
SDK's default paths. This should hopefully not be an issue
|
||||
in practice, as we don't turn -lFoo into absolute paths in
|
||||
qmake, so the only risk is that we're picking up the wrong
|
||||
prl files and adding additional dependencies that the lib
|
||||
in the SDK doesn't have.
|
||||
|
||||
Upstream commits:
|
||||
- Qt 5.15.16: Not yet publicly available.
|
||||
- Qt dev: cdf64b0e47115cc473e1afd1472b4b09e130b2a5
|
||||
|
||||
For other Qt branches see
|
||||
https://codereview.qt-project.org/q/I2347b26e2df0828471373b0e15b8c9089274c65d
|
||||
|
||||
--- old/qtbase/mkspecs/features/toolchain.prf
|
||||
+++ new/qtbase/mkspecs/features/toolchain.prf
|
||||
@@ -283,9 +283,12 @@ isEmpty($${target_prefix}.INCDIRS) {
|
||||
}
|
||||
}
|
||||
}
|
||||
- isEmpty(QMAKE_DEFAULT_LIBDIRS)|isEmpty(QMAKE_DEFAULT_INCDIRS): \
|
||||
+ isEmpty(QMAKE_DEFAULT_INCDIRS): \
|
||||
!integrity: \
|
||||
- error("failed to parse default search paths from compiler output")
|
||||
+ error("failed to parse default include paths from compiler output")
|
||||
+ isEmpty(QMAKE_DEFAULT_LIBDIRS): \
|
||||
+ !integrity:!darwin: \
|
||||
+ error("failed to parse default library paths from compiler output")
|
||||
QMAKE_DEFAULT_LIBDIRS = $$unique(QMAKE_DEFAULT_LIBDIRS)
|
||||
} else: ghs {
|
||||
cmd = $$QMAKE_CXX $$QMAKE_CXXFLAGS -$${LITERAL_HASH} -o /tmp/fake_output /tmp/fake_input.cpp
|
||||
@@ -407,7 +410,7 @@ isEmpty($${target_prefix}.INCDIRS) {
|
||||
QMAKE_DEFAULT_INCDIRS = $$split(INCLUDE, $$QMAKE_DIRLIST_SEP)
|
||||
}
|
||||
|
||||
- unix:if(!cross_compile|host_build) {
|
||||
+ unix:!darwin:if(!cross_compile|host_build) {
|
||||
isEmpty(QMAKE_DEFAULT_INCDIRS): QMAKE_DEFAULT_INCDIRS = /usr/include /usr/local/include
|
||||
isEmpty(QMAKE_DEFAULT_LIBDIRS): QMAKE_DEFAULT_LIBDIRS = /lib /usr/lib
|
||||
}
|
||||
49
depends/patches/qt/memory_resource.patch
Normal file
49
depends/patches/qt/memory_resource.patch
Normal file
@@ -0,0 +1,49 @@
|
||||
Fix unusable memory_resource on macos
|
||||
|
||||
See https://bugreports.qt.io/browse/QTBUG-117484
|
||||
and https://bugreports.qt.io/browse/QTBUG-114316
|
||||
|
||||
--- a/qtbase/src/corelib/tools/qduplicatetracker_p.h
|
||||
+++ b/qtbase/src/corelib/tools/qduplicatetracker_p.h
|
||||
@@ -52,7 +52,7 @@
|
||||
|
||||
#include <qglobal.h>
|
||||
|
||||
-#if QT_HAS_INCLUDE(<memory_resource>) && __cplusplus > 201402L
|
||||
+#ifdef __cpp_lib_memory_resource
|
||||
# include <unordered_set>
|
||||
# include <memory_resource>
|
||||
#else
|
||||
|
||||
--- a/qtbase/src/corelib/global/qcompilerdetection.h
|
||||
+++ b/qtbase/src/corelib/global/qcompilerdetection.h
|
||||
@@ -1041,16 +1041,22 @@
|
||||
# endif // !_HAS_CONSTEXPR
|
||||
# endif // !__GLIBCXX__ && !_LIBCPP_VERSION
|
||||
# endif // Q_OS_QNX
|
||||
-# if (defined(Q_CC_CLANG) || defined(Q_CC_INTEL)) && defined(Q_OS_MAC) && defined(__GNUC_LIBSTD__) \
|
||||
- && ((__GNUC_LIBSTD__-0) * 100 + __GNUC_LIBSTD_MINOR__-0 <= 402)
|
||||
+# if (defined(Q_CC_CLANG) || defined(Q_CC_INTEL)) && defined(Q_OS_MAC)
|
||||
+# if defined(__GNUC_LIBSTD__) && ((__GNUC_LIBSTD__-0) * 100 + __GNUC_LIBSTD_MINOR__-0 <= 402)
|
||||
// Apple has not updated libstdc++ since 2007, which means it does not have
|
||||
// <initializer_list> or std::move. Let's disable these features
|
||||
-# undef Q_COMPILER_INITIALIZER_LISTS
|
||||
-# undef Q_COMPILER_RVALUE_REFS
|
||||
-# undef Q_COMPILER_REF_QUALIFIERS
|
||||
+# undef Q_COMPILER_INITIALIZER_LISTS
|
||||
+# undef Q_COMPILER_RVALUE_REFS
|
||||
+# undef Q_COMPILER_REF_QUALIFIERS
|
||||
// Also disable <atomic>, since it's clearly not there
|
||||
-# undef Q_COMPILER_ATOMICS
|
||||
-# endif
|
||||
+# undef Q_COMPILER_ATOMICS
|
||||
+# endif
|
||||
+# if defined(__cpp_lib_memory_resource) \
|
||||
+ && ((defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 140000) \
|
||||
+ || (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 170000))
|
||||
+# undef __cpp_lib_memory_resource // Only supported on macOS 14 and iOS 17
|
||||
+# endif
|
||||
+# endif // (defined(Q_CC_CLANG) || defined(Q_CC_INTEL)) && defined(Q_OS_MAC)
|
||||
# if defined(Q_CC_CLANG) && defined(Q_CC_INTEL) && Q_CC_INTEL >= 1500
|
||||
// ICC 15.x and 16.0 have their own implementation of std::atomic, which is activated when in Clang mode
|
||||
// (probably because libc++'s <atomic> on OS X failed to compile), but they're missing some
|
||||
@@ -1,7 +1,7 @@
|
||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
|
||||
.TH BITCOIN-CLI "1" "May 2023" "bitcoin-cli v24.1.0rc3" "User Commands"
|
||||
.TH BITCOIN-CLI "1" "October 2023" "bitcoin-cli v24.2.0" "User Commands"
|
||||
.SH NAME
|
||||
bitcoin-cli \- manual page for bitcoin-cli v24.1.0rc3
|
||||
bitcoin-cli \- manual page for bitcoin-cli v24.2.0
|
||||
.SH SYNOPSIS
|
||||
.B bitcoin-cli
|
||||
[\fI\,options\/\fR] \fI\,<command> \/\fR[\fI\,params\/\fR] \fI\,Send command to Bitcoin Core\/\fR
|
||||
@@ -15,7 +15,7 @@ bitcoin-cli \- manual page for bitcoin-cli v24.1.0rc3
|
||||
.B bitcoin-cli
|
||||
[\fI\,options\/\fR] \fI\,help <command> Get help for a command\/\fR
|
||||
.SH DESCRIPTION
|
||||
Bitcoin Core RPC client version v24.1.0rc3
|
||||
Bitcoin Core RPC client version v24.2.0
|
||||
.SH OPTIONS
|
||||
.HP
|
||||
\-?
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
|
||||
.TH BITCOIN-QT "1" "May 2023" "bitcoin-qt v24.1.0rc3" "User Commands"
|
||||
.TH BITCOIN-QT "1" "October 2023" "bitcoin-qt v24.2.0" "User Commands"
|
||||
.SH NAME
|
||||
bitcoin-qt \- manual page for bitcoin-qt v24.1.0rc3
|
||||
bitcoin-qt \- manual page for bitcoin-qt v24.2.0
|
||||
.SH SYNOPSIS
|
||||
.B bitcoin-qt
|
||||
[\fI\,command-line options\/\fR]
|
||||
.SH DESCRIPTION
|
||||
Bitcoin Core version v24.1.0rc3
|
||||
Bitcoin Core version v24.2.0
|
||||
.SH OPTIONS
|
||||
.HP
|
||||
\-?
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
|
||||
.TH BITCOIN-TX "1" "May 2023" "bitcoin-tx v24.1.0rc3" "User Commands"
|
||||
.TH BITCOIN-TX "1" "October 2023" "bitcoin-tx v24.2.0" "User Commands"
|
||||
.SH NAME
|
||||
bitcoin-tx \- manual page for bitcoin-tx v24.1.0rc3
|
||||
bitcoin-tx \- manual page for bitcoin-tx v24.2.0
|
||||
.SH SYNOPSIS
|
||||
.B bitcoin-tx
|
||||
[\fI\,options\/\fR] \fI\,<hex-tx> \/\fR[\fI\,commands\/\fR] \fI\,Update hex-encoded bitcoin transaction\/\fR
|
||||
@@ -9,7 +9,7 @@ bitcoin-tx \- manual page for bitcoin-tx v24.1.0rc3
|
||||
.B bitcoin-tx
|
||||
[\fI\,options\/\fR] \fI\,-create \/\fR[\fI\,commands\/\fR] \fI\,Create hex-encoded bitcoin transaction\/\fR
|
||||
.SH DESCRIPTION
|
||||
Bitcoin Core bitcoin\-tx utility version v24.1.0rc3
|
||||
Bitcoin Core bitcoin\-tx utility version v24.2.0
|
||||
.SH OPTIONS
|
||||
.HP
|
||||
\-?
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
|
||||
.TH BITCOIN-UTIL "1" "May 2023" "bitcoin-util v24.1.0rc3" "User Commands"
|
||||
.TH BITCOIN-UTIL "1" "October 2023" "bitcoin-util v24.2.0" "User Commands"
|
||||
.SH NAME
|
||||
bitcoin-util \- manual page for bitcoin-util v24.1.0rc3
|
||||
bitcoin-util \- manual page for bitcoin-util v24.2.0
|
||||
.SH SYNOPSIS
|
||||
.B bitcoin-util
|
||||
[\fI\,options\/\fR] [\fI\,commands\/\fR] \fI\,Do stuff\/\fR
|
||||
.SH DESCRIPTION
|
||||
Bitcoin Core bitcoin\-util utility version v24.1.0rc3
|
||||
Bitcoin Core bitcoin\-util utility version v24.2.0
|
||||
.SH OPTIONS
|
||||
.HP
|
||||
\-?
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
|
||||
.TH BITCOIN-WALLET "1" "May 2023" "bitcoin-wallet v24.1.0rc3" "User Commands"
|
||||
.TH BITCOIN-WALLET "1" "October 2023" "bitcoin-wallet v24.2.0" "User Commands"
|
||||
.SH NAME
|
||||
bitcoin-wallet \- manual page for bitcoin-wallet v24.1.0rc3
|
||||
bitcoin-wallet \- manual page for bitcoin-wallet v24.2.0
|
||||
.SH DESCRIPTION
|
||||
Bitcoin Core bitcoin\-wallet version v24.1.0rc3
|
||||
Bitcoin Core bitcoin\-wallet version v24.2.0
|
||||
.PP
|
||||
bitcoin\-wallet is an offline tool for creating and interacting with Bitcoin Core wallet files.
|
||||
By default bitcoin\-wallet will act on wallets in the default mainnet wallet directory in the datadir.
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
|
||||
.TH BITCOIND "1" "May 2023" "bitcoind v24.1.0rc3" "User Commands"
|
||||
.TH BITCOIND "1" "October 2023" "bitcoind v24.2.0" "User Commands"
|
||||
.SH NAME
|
||||
bitcoind \- manual page for bitcoind v24.1.0rc3
|
||||
bitcoind \- manual page for bitcoind v24.2.0
|
||||
.SH SYNOPSIS
|
||||
.B bitcoind
|
||||
[\fI\,options\/\fR] \fI\,Start Bitcoin Core\/\fR
|
||||
.SH DESCRIPTION
|
||||
Bitcoin Core version v24.1.0rc3
|
||||
Bitcoin Core version v24.2.0
|
||||
.SH OPTIONS
|
||||
.HP
|
||||
\-?
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
24.1rc3 Release Notes
|
||||
====================
|
||||
24.2 Release Notes
|
||||
==================
|
||||
|
||||
Bitcoin Core version 24.1rc3 is now available from:
|
||||
Bitcoin Core version 24.2 is now available from:
|
||||
|
||||
<https://bitcoincore.org/bin/bitcoin-core-24.1/test.rc3/>
|
||||
<https://bitcoincore.org/bin/bitcoin-core-24.2/>
|
||||
|
||||
This release includes new features, various bug fixes and performance
|
||||
This release includes various bug fixes and performance
|
||||
improvements, as well as updated translations.
|
||||
|
||||
Please report bugs using the issue tracker at GitHub:
|
||||
@@ -37,63 +37,40 @@ 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.
|
||||
|
||||
### P2P
|
||||
### Fees
|
||||
|
||||
- #26878 I2P network optimizations
|
||||
- #26909 net: prevent peers.dat corruptions by only serializing once
|
||||
- #27608 p2p: Avoid prematurely clearing download state for other peers
|
||||
- #27610 Improve performance of p2p inv to send queues
|
||||
- #27622 Fee estimation: avoid serving stale fee estimate
|
||||
|
||||
### RPC and other APIs
|
||||
|
||||
- #26515 rpc: Require NodeStateStats object in getpeerinfo
|
||||
- #27279 doc: fix/improve warning helps in {create,load,unload,restore}wallet
|
||||
- #27468 rest: avoid segfault for invalid URI
|
||||
- #27727 rpc: Fix invalid bech32 address handling
|
||||
|
||||
### Build System
|
||||
|
||||
- #26944 depends: fix systemtap download URL
|
||||
- #27462 depends: fix compiling bdb with clang-16 on aarch64
|
||||
- #28097 depends: xcb-proto 1.15.2
|
||||
- #28543 build, macos: Fix qt package build with new Xcode 15 linker
|
||||
- #28571 depends: fix unusable memory_resource in macos qt build
|
||||
|
||||
### Wallet
|
||||
### CI
|
||||
|
||||
- #26595 wallet: be able to specify a wallet name and passphrase to migratewallet
|
||||
- #26675 wallet: For feebump, ignore abandoned descendant spends
|
||||
- #26679 wallet: Skip rescanning if wallet is more recent than tip
|
||||
- #26761 wallet: fully migrate address book entries for watchonly/solvable wallets
|
||||
- #27053 wallet: reuse change dest when re-creating TX with avoidpartialspends
|
||||
- #27080 wallet: Zero out wallet master key upon locking so it doesn't persist in memory
|
||||
- #27473 wallet: Properly handle "unknown" Address Type
|
||||
|
||||
### GUI changes
|
||||
|
||||
- gui#687 Load PSBTs using istreambuf_iterator rather than istream_iterator
|
||||
- gui#704 Correctly limit overview transaction list
|
||||
- #27777 ci: Prune dangling images on RESTART_CI_DOCKER_BEFORE_RUN
|
||||
- #27834 ci: Nuke Android APK task, Use credits for tsan
|
||||
- #27844 ci: Use podman stop over podman kill
|
||||
- #27886 ci: Switch to amd64 container in "ARM" task
|
||||
|
||||
### Miscellaneous
|
||||
|
||||
- #26880 ci: replace Intel macOS CI job
|
||||
- #26924 refactor: Add missing includes to fix gcc-13 compile error
|
||||
- #28452 Do not use std::vector = {} to release memory
|
||||
|
||||
Credits
|
||||
=======
|
||||
|
||||
Thanks to everyone who directly contributed to this release:
|
||||
|
||||
- Andrew Chow
|
||||
- Anthony Towns
|
||||
- Abubakar Sadiq Ismail
|
||||
- Hennadii Stepanov
|
||||
- John Moffett
|
||||
- Jon Atack
|
||||
- Marco Falke
|
||||
- Martin Zumsande
|
||||
- Matthew Zipkin
|
||||
- Michael Ford
|
||||
- pablomartin4btc
|
||||
- Sebastian Falbesoner
|
||||
- Suhas Daftuar
|
||||
- Thomas Nguyen
|
||||
- Vasil Dimov
|
||||
- Pieter Wuille
|
||||
|
||||
As well as to everyone that helped with translations on
|
||||
[Transifex](https://www.transifex.com/bitcoin/bitcoin/).
|
||||
|
||||
99
doc/release-notes/release-notes-24.1.md
Normal file
99
doc/release-notes/release-notes-24.1.md
Normal file
@@ -0,0 +1,99 @@
|
||||
24.1 Release Notes
|
||||
==================
|
||||
|
||||
Bitcoin Core version 24.1 is now available from:
|
||||
|
||||
<https://bitcoincore.org/bin/bitcoin-core-24.1/>
|
||||
|
||||
This release includes various bug fixes and performance
|
||||
improvements, as well as updated translations.
|
||||
|
||||
Please report bugs using the issue tracker at GitHub:
|
||||
|
||||
<https://github.com/bitcoin/bitcoin/issues>
|
||||
|
||||
To receive security and update notifications, please subscribe to:
|
||||
|
||||
<https://bitcoincore.org/en/list/announcements/join/>
|
||||
|
||||
How to Upgrade
|
||||
==============
|
||||
|
||||
If you are running an older version, shut it down. Wait until it has completely
|
||||
shut down (which might take a few minutes in some cases), then run the
|
||||
installer (on Windows) or just copy over `/Applications/Bitcoin-Qt` (on macOS)
|
||||
or `bitcoind`/`bitcoin-qt` (on Linux).
|
||||
|
||||
Upgrading directly from a version of Bitcoin Core that has reached its EOL is
|
||||
possible, but it might take some time if the data directory needs to be migrated. Old
|
||||
wallet versions of Bitcoin Core are generally supported.
|
||||
|
||||
Compatibility
|
||||
==============
|
||||
|
||||
Bitcoin Core is supported and extensively tested on operating systems
|
||||
using the Linux kernel, macOS 10.15+, and Windows 7 and newer. Bitcoin
|
||||
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.
|
||||
|
||||
### P2P
|
||||
|
||||
- #26878 I2P network optimizations
|
||||
- #26909 net: prevent peers.dat corruptions by only serializing once
|
||||
- #27608 p2p: Avoid prematurely clearing download state for other peers
|
||||
- #27610 Improve performance of p2p inv to send queues
|
||||
|
||||
### RPC and other APIs
|
||||
|
||||
- #26515 rpc: Require NodeStateStats object in getpeerinfo
|
||||
- #27279 doc: fix/improve warning helps in {create,load,unload,restore}wallet
|
||||
- #27468 rest: avoid segfault for invalid URI
|
||||
|
||||
### Build System
|
||||
|
||||
- #26944 depends: fix systemtap download URL
|
||||
- #27462 depends: fix compiling bdb with clang-16 on aarch64
|
||||
|
||||
### Wallet
|
||||
|
||||
- #26595 wallet: be able to specify a wallet name and passphrase to migratewallet
|
||||
- #26675 wallet: For feebump, ignore abandoned descendant spends
|
||||
- #26679 wallet: Skip rescanning if wallet is more recent than tip
|
||||
- #26761 wallet: fully migrate address book entries for watchonly/solvable wallets
|
||||
- #27053 wallet: reuse change dest when re-creating TX with avoidpartialspends
|
||||
- #27080 wallet: Zero out wallet master key upon locking so it doesn't persist in memory
|
||||
- #27473 wallet: Properly handle "unknown" Address Type
|
||||
|
||||
### GUI changes
|
||||
|
||||
- gui#687 Load PSBTs using istreambuf_iterator rather than istream_iterator
|
||||
- gui#704 Correctly limit overview transaction list
|
||||
|
||||
### Miscellaneous
|
||||
|
||||
- #26880 ci: replace Intel macOS CI job
|
||||
- #26924 refactor: Add missing includes to fix gcc-13 compile error
|
||||
|
||||
Credits
|
||||
=======
|
||||
|
||||
Thanks to everyone who directly contributed to this release:
|
||||
|
||||
- Andrew Chow
|
||||
- Anthony Towns
|
||||
- Hennadii Stepanov
|
||||
- John Moffett
|
||||
- Jon Atack
|
||||
- Marco Falke
|
||||
- Martin Zumsande
|
||||
- Matthew Zipkin
|
||||
- Michael Ford
|
||||
- pablomartin4btc
|
||||
- Sebastian Falbesoner
|
||||
- Suhas Daftuar
|
||||
- Thomas Nguyen
|
||||
- Vasil Dimov
|
||||
|
||||
As well as to everyone that helped with translations on
|
||||
[Transifex](https://www.transifex.com/bitcoin/bitcoin/).
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <pow.h>
|
||||
#include <timedata.h>
|
||||
#include <util/check.h>
|
||||
#include <util/vector.h>
|
||||
|
||||
// The two constants below are computed using the simulation script on
|
||||
// https://gist.github.com/sipa/016ae445c132cdf65a2791534dfb7ae1
|
||||
@@ -51,9 +52,9 @@ HeadersSyncState::HeadersSyncState(NodeId id, const Consensus::Params& consensus
|
||||
void HeadersSyncState::Finalize()
|
||||
{
|
||||
Assume(m_download_state != State::FINAL);
|
||||
m_header_commitments = {};
|
||||
ClearShrink(m_header_commitments);
|
||||
m_last_header_received.SetNull();
|
||||
m_redownloaded_headers = {};
|
||||
ClearShrink(m_redownloaded_headers);
|
||||
m_redownload_buffer_last_hash.SetNull();
|
||||
m_redownload_buffer_first_prev_hash.SetNull();
|
||||
m_process_all_remaining_headers = false;
|
||||
|
||||
14
src/init.cpp
14
src/init.cpp
@@ -76,6 +76,7 @@
|
||||
#include <util/system.h>
|
||||
#include <util/thread.h>
|
||||
#include <util/threadnames.h>
|
||||
#include <util/time.h>
|
||||
#include <util/translation.h>
|
||||
#include <validation.h>
|
||||
#include <validationinterface.h>
|
||||
@@ -561,6 +562,7 @@ void SetupServerArgs(ArgsManager& argsman)
|
||||
argsman.AddArg("-acceptnonstdtxn", strprintf("Relay and mine \"non-standard\" transactions (%sdefault: %u)", "testnet/regtest only; ", !testnetChainParams->RequireStandard()), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::NODE_RELAY);
|
||||
argsman.AddArg("-incrementalrelayfee=<amt>", strprintf("Fee rate (in %s/kvB) used to define cost of relay, used for mempool limiting and replacement policy. (default: %s)", CURRENCY_UNIT, FormatMoney(DEFAULT_INCREMENTAL_RELAY_FEE)), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::NODE_RELAY);
|
||||
argsman.AddArg("-dustrelayfee=<amt>", strprintf("Fee rate (in %s/kvB) used to define dust, the value of an output such that it will cost more than its value in fees at this fee rate to spend it. (default: %s)", CURRENCY_UNIT, FormatMoney(DUST_RELAY_TX_FEE)), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::NODE_RELAY);
|
||||
argsman.AddArg("-acceptstalefeeestimates", strprintf("Read fee estimates even if they are stale (%sdefault: %u) fee estimates are considered stale if they are %s hours old", "regtest only; ", DEFAULT_ACCEPT_STALE_FEE_ESTIMATES, Ticks<std::chrono::hours>(MAX_FILE_AGE)), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
|
||||
argsman.AddArg("-bytespersigop", strprintf("Equivalent bytes per sigop in transactions for relay and mining (default: %u)", DEFAULT_BYTES_PER_SIGOP), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
|
||||
argsman.AddArg("-datacarrier", strprintf("Relay and mine data carrier transactions (default: %u)", DEFAULT_ACCEPT_DATACARRIER), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
|
||||
argsman.AddArg("-datacarriersize", strprintf("Maximum size of data in data carrier transactions we relay and mine (default: %u)", MAX_OP_RETURN_RELAY), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
|
||||
@@ -1253,7 +1255,17 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
|
||||
assert(!node.fee_estimator);
|
||||
// Don't initialize fee estimation with old data if we don't relay transactions,
|
||||
// as they would never get updated.
|
||||
if (!ignores_incoming_txs) node.fee_estimator = std::make_unique<CBlockPolicyEstimator>(FeeestPath(args));
|
||||
if (!ignores_incoming_txs) {
|
||||
bool read_stale_estimates = args.GetBoolArg("-acceptstalefeeestimates", DEFAULT_ACCEPT_STALE_FEE_ESTIMATES);
|
||||
if (read_stale_estimates && (chainparams.NetworkIDString() != CBaseChainParams::REGTEST)) {
|
||||
return InitError(strprintf(_("acceptstalefeeestimates is not supported on %s chain."), chainparams.NetworkIDString()));
|
||||
}
|
||||
node.fee_estimator = std::make_unique<CBlockPolicyEstimator>(FeeestPath(args), read_stale_estimates);
|
||||
|
||||
// Flush estimates to disk periodically
|
||||
CBlockPolicyEstimator* fee_estimator = node.fee_estimator.get();
|
||||
node.scheduler->scheduleEvery([fee_estimator] { fee_estimator->FlushFeeEstimates(); }, FEE_FLUSH_INTERVAL);
|
||||
}
|
||||
|
||||
// sanitize comments per BIP-0014, format user agent and check total size
|
||||
std::vector<std::string> uacomments;
|
||||
|
||||
@@ -109,13 +109,13 @@ CTxDestination DecodeDestination(const std::string& str, const CChainParams& par
|
||||
std::equal(pubkey_prefix.begin(), pubkey_prefix.end(), data.begin()))) {
|
||||
error_str = "Invalid length for Base58 address";
|
||||
} else {
|
||||
error_str = "Invalid prefix for Base58-encoded address";
|
||||
error_str = "Invalid or unsupported Base58-encoded address.";
|
||||
}
|
||||
return CNoDestination();
|
||||
} else if (!is_bech32) {
|
||||
// Try Base58 decoding without the checksum, using a much larger max length
|
||||
if (!DecodeBase58(str, data, 100)) {
|
||||
error_str = "Not a valid Bech32 or Base58 encoding";
|
||||
error_str = "Invalid or unsupported Segwit (Bech32) or Base58 encoding.";
|
||||
} else {
|
||||
error_str = "Invalid checksum or length of Base58 address";
|
||||
}
|
||||
@@ -124,7 +124,11 @@ CTxDestination DecodeDestination(const std::string& str, const CChainParams& par
|
||||
|
||||
data.clear();
|
||||
const auto dec = bech32::Decode(str);
|
||||
if ((dec.encoding == bech32::Encoding::BECH32 || dec.encoding == bech32::Encoding::BECH32M) && dec.data.size() > 0) {
|
||||
if (dec.encoding == bech32::Encoding::BECH32 || dec.encoding == bech32::Encoding::BECH32M) {
|
||||
if (dec.data.empty()) {
|
||||
error_str = "Empty Bech32 data section";
|
||||
return CNoDestination();
|
||||
}
|
||||
// Bech32 decoding
|
||||
if (dec.hrp != params.Bech32HRP()) {
|
||||
error_str = "Invalid prefix for Bech32 address";
|
||||
@@ -158,7 +162,7 @@ CTxDestination DecodeDestination(const std::string& str, const CChainParams& par
|
||||
}
|
||||
}
|
||||
|
||||
error_str = "Invalid Bech32 v0 address data size";
|
||||
error_str = strprintf("Invalid Bech32 v0 address program size (%s byte), per BIP141", data.size());
|
||||
return CNoDestination();
|
||||
}
|
||||
|
||||
@@ -175,7 +179,7 @@ CTxDestination DecodeDestination(const std::string& str, const CChainParams& par
|
||||
}
|
||||
|
||||
if (data.size() < 2 || data.size() > BECH32_WITNESS_PROG_MAX_LEN) {
|
||||
error_str = "Invalid Bech32 address data size";
|
||||
error_str = strprintf("Invalid Bech32 address program size (%s byte)", data.size());
|
||||
return CNoDestination();
|
||||
}
|
||||
|
||||
@@ -184,6 +188,9 @@ CTxDestination DecodeDestination(const std::string& str, const CChainParams& par
|
||||
std::copy(data.begin(), data.end(), unk.program);
|
||||
unk.length = data.size();
|
||||
return unk;
|
||||
} else {
|
||||
error_str = strprintf("Invalid padding in Bech32 data section");
|
||||
return CNoDestination();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <chrono>
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
@@ -527,7 +528,7 @@ bool CBlockPolicyEstimator::_removeTx(const uint256& hash, bool inBlock)
|
||||
}
|
||||
}
|
||||
|
||||
CBlockPolicyEstimator::CBlockPolicyEstimator(const fs::path& estimation_filepath)
|
||||
CBlockPolicyEstimator::CBlockPolicyEstimator(const fs::path& estimation_filepath, const bool read_stale_estimates)
|
||||
: m_estimation_filepath{estimation_filepath}, nBestSeenHeight{0}, firstRecordedHeight{0}, historicalFirst{0}, historicalBest{0}, trackedTxs{0}, untrackedTxs{0}
|
||||
{
|
||||
static_assert(MIN_BUCKET_FEERATE > 0, "Min feerate must be nonzero");
|
||||
@@ -545,9 +546,22 @@ CBlockPolicyEstimator::CBlockPolicyEstimator(const fs::path& estimation_filepath
|
||||
shortStats = std::unique_ptr<TxConfirmStats>(new TxConfirmStats(buckets, bucketMap, SHORT_BLOCK_PERIODS, SHORT_DECAY, SHORT_SCALE));
|
||||
longStats = std::unique_ptr<TxConfirmStats>(new TxConfirmStats(buckets, bucketMap, LONG_BLOCK_PERIODS, LONG_DECAY, LONG_SCALE));
|
||||
|
||||
// If the fee estimation file is present, read recorded estimations
|
||||
AutoFile est_file{fsbridge::fopen(m_estimation_filepath, "rb")};
|
||||
if (est_file.IsNull() || !Read(est_file)) {
|
||||
|
||||
// Whenever the fee estimation file is not present return early
|
||||
if (est_file.IsNull()) {
|
||||
LogPrintf("%s is not found. Continue anyway.\n", fs::PathToString(m_estimation_filepath));
|
||||
return;
|
||||
}
|
||||
|
||||
std::chrono::hours file_age = GetFeeEstimatorFileAge();
|
||||
// fee estimate file must not be too old to avoid wrong fee estimates.
|
||||
if (file_age > MAX_FILE_AGE && !read_stale_estimates) {
|
||||
LogPrintf("Fee estimation file %s too old (age=%lld > %lld hours) and will not be used to avoid serving stale estimates.\n", fs::PathToString(m_estimation_filepath), Ticks<std::chrono::hours>(file_age), Ticks<std::chrono::hours>(MAX_FILE_AGE));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Read(est_file)) {
|
||||
LogPrintf("Failed to read fee estimates from %s. Continue anyway.\n", fs::PathToString(m_estimation_filepath));
|
||||
}
|
||||
}
|
||||
@@ -903,10 +917,16 @@ CFeeRate CBlockPolicyEstimator::estimateSmartFee(int confTarget, FeeCalculation
|
||||
|
||||
void CBlockPolicyEstimator::Flush() {
|
||||
FlushUnconfirmed();
|
||||
FlushFeeEstimates();
|
||||
}
|
||||
|
||||
void CBlockPolicyEstimator::FlushFeeEstimates()
|
||||
{
|
||||
AutoFile est_file{fsbridge::fopen(m_estimation_filepath, "wb")};
|
||||
if (est_file.IsNull() || !Write(est_file)) {
|
||||
LogPrintf("Failed to write fee estimates to %s. Continue anyway.\n", fs::PathToString(m_estimation_filepath));
|
||||
} else {
|
||||
LogPrintf("Flushed fee estimates to %s.\n", fs::PathToString(m_estimation_filepath.filename()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1010,6 +1030,13 @@ void CBlockPolicyEstimator::FlushUnconfirmed() {
|
||||
LogPrint(BCLog::ESTIMATEFEE, "Recorded %u unconfirmed txs from mempool in %gs\n", num_entries, (endclear - startclear)*0.000001);
|
||||
}
|
||||
|
||||
std::chrono::hours CBlockPolicyEstimator::GetFeeEstimatorFileAge()
|
||||
{
|
||||
auto file_time = std::filesystem::last_write_time(m_estimation_filepath);
|
||||
auto now = std::filesystem::file_time_type::clock::now();
|
||||
return std::chrono::duration_cast<std::chrono::hours>(now - file_time);
|
||||
}
|
||||
|
||||
FeeFilterRounder::FeeFilterRounder(const CFeeRate& minIncrementalFee)
|
||||
{
|
||||
CAmount minFeeLimit = std::max(CAmount(1), minIncrementalFee.GetFeePerK() / 2);
|
||||
|
||||
@@ -14,12 +14,25 @@
|
||||
#include <uint256.h>
|
||||
|
||||
#include <array>
|
||||
#include <chrono>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
||||
// How often to flush fee estimates to fee_estimates.dat.
|
||||
static constexpr std::chrono::hours FEE_FLUSH_INTERVAL{1};
|
||||
|
||||
/** fee_estimates.dat that are more than 60 hours (2.5 days) will not be read,
|
||||
* as the estimates in the file are stale.
|
||||
*/
|
||||
static constexpr std::chrono::hours MAX_FILE_AGE{60};
|
||||
|
||||
// Whether we allow importing a fee_estimates file older than MAX_FILE_AGE.
|
||||
static constexpr bool DEFAULT_ACCEPT_STALE_FEE_ESTIMATES{false};
|
||||
|
||||
class AutoFile;
|
||||
class CTxMemPoolEntry;
|
||||
class TxConfirmStats;
|
||||
@@ -183,7 +196,7 @@ private:
|
||||
const fs::path m_estimation_filepath;
|
||||
public:
|
||||
/** Create new BlockPolicyEstimator and initialize stats tracking classes with default values */
|
||||
CBlockPolicyEstimator(const fs::path& estimation_filepath);
|
||||
CBlockPolicyEstimator(const fs::path& estimation_filepath, const bool read_stale_estimates);
|
||||
~CBlockPolicyEstimator();
|
||||
|
||||
/** Process all the transactions that have been included in a block */
|
||||
@@ -239,6 +252,13 @@ public:
|
||||
void Flush()
|
||||
EXCLUSIVE_LOCKS_REQUIRED(!m_cs_fee_estimator);
|
||||
|
||||
/** Record current fee estimations. */
|
||||
void FlushFeeEstimates()
|
||||
EXCLUSIVE_LOCKS_REQUIRED(!m_cs_fee_estimator);
|
||||
|
||||
/** Calculates the age of the file, since last modified */
|
||||
std::chrono::hours GetFeeEstimatorFileAge();
|
||||
|
||||
private:
|
||||
mutable Mutex m_cs_fee_estimator;
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ void initialize_policy_estimator()
|
||||
FUZZ_TARGET_INIT(policy_estimator, initialize_policy_estimator)
|
||||
{
|
||||
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
|
||||
CBlockPolicyEstimator block_policy_estimator{FeeestPath(*g_setup->m_node.args)};
|
||||
CBlockPolicyEstimator block_policy_estimator{FeeestPath(*g_setup->m_node.args), DEFAULT_ACCEPT_STALE_FEE_ESTIMATES};
|
||||
LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000) {
|
||||
CallOneOf(
|
||||
fuzzed_data_provider,
|
||||
|
||||
@@ -28,7 +28,7 @@ FUZZ_TARGET_INIT(policy_estimator_io, initialize_policy_estimator_io)
|
||||
FuzzedAutoFileProvider fuzzed_auto_file_provider = ConsumeAutoFile(fuzzed_data_provider);
|
||||
AutoFile fuzzed_auto_file{fuzzed_auto_file_provider.open()};
|
||||
// Re-using block_policy_estimator across runs to avoid costly creation of CBlockPolicyEstimator object.
|
||||
static CBlockPolicyEstimator block_policy_estimator{FeeestPath(*g_setup->m_node.args)};
|
||||
static CBlockPolicyEstimator block_policy_estimator{FeeestPath(*g_setup->m_node.args), DEFAULT_ACCEPT_STALE_FEE_ESTIMATES};
|
||||
if (block_policy_estimator.Read(fuzzed_auto_file)) {
|
||||
block_policy_estimator.Write(fuzzed_auto_file);
|
||||
}
|
||||
|
||||
@@ -186,7 +186,7 @@ ChainTestingSetup::ChainTestingSetup(const std::string& chainName, const std::ve
|
||||
m_node.scheduler->m_service_thread = std::thread(util::TraceThread, "scheduler", [&] { m_node.scheduler->serviceQueue(); });
|
||||
GetMainSignals().RegisterBackgroundSignalScheduler(*m_node.scheduler);
|
||||
|
||||
m_node.fee_estimator = std::make_unique<CBlockPolicyEstimator>(FeeestPath(*m_node.args));
|
||||
m_node.fee_estimator = std::make_unique<CBlockPolicyEstimator>(FeeestPath(*m_node.args), DEFAULT_ACCEPT_STALE_FEE_ESTIMATES);
|
||||
m_node.mempool = std::make_unique<CTxMemPool>(MemPoolOptionsForTest(m_node));
|
||||
|
||||
m_cache_sizes = CalculateCacheSizes(m_args);
|
||||
|
||||
@@ -2782,4 +2782,29 @@ BOOST_AUTO_TEST_CASE(util_WriteBinaryFile)
|
||||
BOOST_CHECK(valid);
|
||||
BOOST_CHECK_EQUAL(actual_text, expected_text);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(clearshrink_test)
|
||||
{
|
||||
{
|
||||
std::vector<uint8_t> v = {1, 2, 3};
|
||||
ClearShrink(v);
|
||||
BOOST_CHECK_EQUAL(v.size(), 0);
|
||||
BOOST_CHECK_EQUAL(v.capacity(), 0);
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<bool> v = {false, true, false, false, true, true};
|
||||
ClearShrink(v);
|
||||
BOOST_CHECK_EQUAL(v.size(), 0);
|
||||
BOOST_CHECK_EQUAL(v.capacity(), 0);
|
||||
}
|
||||
|
||||
{
|
||||
std::deque<int> v = {1, 3, 3, 7};
|
||||
ClearShrink(v);
|
||||
BOOST_CHECK_EQUAL(v.size(), 0);
|
||||
// std::deque has no capacity() we can observe.
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
@@ -49,4 +49,22 @@ inline V Cat(V v1, const V& v2)
|
||||
return v1;
|
||||
}
|
||||
|
||||
/** Clear a vector (or std::deque) and release its allocated memory. */
|
||||
template<typename V>
|
||||
inline void ClearShrink(V& v) noexcept
|
||||
{
|
||||
// There are various ways to clear a vector and release its memory:
|
||||
//
|
||||
// 1. V{}.swap(v)
|
||||
// 2. v = V{}
|
||||
// 3. v = {}; v.shrink_to_fit();
|
||||
// 4. v.clear(); v.shrink_to_fit();
|
||||
//
|
||||
// (2) does not appear to release memory in glibc debug mode, even if v.shrink_to_fit()
|
||||
// follows. (3) and (4) rely on std::vector::shrink_to_fit, which is only a non-binding
|
||||
// request. Therefore, we use method (1).
|
||||
|
||||
V{}.swap(v);
|
||||
}
|
||||
|
||||
#endif // BITCOIN_UTIL_VECTOR_H
|
||||
|
||||
@@ -7,6 +7,7 @@ from copy import deepcopy
|
||||
from decimal import Decimal
|
||||
import os
|
||||
import random
|
||||
import time
|
||||
|
||||
from test_framework.messages import (
|
||||
COIN,
|
||||
@@ -21,6 +22,8 @@ from test_framework.util import (
|
||||
)
|
||||
from test_framework.wallet import MiniWallet
|
||||
|
||||
MAX_FILE_AGE = 60
|
||||
SECONDS_PER_HOUR = 60 * 60
|
||||
|
||||
def small_txpuzzle_randfee(
|
||||
wallet, from_node, conflist, unconflist, amount, min_fee, fee_increment
|
||||
@@ -273,6 +276,95 @@ class EstimateFeeTest(BitcoinTestFramework):
|
||||
est_feerate = node.estimatesmartfee(2)["feerate"]
|
||||
assert_equal(est_feerate, high_feerate_kvb)
|
||||
|
||||
def test_old_fee_estimate_file(self):
|
||||
# Get the initial fee rate while node is running
|
||||
fee_rate = self.nodes[0].estimatesmartfee(1)["feerate"]
|
||||
|
||||
# Restart node to ensure fee_estimate.dat file is read
|
||||
self.restart_node(0)
|
||||
assert_equal(self.nodes[0].estimatesmartfee(1)["feerate"], fee_rate)
|
||||
|
||||
fee_dat = self.nodes[0].chain_path / "fee_estimates.dat"
|
||||
|
||||
# Stop the node and backdate the fee_estimates.dat file more than MAX_FILE_AGE
|
||||
self.stop_node(0)
|
||||
last_modified_time = time.time() - (MAX_FILE_AGE + 1) * SECONDS_PER_HOUR
|
||||
os.utime(fee_dat, (last_modified_time, last_modified_time))
|
||||
|
||||
# Start node and ensure the fee_estimates.dat file was not read
|
||||
self.start_node(0)
|
||||
assert_equal(self.nodes[0].estimatesmartfee(1)["errors"], ["Insufficient data or no feerate found"])
|
||||
|
||||
|
||||
def test_estimate_dat_is_flushed_periodically(self):
|
||||
fee_dat = self.nodes[0].chain_path / "fee_estimates.dat"
|
||||
os.remove(fee_dat) if os.path.exists(fee_dat) else None
|
||||
|
||||
# Verify that fee_estimates.dat does not exist
|
||||
assert_equal(os.path.isfile(fee_dat), False)
|
||||
|
||||
# Verify if the string "Flushed fee estimates to fee_estimates.dat." is present in the debug log file.
|
||||
# If present, it indicates that fee estimates have been successfully flushed to disk.
|
||||
with self.nodes[0].assert_debug_log(expected_msgs=["Flushed fee estimates to fee_estimates.dat."], timeout=1):
|
||||
# Mock the scheduler for an hour to flush fee estimates to fee_estimates.dat
|
||||
self.nodes[0].mockscheduler(SECONDS_PER_HOUR)
|
||||
|
||||
# Verify that fee estimates were flushed and fee_estimates.dat file is created
|
||||
assert_equal(os.path.isfile(fee_dat), True)
|
||||
|
||||
# Verify that the estimates remain the same if there are no blocks in the flush interval
|
||||
block_hash_before = self.nodes[0].getbestblockhash()
|
||||
fee_dat_initial_content = open(fee_dat, "rb").read()
|
||||
with self.nodes[0].assert_debug_log(expected_msgs=["Flushed fee estimates to fee_estimates.dat."], timeout=1):
|
||||
# Mock the scheduler for an hour to flush fee estimates to fee_estimates.dat
|
||||
self.nodes[0].mockscheduler(SECONDS_PER_HOUR)
|
||||
|
||||
# Verify that there were no blocks in between the flush interval
|
||||
assert_equal(block_hash_before, self.nodes[0].getbestblockhash())
|
||||
|
||||
fee_dat_current_content = open(fee_dat, "rb").read()
|
||||
assert_equal(fee_dat_current_content, fee_dat_initial_content)
|
||||
|
||||
# Verify that the estimates remain the same after shutdown with no blocks before shutdown
|
||||
self.restart_node(0)
|
||||
fee_dat_current_content = open(fee_dat, "rb").read()
|
||||
assert_equal(fee_dat_current_content, fee_dat_initial_content)
|
||||
|
||||
# Verify that the estimates are not the same if new blocks were produced in the flush interval
|
||||
with self.nodes[0].assert_debug_log(expected_msgs=["Flushed fee estimates to fee_estimates.dat."], timeout=1):
|
||||
# Mock the scheduler for an hour to flush fee estimates to fee_estimates.dat
|
||||
self.generate(self.nodes[0], 5, sync_fun=self.no_op)
|
||||
self.nodes[0].mockscheduler(SECONDS_PER_HOUR)
|
||||
|
||||
fee_dat_current_content = open(fee_dat, "rb").read()
|
||||
assert fee_dat_current_content != fee_dat_initial_content
|
||||
|
||||
fee_dat_initial_content = fee_dat_current_content
|
||||
|
||||
# Generate blocks before shutdown and verify that the fee estimates are not the same
|
||||
self.generate(self.nodes[0], 5, sync_fun=self.no_op)
|
||||
self.restart_node(0)
|
||||
fee_dat_current_content = open(fee_dat, "rb").read()
|
||||
assert fee_dat_current_content != fee_dat_initial_content
|
||||
|
||||
|
||||
def test_acceptstalefeeestimates_option(self):
|
||||
# Get the initial fee rate while node is running
|
||||
fee_rate = self.nodes[0].estimatesmartfee(1)["feerate"]
|
||||
|
||||
self.stop_node(0)
|
||||
|
||||
fee_dat = self.nodes[0].chain_path / "fee_estimates.dat"
|
||||
|
||||
# Stop the node and backdate the fee_estimates.dat file more than MAX_FILE_AGE
|
||||
last_modified_time = time.time() - (MAX_FILE_AGE + 1) * SECONDS_PER_HOUR
|
||||
os.utime(fee_dat, (last_modified_time, last_modified_time))
|
||||
|
||||
# Restart node with -acceptstalefeeestimates option to ensure fee_estimate.dat file is read
|
||||
self.start_node(0,extra_args=["-acceptstalefeeestimates"])
|
||||
assert_equal(self.nodes[0].estimatesmartfee(1)["feerate"], fee_rate)
|
||||
|
||||
|
||||
def run_test(self):
|
||||
self.log.info("This test is time consuming, please be patient")
|
||||
self.log.info("Splitting inputs so we can generate tx's")
|
||||
@@ -296,12 +388,21 @@ class EstimateFeeTest(BitcoinTestFramework):
|
||||
self.log.info("Testing estimates with single transactions.")
|
||||
self.sanity_check_estimates_range()
|
||||
|
||||
self.log.info("Test fee_estimates.dat is flushed periodically")
|
||||
self.test_estimate_dat_is_flushed_periodically()
|
||||
|
||||
# check that the effective feerate is greater than or equal to the mempoolminfee even for high mempoolminfee
|
||||
self.log.info(
|
||||
"Test fee rate estimation after restarting node with high MempoolMinFee"
|
||||
)
|
||||
self.test_feerate_mempoolminfee()
|
||||
|
||||
self.log.info("Test acceptstalefeeestimates option")
|
||||
self.test_acceptstalefeeestimates_option()
|
||||
|
||||
self.log.info("Test reading old fee_estimates.dat")
|
||||
self.test_old_fee_estimate_file()
|
||||
|
||||
self.log.info("Restarting node with fresh estimation")
|
||||
self.stop_node(0)
|
||||
fee_dat = os.path.join(self.nodes[0].datadir, self.chain, "fee_estimates.dat")
|
||||
|
||||
@@ -60,12 +60,12 @@ class InvalidAddressErrorMessageTest(BitcoinTestFramework):
|
||||
|
||||
def test_validateaddress(self):
|
||||
# Invalid Bech32
|
||||
self.check_invalid(BECH32_INVALID_SIZE, 'Invalid Bech32 address data size')
|
||||
self.check_invalid(BECH32_INVALID_PREFIX, 'Not a valid Bech32 or Base58 encoding')
|
||||
self.check_invalid(BECH32_INVALID_SIZE, 'Invalid Bech32 address program size (41 byte)')
|
||||
self.check_invalid(BECH32_INVALID_PREFIX, 'Invalid or unsupported Segwit (Bech32) or Base58 encoding.')
|
||||
self.check_invalid(BECH32_INVALID_BECH32, 'Version 1+ witness address must use Bech32m checksum')
|
||||
self.check_invalid(BECH32_INVALID_BECH32M, 'Version 0 witness address must use Bech32 checksum')
|
||||
self.check_invalid(BECH32_INVALID_VERSION, 'Invalid Bech32 address witness version')
|
||||
self.check_invalid(BECH32_INVALID_V0_SIZE, 'Invalid Bech32 v0 address data size')
|
||||
self.check_invalid(BECH32_INVALID_V0_SIZE, 'Invalid Bech32 v0 address program size (21 byte), per BIP141')
|
||||
self.check_invalid(BECH32_TOO_LONG, 'Bech32 string too long', list(range(90, 108)))
|
||||
self.check_invalid(BECH32_ONE_ERROR, 'Invalid Bech32 checksum', [9])
|
||||
self.check_invalid(BECH32_TWO_ERRORS, 'Invalid Bech32 checksum', [22, 43])
|
||||
@@ -81,7 +81,7 @@ class InvalidAddressErrorMessageTest(BitcoinTestFramework):
|
||||
self.check_valid(BECH32_VALID_MULTISIG)
|
||||
|
||||
# Invalid Base58
|
||||
self.check_invalid(BASE58_INVALID_PREFIX, 'Invalid prefix for Base58-encoded address')
|
||||
self.check_invalid(BASE58_INVALID_PREFIX, 'Invalid or unsupported Base58-encoded address.')
|
||||
self.check_invalid(BASE58_INVALID_CHECKSUM, 'Invalid checksum or length of Base58 address')
|
||||
self.check_invalid(BASE58_INVALID_LENGTH, 'Invalid checksum or length of Base58 address')
|
||||
|
||||
@@ -89,19 +89,19 @@ class InvalidAddressErrorMessageTest(BitcoinTestFramework):
|
||||
self.check_valid(BASE58_VALID)
|
||||
|
||||
# Invalid address format
|
||||
self.check_invalid(INVALID_ADDRESS, 'Not a valid Bech32 or Base58 encoding')
|
||||
self.check_invalid(INVALID_ADDRESS_2, 'Not a valid Bech32 or Base58 encoding')
|
||||
self.check_invalid(INVALID_ADDRESS, 'Invalid or unsupported Segwit (Bech32) or Base58 encoding.')
|
||||
self.check_invalid(INVALID_ADDRESS_2, 'Invalid or unsupported Segwit (Bech32) or Base58 encoding.')
|
||||
|
||||
def test_getaddressinfo(self):
|
||||
node = self.nodes[0]
|
||||
|
||||
assert_raises_rpc_error(-5, "Invalid Bech32 address data size", node.getaddressinfo, BECH32_INVALID_SIZE)
|
||||
assert_raises_rpc_error(-5, "Invalid Bech32 address program size (41 byte)", node.getaddressinfo, BECH32_INVALID_SIZE)
|
||||
|
||||
assert_raises_rpc_error(-5, "Not a valid Bech32 or Base58 encoding", node.getaddressinfo, BECH32_INVALID_PREFIX)
|
||||
assert_raises_rpc_error(-5, "Invalid or unsupported Segwit (Bech32) or Base58 encoding.", node.getaddressinfo, BECH32_INVALID_PREFIX)
|
||||
|
||||
assert_raises_rpc_error(-5, "Invalid prefix for Base58-encoded address", node.getaddressinfo, BASE58_INVALID_PREFIX)
|
||||
assert_raises_rpc_error(-5, "Invalid or unsupported Base58-encoded address.", node.getaddressinfo, BASE58_INVALID_PREFIX)
|
||||
|
||||
assert_raises_rpc_error(-5, "Not a valid Bech32 or Base58 encoding", node.getaddressinfo, INVALID_ADDRESS)
|
||||
assert_raises_rpc_error(-5, "Invalid or unsupported Segwit (Bech32) or Base58 encoding.", node.getaddressinfo, INVALID_ADDRESS)
|
||||
|
||||
def run_test(self):
|
||||
self.test_validateaddress()
|
||||
|
||||
203
test/functional/rpc_validateaddress.py
Executable file
203
test/functional/rpc_validateaddress.py
Executable file
@@ -0,0 +1,203 @@
|
||||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2023 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 validateaddress for main chain"""
|
||||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
|
||||
from test_framework.util import assert_equal
|
||||
|
||||
INVALID_DATA = [
|
||||
# BIP 173
|
||||
(
|
||||
"tc1qw508d6qejxtdg4y5r3zarvary0c5xw7kg3g4ty",
|
||||
"Invalid or unsupported Segwit (Bech32) or Base58 encoding.", # Invalid hrp
|
||||
[],
|
||||
),
|
||||
("bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t5", "Invalid Bech32 checksum", [41]),
|
||||
(
|
||||
"BC13W508D6QEJXTDG4Y5R3ZARVARY0C5XW7KN40WF2",
|
||||
"Version 1+ witness address must use Bech32m checksum",
|
||||
[],
|
||||
),
|
||||
(
|
||||
"bc1rw5uspcuh",
|
||||
"Version 1+ witness address must use Bech32m checksum", # Invalid program length
|
||||
[],
|
||||
),
|
||||
(
|
||||
"bc10w508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7kw5rljs90",
|
||||
"Version 1+ witness address must use Bech32m checksum", # Invalid program length
|
||||
[],
|
||||
),
|
||||
(
|
||||
"BC1QR508D6QEJXTDG4Y5R3ZARVARYV98GJ9P",
|
||||
"Invalid Bech32 v0 address program size (16 byte), per BIP141",
|
||||
[],
|
||||
),
|
||||
(
|
||||
"tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sL5k7",
|
||||
"Invalid or unsupported Segwit (Bech32) or Base58 encoding.", # tb1, Mixed case
|
||||
[],
|
||||
),
|
||||
(
|
||||
"BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KV8F3t4",
|
||||
"Invalid character or mixed case", # bc1, Mixed case, not in BIP 173 test vectors
|
||||
[40],
|
||||
),
|
||||
(
|
||||
"bc1zw508d6qejxtdg4y5r3zarvaryvqyzf3du",
|
||||
"Version 1+ witness address must use Bech32m checksum", # Wrong padding
|
||||
[],
|
||||
),
|
||||
(
|
||||
"tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3pjxtptv",
|
||||
"Invalid or unsupported Segwit (Bech32) or Base58 encoding.", # tb1, Non-zero padding in 8-to-5 conversion
|
||||
[],
|
||||
),
|
||||
("bc1gmk9yu", "Empty Bech32 data section", []),
|
||||
# BIP 350
|
||||
(
|
||||
"tc1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vq5zuyut",
|
||||
"Invalid or unsupported Segwit (Bech32) or Base58 encoding.", # Invalid human-readable part
|
||||
[],
|
||||
),
|
||||
(
|
||||
"bc1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vqh2y7hd",
|
||||
"Version 1+ witness address must use Bech32m checksum", # Invalid checksum (Bech32 instead of Bech32m)
|
||||
[],
|
||||
),
|
||||
(
|
||||
"tb1z0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vqglt7rf",
|
||||
"Invalid or unsupported Segwit (Bech32) or Base58 encoding.", # tb1, Invalid checksum (Bech32 instead of Bech32m)
|
||||
[],
|
||||
),
|
||||
(
|
||||
"BC1S0XLXVLHEMJA6C4DQV22UAPCTQUPFHLXM9H8Z3K2E72Q4K9HCZ7VQ54WELL",
|
||||
"Version 1+ witness address must use Bech32m checksum", # Invalid checksum (Bech32 instead of Bech32m)
|
||||
[],
|
||||
),
|
||||
(
|
||||
"bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kemeawh",
|
||||
"Version 0 witness address must use Bech32 checksum", # Invalid checksum (Bech32m instead of Bech32)
|
||||
[],
|
||||
),
|
||||
(
|
||||
"tb1q0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vq24jc47",
|
||||
"Invalid or unsupported Segwit (Bech32) or Base58 encoding.", # tb1, Invalid checksum (Bech32m instead of Bech32)
|
||||
[],
|
||||
),
|
||||
(
|
||||
"bc1p38j9r5y49hruaue7wxjce0updqjuyyx0kh56v8s25huc6995vvpql3jow4",
|
||||
"Invalid Base 32 character", # Invalid character in checksum
|
||||
[59],
|
||||
),
|
||||
(
|
||||
"BC130XLXVLHEMJA6C4DQV22UAPCTQUPFHLXM9H8Z3K2E72Q4K9HCZ7VQ7ZWS8R",
|
||||
"Invalid Bech32 address witness version",
|
||||
[],
|
||||
),
|
||||
("bc1pw5dgrnzv", "Invalid Bech32 address program size (1 byte)", []),
|
||||
(
|
||||
"bc1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7v8n0nx0muaewav253zgeav",
|
||||
"Invalid Bech32 address program size (41 byte)",
|
||||
[],
|
||||
),
|
||||
(
|
||||
"BC1QR508D6QEJXTDG4Y5R3ZARVARYV98GJ9P",
|
||||
"Invalid Bech32 v0 address program size (16 byte), per BIP141",
|
||||
[],
|
||||
),
|
||||
(
|
||||
"tb1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vq47Zagq",
|
||||
"Invalid or unsupported Segwit (Bech32) or Base58 encoding.", # tb1, Mixed case
|
||||
[],
|
||||
),
|
||||
(
|
||||
"bc1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7v07qwwzcrf",
|
||||
"Invalid padding in Bech32 data section", # zero padding of more than 4 bits
|
||||
[],
|
||||
),
|
||||
(
|
||||
"tb1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vpggkg4j",
|
||||
"Invalid or unsupported Segwit (Bech32) or Base58 encoding.", # tb1, Non-zero padding in 8-to-5 conversion
|
||||
[],
|
||||
),
|
||||
("bc1gmk9yu", "Empty Bech32 data section", []),
|
||||
]
|
||||
VALID_DATA = [
|
||||
# BIP 350
|
||||
(
|
||||
"BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KV8F3T4",
|
||||
"0014751e76e8199196d454941c45d1b3a323f1433bd6",
|
||||
),
|
||||
# (
|
||||
# "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7",
|
||||
# "00201863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262",
|
||||
# ),
|
||||
(
|
||||
"bc1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3qccfmv3",
|
||||
"00201863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262",
|
||||
),
|
||||
(
|
||||
"bc1pw508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7kt5nd6y",
|
||||
"5128751e76e8199196d454941c45d1b3a323f1433bd6751e76e8199196d454941c45d1b3a323f1433bd6",
|
||||
),
|
||||
("BC1SW50QGDZ25J", "6002751e"),
|
||||
("bc1zw508d6qejxtdg4y5r3zarvaryvaxxpcs", "5210751e76e8199196d454941c45d1b3a323"),
|
||||
# (
|
||||
# "tb1qqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvsesrxh6hy",
|
||||
# "0020000000c4a5cad46221b2a187905e5266362b99d5e91c6ce24d165dab93e86433",
|
||||
# ),
|
||||
(
|
||||
"bc1qqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvses5wp4dt",
|
||||
"0020000000c4a5cad46221b2a187905e5266362b99d5e91c6ce24d165dab93e86433",
|
||||
),
|
||||
# (
|
||||
# "tb1pqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvsesf3hn0c",
|
||||
# "5120000000c4a5cad46221b2a187905e5266362b99d5e91c6ce24d165dab93e86433",
|
||||
# ),
|
||||
(
|
||||
"bc1pqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvses7epu4h",
|
||||
"5120000000c4a5cad46221b2a187905e5266362b99d5e91c6ce24d165dab93e86433",
|
||||
),
|
||||
(
|
||||
"bc1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vqzk5jj0",
|
||||
"512079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798",
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
class ValidateAddressMainTest(BitcoinTestFramework):
|
||||
def set_test_params(self):
|
||||
self.setup_clean_chain = True
|
||||
self.chain = "" # main
|
||||
self.num_nodes = 1
|
||||
self.extra_args = [["-prune=899"]] * self.num_nodes
|
||||
|
||||
def check_valid(self, addr, spk):
|
||||
info = self.nodes[0].validateaddress(addr)
|
||||
assert_equal(info["isvalid"], True)
|
||||
assert_equal(info["scriptPubKey"], spk)
|
||||
assert "error" not in info
|
||||
assert "error_locations" not in info
|
||||
|
||||
def check_invalid(self, addr, error_str, error_locations):
|
||||
res = self.nodes[0].validateaddress(addr)
|
||||
assert_equal(res["isvalid"], False)
|
||||
assert_equal(res["error"], error_str)
|
||||
assert_equal(res["error_locations"], error_locations)
|
||||
|
||||
def test_validateaddress(self):
|
||||
for (addr, error, locs) in INVALID_DATA:
|
||||
self.check_invalid(addr, error, locs)
|
||||
for (addr, spk) in VALID_DATA:
|
||||
self.check_valid(addr, spk)
|
||||
|
||||
def run_test(self):
|
||||
self.test_validateaddress()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
ValidateAddressMainTest().main()
|
||||
@@ -139,6 +139,7 @@ BASE_SCRIPTS = [
|
||||
'feature_fee_estimation.py',
|
||||
'interface_zmq.py',
|
||||
'rpc_invalid_address_message.py',
|
||||
'rpc_validateaddress.py',
|
||||
'interface_bitcoin_cli.py --legacy-wallet',
|
||||
'interface_bitcoin_cli.py --descriptors',
|
||||
'feature_bind_extra.py',
|
||||
|
||||
@@ -629,7 +629,7 @@ class WalletTest(BitcoinTestFramework):
|
||||
assert_equal(total_txs, len(self.nodes[0].listtransactions("*", 99999)))
|
||||
|
||||
# Test getaddressinfo on external address. Note that these addresses are taken from disablewallet.py
|
||||
assert_raises_rpc_error(-5, "Invalid prefix for Base58-encoded address", self.nodes[0].getaddressinfo, "3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy")
|
||||
assert_raises_rpc_error(-5, "Invalid or unsupported Base58-encoded address.", self.nodes[0].getaddressinfo, "3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy")
|
||||
address_info = self.nodes[0].getaddressinfo("mneYUmWYsuk7kySiURxCi3AGxrAqZxLgPZ")
|
||||
assert_equal(address_info['address'], "mneYUmWYsuk7kySiURxCi3AGxrAqZxLgPZ")
|
||||
assert_equal(address_info["scriptPubKey"], "76a9144e3854046c7bd1594ac904e4793b6a45b36dea0988ac")
|
||||
|
||||
Reference in New Issue
Block a user