aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xautogen.sh4
-rw-r--r--build_msvc/bitcoin_config.h6
-rwxr-xr-xci/test/00_setup_env.sh2
-rw-r--r--ci/test/00_setup_env_arm.sh3
-rwxr-xr-xci/test/04_install.sh21
-rw-r--r--configure.ac17
-rwxr-xr-xcontrib/devtools/copyright_header.py4
-rw-r--r--contrib/gitian-descriptors/gitian-linux.yml4
-rw-r--r--contrib/gitian-descriptors/gitian-osx.yml2
-rw-r--r--contrib/gitian-descriptors/gitian-win.yml25
-rw-r--r--contrib/init/bitcoind.conf2
-rw-r--r--contrib/init/bitcoind.init2
-rw-r--r--contrib/init/bitcoind.openrcconf2
-rw-r--r--contrib/init/bitcoind.service1
-rwxr-xr-xcontrib/linearize/linearize-data.py7
-rwxr-xr-xcontrib/seeds/makeseeds.py4
-rw-r--r--doc/bips.md2
-rw-r--r--doc/descriptors.md13
-rw-r--r--doc/release-notes-17056.md4
-rw-r--r--doc/release-notes.md318
-rw-r--r--doc/release-process.md20
-rw-r--r--src/Makefile.am3
-rw-r--r--src/Makefile.qt.include4
-rw-r--r--src/bitcoin-cli.cpp33
-rw-r--r--src/bitcoind.cpp2
-rw-r--r--src/compat/stdin.cpp72
-rw-r--r--src/compat/stdin.h18
-rw-r--r--src/interfaces/node.cpp1
-rw-r--r--src/interfaces/node.h3
-rw-r--r--src/net.h2
-rw-r--r--src/net_processing.cpp23
-rw-r--r--src/policy/feerate.h2
-rw-r--r--src/qt/bitcoin.cpp2
-rw-r--r--src/qt/paymentserver.cpp10
-rw-r--r--src/qt/receivecoinsdialog.cpp13
-rw-r--r--src/qt/sendcoinsdialog.cpp4
-rw-r--r--src/rpc/blockchain.cpp2
-rw-r--r--src/script/descriptor.cpp19
-rw-r--r--src/sync.h4
-rw-r--r--src/test/descriptor_tests.cpp3
-rw-r--r--src/test/fuzz/deserialize.cpp2
-rw-r--r--src/test/fuzz/fuzz.cpp3
-rw-r--r--src/test/fuzz/fuzz.h2
-rw-r--r--src/test/fuzz/script_flags.cpp2
-rw-r--r--src/txdb.cpp2
-rw-r--r--src/txmempool.cpp5
-rw-r--r--src/txmempool.h13
-rw-r--r--src/util/macros.h11
-rw-r--r--src/util/threadnames.cpp5
-rw-r--r--src/util/threadnames.h5
-rw-r--r--src/util/time.h8
-rw-r--r--src/validation.cpp12
-rw-r--r--src/wallet/feebumper.cpp117
-rw-r--r--src/wallet/init.cpp3
-rw-r--r--src/wallet/rpcwallet.cpp21
-rw-r--r--src/wallet/wallet.cpp6
-rw-r--r--src/wallet/wallet.h6
-rw-r--r--test/functional/data/rpc_bip67.json58
-rwxr-xr-xtest/functional/feature_bip68_sequence.py5
-rwxr-xr-xtest/functional/feature_rbf.py2
-rwxr-xr-xtest/functional/mempool_persist.py24
-rwxr-xr-xtest/functional/p2p_feefilter.py23
-rwxr-xr-xtest/functional/rpc_createmultisig.py15
-rw-r--r--test/functional/test_framework/util.py4
-rwxr-xr-xtest/functional/wallet_address_types.py2
-rwxr-xr-xtest/functional/wallet_basic.py2
-rwxr-xr-xtest/functional/wallet_bumpfee.py29
-rwxr-xr-xtest/functional/wallet_import_with_label.py4
68 files changed, 582 insertions, 492 deletions
diff --git a/autogen.sh b/autogen.sh
index 2c434e9ef0..3e922e7e64 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -5,9 +5,9 @@
export LC_ALL=C
set -e
-srcdir="$(dirname $0)"
+srcdir="$(dirname "$0")"
cd "$srcdir"
-if [ -z ${LIBTOOLIZE} ] && GLIBTOOLIZE="$(command -v glibtoolize)"; then
+if [ -z "${LIBTOOLIZE}" ] && GLIBTOOLIZE="$(command -v glibtoolize)"; then
LIBTOOLIZE="${GLIBTOOLIZE}"
export LIBTOOLIZE
fi
diff --git a/build_msvc/bitcoin_config.h b/build_msvc/bitcoin_config.h
index 66cc1208a1..2fe489239d 100644
--- a/build_msvc/bitcoin_config.h
+++ b/build_msvc/bitcoin_config.h
@@ -14,7 +14,7 @@
#define CLIENT_VERSION_MAJOR 0
/* Minor version */
-#define CLIENT_VERSION_MINOR 18
+#define CLIENT_VERSION_MINOR 19
/* Build revision */
#define CLIENT_VERSION_REVISION 99
@@ -346,7 +346,7 @@
#define PACKAGE_NAME "Bitcoin Core"
/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "Bitcoin Core 0.18.99"
+#define PACKAGE_STRING "Bitcoin Core 0.19.99"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "bitcoin"
@@ -355,7 +355,7 @@
#define PACKAGE_URL "https://bitcoincore.org/"
/* Define to the version of this package. */
-#define PACKAGE_VERSION "0.18.99"
+#define PACKAGE_VERSION "0.19.99"
/* Define to necessary symbol if this constant uses a non-standard name on
your system. */
diff --git a/ci/test/00_setup_env.sh b/ci/test/00_setup_env.sh
index 94598835ac..8bc50da2c3 100755
--- a/ci/test/00_setup_env.sh
+++ b/ci/test/00_setup_env.sh
@@ -22,6 +22,8 @@ export MAKEJOBS=${MAKEJOBS:--j4}
# A folder for the ci system to put temporary files (ccache, datadirs for tests, ...)
export BASE_SCRATCH_DIR=${BASE_SCRATCH_DIR:-$BASE_ROOT_DIR/ci/scratch/}
export HOST=${HOST:-x86_64-unknown-linux-gnu}
+# Whether to prefer BusyBox over GNU utilities
+export USE_BUSY_BOX=${USE_BUSY_BOX:-false}
export RUN_UNIT_TESTS=${RUN_UNIT_TESTS:-true}
export RUN_FUNCTIONAL_TESTS=${RUN_FUNCTIONAL_TESTS:-true}
export RUN_FUZZ_TESTS=${RUN_FUZZ_TESTS:-false}
diff --git a/ci/test/00_setup_env_arm.sh b/ci/test/00_setup_env_arm.sh
index ac7ace8c3b..db640015b1 100644
--- a/ci/test/00_setup_env_arm.sh
+++ b/ci/test/00_setup_env_arm.sh
@@ -7,7 +7,8 @@
export LC_ALL=C.UTF-8
export HOST=arm-linux-gnueabihf
-export PACKAGES="python3 g++-arm-linux-gnueabihf"
+export PACKAGES="python3 g++-arm-linux-gnueabihf busybox"
+export USE_BUSY_BOX=true
export RUN_UNIT_TESTS=false
export RUN_FUNCTIONAL_TESTS=false
export GOAL="install"
diff --git a/ci/test/04_install.sh b/ci/test/04_install.sh
index 54d7a9b814..409e87ce04 100755
--- a/ci/test/04_install.sh
+++ b/ci/test/04_install.sh
@@ -33,18 +33,29 @@ if [ -z "$RUN_CI_ON_HOST" ]; then
DOCKER_ID=$(docker run $DOCKER_ADMIN -idt --mount type=bind,src=$BASE_BUILD_DIR,dst=$BASE_BUILD_DIR --mount type=bind,src=$CCACHE_DIR,dst=$CCACHE_DIR -w $BASE_BUILD_DIR --env-file /tmp/env $DOCKER_NAME_TAG)
DOCKER_EXEC () {
- docker exec $DOCKER_ID bash -c "cd $PWD && $*"
+ docker exec $DOCKER_ID bash -c "export PATH=$BASE_SCRATCH_DIR/bins/:\$PATH && cd $PWD && $*"
}
else
echo "Running on host system without docker wrapper"
DOCKER_EXEC () {
- bash -c "cd $PWD && $*"
+ bash -c "export PATH=$BASE_SCRATCH_DIR/bins/:\$PATH && cd $PWD && $*"
}
fi
DOCKER_EXEC free -m -h
-DOCKER_EXEC echo "Number of CPUs \(nproc\): $(nproc)"
+DOCKER_EXEC echo "Number of CPUs \(nproc\):" \$\(nproc\)
${CI_RETRY_EXE} DOCKER_EXEC apt-get update
-${CI_RETRY_EXE} DOCKER_EXEC apt-get install --no-install-recommends --no-upgrade -qq $PACKAGES $DOCKER_PACKAGES
-
+${CI_RETRY_EXE} DOCKER_EXEC apt-get install --no-install-recommends --no-upgrade -y $PACKAGES $DOCKER_PACKAGES
+
+if [ "$USE_BUSY_BOX" = "true" ]; then
+ echo "Setup to use BusyBox utils"
+ DOCKER_EXEC mkdir -p $BASE_SCRATCH_DIR/bins/
+ # tar excluded for now because it requires passing in the exact archive type in ./depends (fixed in later BusyBox version)
+ # find excluded for now because it does not recognize the -delete option in ./depends (fixed in later BusyBox version)
+ # ar excluded for now because it does not recognize the -q option in ./depends (unknown if fixed)
+ # shellcheck disable=SC1010
+ DOCKER_EXEC for util in \$\(busybox --list \| grep -v "^ar$" \| grep -v "^tar$" \| grep -v "^find$"\)\; do ln -s \$\(command -v busybox\) $BASE_SCRATCH_DIR/bins/\$util\; done
+ # Print BusyBox version
+ DOCKER_EXEC patch --help
+fi
diff --git a/configure.ac b/configure.ac
index 2445b72683..d25e0f4496 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,7 +1,7 @@
dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N)
AC_PREREQ([2.60])
define(_CLIENT_VERSION_MAJOR, 0)
-define(_CLIENT_VERSION_MINOR, 18)
+define(_CLIENT_VERSION_MINOR, 19)
define(_CLIENT_VERSION_REVISION, 99)
define(_CLIENT_VERSION_BUILD, 0)
define(_CLIENT_VERSION_RC, 0)
@@ -76,6 +76,10 @@ fi
AC_PROG_OBJCXX
])
+dnl Since libtool 1.5.2 (released 2004-01-25), on Linux libtool no longer
+dnl sets RPATH for any directories in the dynamic linker search path.
+dnl See more: https://wiki.debian.org/RpathIssue
+LT_PREREQ([1.5.2])
dnl Libtool init checks.
LT_INIT([pic-only])
@@ -1660,17 +1664,6 @@ AC_CONFIG_SUBDIRS([src/secp256k1])
AC_OUTPUT
-dnl Taken from https://wiki.debian.org/RpathIssue
-case $host in
- *-*-linux-gnu)
- AC_MSG_RESULT([Fixing libtool for -rpath problems.])
- sed < libtool > libtool-2 \
- 's/^hardcode_libdir_flag_spec.*$'/'hardcode_libdir_flag_spec=" -D__LIBTOOL_IS_A_FOOL__ "/'
- mv libtool-2 libtool
- chmod 755 libtool
- ;;
-esac
-
dnl Replace the BUILDDIR path with the correct Windows path if compiling on Native Windows
case ${OS} in
*Windows*)
diff --git a/contrib/devtools/copyright_header.py b/contrib/devtools/copyright_header.py
index 67e77bc63d..5307b04197 100755
--- a/contrib/devtools/copyright_header.py
+++ b/contrib/devtools/copyright_header.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2016-2018 The Bitcoin Core developers
+# Copyright (c) 2016-2019 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -34,7 +34,7 @@ EXCLUDE_DIRS = [
"src/univalue/",
]
-INCLUDE = ['*.h', '*.cpp', '*.cc', '*.c', '*.mm', '*.py']
+INCLUDE = ['*.h', '*.cpp', '*.cc', '*.c', '*.mm', '*.py', '*.sh', '*.bash-completion']
INCLUDE_COMPILED = re.compile('|'.join([fnmatch.translate(m) for m in INCLUDE]))
def applies_to_file(filename):
diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml
index c50750ed44..e0b9f74397 100644
--- a/contrib/gitian-descriptors/gitian-linux.yml
+++ b/contrib/gitian-descriptors/gitian-linux.yml
@@ -1,5 +1,5 @@
---
-name: "bitcoin-core-linux-0.19"
+name: "bitcoin-core-linux-0.20"
enable_cache: true
distro: "ubuntu"
suites:
@@ -181,7 +181,7 @@ script: |
rm -rf ${DISTNAME}/lib/pkgconfig
find ${DISTNAME}/bin -type f -executable -print0 | xargs -0 -n1 -I{} ../contrib/devtools/split-debug.sh {} {} {}.dbg
find ${DISTNAME}/lib -type f -print0 | xargs -0 -n1 -I{} ../contrib/devtools/split-debug.sh {} {} {}.dbg
- cp ../doc/README.md ${DISTNAME}/
+ cp ../README.md ${DISTNAME}/
find ${DISTNAME} -not -name "*.dbg" | sort | tar --mtime="$REFERENCE_DATETIME" --no-recursion --mode='u+rw,go+r-w,a+X' --owner=0 --group=0 -c -T - | gzip -9n > ${OUTDIR}/${DISTNAME}-${i}.tar.gz
find ${DISTNAME} -name "*.dbg" | sort | tar --mtime="$REFERENCE_DATETIME" --no-recursion --mode='u+rw,go+r-w,a+X' --owner=0 --group=0 -c -T - | gzip -9n > ${OUTDIR}/${DISTNAME}-${i}-debug.tar.gz
cd ../../
diff --git a/contrib/gitian-descriptors/gitian-osx.yml b/contrib/gitian-descriptors/gitian-osx.yml
index 8c51ce7159..a563bef778 100644
--- a/contrib/gitian-descriptors/gitian-osx.yml
+++ b/contrib/gitian-descriptors/gitian-osx.yml
@@ -1,5 +1,5 @@
---
-name: "bitcoin-core-osx-0.19"
+name: "bitcoin-core-osx-0.20"
enable_cache: true
distro: "ubuntu"
suites:
diff --git a/contrib/gitian-descriptors/gitian-win.yml b/contrib/gitian-descriptors/gitian-win.yml
index f227c6ad92..d5f2c1ad35 100644
--- a/contrib/gitian-descriptors/gitian-win.yml
+++ b/contrib/gitian-descriptors/gitian-win.yml
@@ -1,5 +1,5 @@
---
-name: "bitcoin-core-win-0.19"
+name: "bitcoin-core-win-0.20"
enable_cache: true
distro: "ubuntu"
suites:
@@ -22,7 +22,6 @@ packages:
- "zip"
- "ca-certificates"
- "python3"
-- "rename"
remotes:
- "url": "https://github.com/bitcoin/bitcoin.git"
"dir": "bitcoin"
@@ -124,14 +123,11 @@ script: |
make dist
SOURCEDIST=`echo bitcoin-*.tar.gz`
DISTNAME=`echo ${SOURCEDIST} | sed 's/.tar.*//'`
-
# Correct tar file order
mkdir -p temp
pushd temp
tar -xf ../$SOURCEDIST
find bitcoin-* | sort | tar --mtime="$REFERENCE_DATETIME" --no-recursion --mode='u+rw,go+r-w,a+X' --owner=0 --group=0 -c -T - | gzip -9n > ../$SOURCEDIST
- mkdir -p $OUTDIR/src
- cp ../$SOURCEDIST $OUTDIR/src
popd
# Workaround for tarball not building with the bare tag version (prep)
@@ -157,24 +153,27 @@ script: |
make ${MAKEOPTS} -C src check-security
make deploy
make install DESTDIR=${INSTALLPATH}
- rename 's/-setup\.exe$/-setup-unsigned.exe/' *-setup.exe
- cp -f bitcoin-*setup*.exe $OUTDIR/
+ (
+ SETUP_EXE="$(basename "$(echo ./*-setup.exe)")"
+ cp -f "$SETUP_EXE" "${OUTDIR}/${SETUP_EXE/%-setup.exe/-setup-unsigned.exe}"
+ )
cd installed
mv ${DISTNAME}/bin/*.dll ${DISTNAME}/lib/
find . -name "lib*.la" -delete
find . -name "lib*.a" -delete
rm -rf ${DISTNAME}/lib/pkgconfig
- find ${DISTNAME}/bin -type f -executable -exec ${i}-objcopy --only-keep-debug {} {}.dbg \; -exec ${i}-strip -s {} \; -exec ${i}-objcopy --add-gnu-debuglink={}.dbg {} \;
- find ${DISTNAME}/lib -type f -exec ${i}-objcopy --only-keep-debug {} {}.dbg \; -exec ${i}-strip -s {} \; -exec ${i}-objcopy --add-gnu-debuglink={}.dbg {} \;
- find ${DISTNAME} -not -name "*.dbg" -type f | sort | zip -X@ ${OUTDIR}/${DISTNAME}-${i}.zip
- find ${DISTNAME} -name "*.dbg" -type f | sort | zip -X@ ${OUTDIR}/${DISTNAME}-${i}-debug.zip
+ find ${DISTNAME}/bin -type f -executable -print0 | xargs -0 -n1 -I{} ../contrib/devtools/split-debug.sh {} {} {}.dbg
+ find ${DISTNAME}/lib -type f -print0 | xargs -0 -n1 -I{} ../contrib/devtools/split-debug.sh {} {} {}.dbg
+ cp ../doc/README_windows.txt ${DISTNAME}/readme.txt
+ find ${DISTNAME} -not -name "*.dbg" -type f | sort | zip -X@ ${OUTDIR}/${DISTNAME}-${i//x86_64-w64-mingw32/win64}.zip
+ find ${DISTNAME} -name "*.dbg" -type f | sort | zip -X@ ${OUTDIR}/${DISTNAME}-${i//x86_64-w64-mingw32/win64}-debug.zip
cd ../../
rm -rf distsrc-${i}
done
+ mkdir -p $OUTDIR/src
+ mv $SOURCEDIST $OUTDIR/src
cp -rf contrib/windeploy $BUILD_DIR
cd $BUILD_DIR/windeploy
mkdir unsigned
cp $OUTDIR/bitcoin-*setup-unsigned.exe unsigned/
find . | sort | tar --mtime="$REFERENCE_DATETIME" --no-recursion --mode='u+rw,go+r-w,a+X' --owner=0 --group=0 -c -T - | gzip -9n > ${OUTDIR}/${DISTNAME}-win-unsigned.tar.gz
- mv ${OUTDIR}/${DISTNAME}-x86_64-*-debug.zip ${OUTDIR}/${DISTNAME}-win64-debug.zip
- mv ${OUTDIR}/${DISTNAME}-x86_64-*.zip ${OUTDIR}/${DISTNAME}-win64.zip
diff --git a/contrib/init/bitcoind.conf b/contrib/init/bitcoind.conf
index de4ea0ed52..dde1bd0c4d 100644
--- a/contrib/init/bitcoind.conf
+++ b/contrib/init/bitcoind.conf
@@ -16,7 +16,7 @@ expect fork
respawn
respawn limit 5 120
-kill timeout 60
+kill timeout 600
pre-start script
# this will catch non-existent config files
diff --git a/contrib/init/bitcoind.init b/contrib/init/bitcoind.init
index 0c95baf3a1..19e1f76d09 100644
--- a/contrib/init/bitcoind.init
+++ b/contrib/init/bitcoind.init
@@ -39,7 +39,7 @@ start() {
stop() {
echo -n $"Stopping $prog: "
- killproc $prog
+ killproc $prog -t600
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && rm -f $lockfile
diff --git a/contrib/init/bitcoind.openrcconf b/contrib/init/bitcoind.openrcconf
index f70e25cb5f..c8a22a08d9 100644
--- a/contrib/init/bitcoind.openrcconf
+++ b/contrib/init/bitcoind.openrcconf
@@ -30,4 +30,4 @@
# Note that this will be mapped as argument to start-stop-daemon's
# '--retry' option, which means you can specify a retry schedule
# here. For more information see man 8 start-stop-daemon.
-BITCOIND_SIGTERM_TIMEOUT=60
+BITCOIND_SIGTERM_TIMEOUT=600
diff --git a/contrib/init/bitcoind.service b/contrib/init/bitcoind.service
index 34c3e7b3ab..8b308644b1 100644
--- a/contrib/init/bitcoind.service
+++ b/contrib/init/bitcoind.service
@@ -29,6 +29,7 @@ ExecStartPre=/bin/chgrp bitcoin /etc/bitcoin
Type=forking
PIDFile=/run/bitcoind/bitcoind.pid
Restart=on-failure
+TimeoutStopSec=600
# Directory creation and permissions
####################################
diff --git a/contrib/linearize/linearize-data.py b/contrib/linearize/linearize-data.py
index 95754ab937..863b22f6b1 100755
--- a/contrib/linearize/linearize-data.py
+++ b/contrib/linearize/linearize-data.py
@@ -213,8 +213,11 @@ class BlockDataCopier:
inMagic = inhdr[:4]
if (inMagic != self.settings['netmagic']):
- print("Invalid magic: " + inMagic.hex())
- return
+ # Seek backwards 7 bytes (skipping the first byte in the previous search)
+ # and continue searching from the new position if the magic bytes are not
+ # found.
+ self.inF.seek(-7, os.SEEK_CUR)
+ continue
inLenLE = inhdr[4:]
su = struct.unpack("<I", inLenLE)
inLen = su[0] - 80 # length without header
diff --git a/contrib/seeds/makeseeds.py b/contrib/seeds/makeseeds.py
index 2f7697e0b1..ec589d4c02 100755
--- a/contrib/seeds/makeseeds.py
+++ b/contrib/seeds/makeseeds.py
@@ -123,7 +123,7 @@ def filtermultiport(ips):
def lookup_asn(net, ip):
'''
- Look up the asn for an IP (4 or 6) address by querying cymry.com, or None
+ Look up the asn for an IP (4 or 6) address by querying cymru.com, or None
if it could not be found.
'''
try:
@@ -187,7 +187,7 @@ def main():
# Skip entries with invalid address.
ips = [ip for ip in ips if ip is not None]
print('%s Skip entries with invalid address' % (ip_stats(ips)), file=sys.stderr)
- # Skip duplicattes (in case multiple seeds files were concatenated)
+ # Skip duplicates (in case multiple seeds files were concatenated)
ips = dedup(ips)
print('%s After removing duplicates' % (ip_stats(ips)), file=sys.stderr)
# Skip entries from suspicious hosts.
diff --git a/doc/bips.md b/doc/bips.md
index 570244aeae..90d0e341df 100644
--- a/doc/bips.md
+++ b/doc/bips.md
@@ -35,6 +35,6 @@ BIPs that are implemented by Bitcoin Core (up-to-date up to **v0.19.0**):
* [`BIP 152`](https://github.com/bitcoin/bips/blob/master/bip-0152.mediawiki): Compact block transfer and related optimizations are used as of **v0.13.0** ([PR 8068](https://github.com/bitcoin/bitcoin/pull/8068)).
- [`BIP 158`](https://github.com/bitcoin/bips/blob/master/bip-0158.mediawiki): Compact Block Filters for Light Clients can be indexed as of **v0.19.0** ([PR #14121](https://github.com/bitcoin/bitcoin/pull/14121)).
* [`BIP 159`](https://github.com/bitcoin/bips/blob/master/bip-0159.mediawiki): The NODE_NETWORK_LIMITED service bit is signalled as of **v0.16.0** ([PR 11740](https://github.com/bitcoin/bitcoin/pull/11740)), and such nodes are connected to as of **v0.17.0** ([PR 10387](https://github.com/bitcoin/bitcoin/pull/10387)).
-* [`BIP 173`](https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki): Bech32 addresses for native Segregated Witness outputs are supported as of **v0.16.0** ([PR 11167](https://github.com/bitcoin/bitcoin/pull/11167)).
+* [`BIP 173`](https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki): Bech32 addresses for native Segregated Witness outputs are supported as of **v0.16.0** ([PR 11167](https://github.com/bitcoin/bitcoin/pull/11167)). Bech32 addresses are generated by default as of **v0.20.0** ([PR 16884](https://github.com/bitcoin/bitcoin/pull/16884)).
* [`BIP 174`](https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki): RPCs to operate on Partially Signed Bitcoin Transactions (PSBT) are present as of **v0.17.0** ([PR 13557](https://github.com/bitcoin/bitcoin/pull/13557)).
* [`BIP 176`](https://github.com/bitcoin/bips/blob/master/bip-0176.mediawiki): Bits Denomination [QT only] is supported as of **v0.16.0** ([PR 12035](https://github.com/bitcoin/bitcoin/pull/12035)).
diff --git a/doc/descriptors.md b/doc/descriptors.md
index dbdac2c5b6..a98f43737e 100644
--- a/doc/descriptors.md
+++ b/doc/descriptors.md
@@ -23,6 +23,7 @@ Output descriptors currently support:
- Pay-to-script-hash scripts (P2SH), through the `sh` function.
- Pay-to-witness-script-hash scripts (P2WSH), through the `wsh` function.
- Multisig scripts, through the `multi` function.
+- Multisig scripts where the public keys are sorted lexicographically, through the `sortedmulti` function.
- Any type of supported address through the `addr` function.
- Raw hex scripts through the `raw` function.
- Public keys (compressed and uncompressed) in hex notation, or BIP32 extended pubkeys with derivation paths.
@@ -37,12 +38,14 @@ Output descriptors currently support:
- `sh(wsh(pkh(02e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13)))` describes an (overly complicated) P2SH-P2WSH-P2PKH output with the specified public key.
- `multi(1,022f8bde4d1a07209355b4a7250a5c5128e88b84bddc619ab7cba8d569b240efe4,025cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc)` describes a bare *1-of-2* multisig output with keys in the specified order.
- `sh(multi(2,022f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01,03acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbe))` describes a P2SH *2-of-2* multisig output with keys in the specified order.
+- `sh(sortedmulti(2,03acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbe,022f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01))` describes a P2SH *2-of-2* multisig output with keys sorted lexicographically in the resulting redeemScript.
- `wsh(multi(2,03a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7,03774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cb,03d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a))` describes a P2WSH *2-of-3* multisig output with keys in the specified order.
- `sh(wsh(multi(1,03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8,03499fdf9e895e719cfd64e67f07d38e3226aa7b63678949e6e49b241a60e823e4,02d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e)))` describes a P2SH-P2WSH *1-of-3* multisig output with keys in the specified order.
- `pk(xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8)` describes a P2PK output with the public key of the specified xpub.
- `pkh(xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw/1'/2)` describes a P2PKH output with child key *1'/2* of the specified xpub.
- `pkh([d34db33f/44'/0'/0']xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1/*)` describes a set of P2PKH outputs, but additionally specifies that the specified xpub is a child of a master with fingerprint `d34db33f`, and derived using path `44'/0'/0'`.
- `wsh(multi(1,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/1/0/*,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/0/0/*))` describes a set of *1-of-2* P2WSH multisig outputs where the first multisig key is the *1/0/`i`* child of the first specified xpub and the second multisig key is the *0/0/`i`* child of the second specified xpub, and `i` is any number in a configurable range (`0-1000` by default).
+- `wsh(sortedmulti(1,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/1/0/*,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/0/0/*))` describes a set of *1-of-2* P2WSH multisig outputs where one multisig key is the *1/0/`i`* child of the first specified xpub and the other multisig key is the *0/0/`i`* child of the second specified xpub, and `i` is any number in a configurable range (`0-1000` by default). The order of public keys in the resulting witnessScripts is determined by the lexicographic order of the public keys at that index.
## Reference
@@ -56,6 +59,7 @@ Descriptors consist of several types of expressions. The top level expression is
- `wpkh(KEY)` (not inside `wsh`): P2WPKH output for the given compressed pubkey.
- `combo(KEY)` (top level only): an alias for the collection of `pk(KEY)` and `pkh(KEY)`. If the key is compressed, it also includes `wpkh(KEY)` and `sh(wpkh(KEY))`.
- `multi(k,KEY_1,KEY_2,...,KEY_n)` (anywhere): k-of-n multisig script.
+- `sortedmulti(k,KEY_1,KEY_2,...,KEY_n)` (anywhere): k-of-n multisig script with keys sorted lexicographically in the resulting script.
- `addr(ADDR)` (top level only): the script which ADDR expands to.
- `raw(HEX)` (top level only): the script whose hex encoding is HEX.
@@ -101,11 +105,12 @@ not contain "p2" for brevity.
Several pieces of software use multi-signature (multisig) scripts based
on Bitcoin's OP_CHECKMULTISIG opcode. To support these, we introduce the
-`multi(k,key_1,key_2,...,key_n)` function. It represents a *k-of-n*
+`multi(k,key_1,key_2,...,key_n)` and `sortedmulti(k,key_1,key_2,...,key_n)`
+functions. They represent a *k-of-n*
multisig policy, where any *k* out of the *n* provided `KEY` expressions must
sign.
-Key order is significant. A `multi()` expression describes a multisig script
+Key order is significant for `multi()`. A `multi()` expression describes a multisig script
with keys in the specified order, and in a search for TXOs, it will not match
outputs with multisig scriptPubKeys that have the same keys in a different
order. Also, to prevent a combinatorial explosion of the search space, if more
@@ -114,6 +119,10 @@ or `*'`, the `multi()` expression only matches multisig scripts with the `i`th
child key from each wildcard path in lockstep, rather than scripts with any
combination of child keys from each wildcard path.
+Key order does not matter for `sortedmulti()`. `sortedmulti()` behaves in the same way
+as `multi()` does but the keys are reordered in the resulting script such that they
+are lexicographically ordered as described in BIP67.
+
### BIP32 derived keys and chains
Most modern wallet software and hardware uses keys that are derived using
diff --git a/doc/release-notes-17056.md b/doc/release-notes-17056.md
new file mode 100644
index 0000000000..23d5a8c8cd
--- /dev/null
+++ b/doc/release-notes-17056.md
@@ -0,0 +1,4 @@
+Low-level RPC Changes
+===
+
+- A new descriptor type `sortedmulti(...)` has been added to support multisig scripts where the public keys are sorted lexicographically in the resulting script.
diff --git a/doc/release-notes.md b/doc/release-notes.md
index 71dc40e66c..ea82962e75 100644
--- a/doc/release-notes.md
+++ b/doc/release-notes.md
@@ -39,7 +39,7 @@ installer (on Windows) or just copy over `/Applications/Bitcoin-Qt` (on Mac)
or `bitcoind`/`bitcoin-qt` (on Linux).
Upgrading directly from a version of Bitcoin Core that has reached its EOL is
-possible, but might take some time if the datadir needs to be migrated. Old
+possible, but it might take some time if the datadir needs to be migrated. Old
wallet versions of Bitcoin Core are generally supported.
Compatibility
@@ -52,340 +52,49 @@ to use Bitcoin Core on unsupported systems.
Bitcoin Core should also work on most other Unix-like systems but is not
as frequently tested on them.
-From 0.17.0 onwards, macOS <10.10 is no longer supported. 0.17.0 is
-built using Qt 5.9.x, which doesn't support versions of macOS older than
-10.10. Additionally, Bitcoin Core does not yet change appearance when
+From Bitcoin Core 0.17.0 onwards, macOS versions earlier than 10.10 are no
+longer supported, as Bitcoin Core is now built using Qt 5.9.x which requires
+macOS 10.10+. Additionally, Bitcoin Core does not yet change appearance when
macOS "dark mode" is activated.
-In addition to previously-supported CPU platforms, this release's
-pre-compiled distribution also provides binaries for the RISC-V
-platform.
+In addition to previously supported CPU platforms, this release's pre-compiled
+distribution provides binaries for the RISC-V platform.
Notable changes
===============
-New user documentation
-----------------------
-
-- [Reduce memory](https://github.com/bitcoin/bitcoin/blob/master/doc/reduce-memory.md)
- suggests configuration tweaks for running Bitcoin Core on systems with
- limited memory. (#16339)
-
New RPCs
--------
-- `getbalances` returns an object with all balances (`mine`,
- `untrusted_pending` and `immature`). Please refer to the RPC help of
- `getbalances` for details. The new RPC is intended to replace
- `getbalance`, `getunconfirmedbalance`, and the balance fields in
- `getwalletinfo`. These old calls and fields may be removed in a
- future version. (#15930, #16239)
-
-- `setwalletflag` sets and unsets wallet flags that enable or disable
- features specific to that existing wallet, such as the new
- `avoid_reuse` feature documented elsewhere in these release notes.
- (#13756)
-
-- `getblockfilter` gets the BIP158 filter for the specified block. This
- RPC is only enabled if block filters have been created using the
- `-blockfilterindex` configuration option. (#14121)
-
New settings
------------
-- `-blockfilterindex` enables the creation of BIP158 block filters for
- the entire blockchain. Filters will be created in the background and
- currently use about 4 GiB of space. Note: this version of Bitcoin
- Core does not serve block filters over the P2P network, although the
- local user may obtain block filters using the `getblockfilter` RPC.
- (#14121)
-
Updated settings
----------------
-- `whitebind` and `whitelist` now accept a list of permissions to
- provide peers connecting using the indicated interfaces or IP
- addresses. If no permissions are specified with an address or CIDR
- network, the implicit default permissions are the same as previous
- releases. See the `bitcoind -help` output for these two options for
- details about the available permissions. (#16248)
-
Updated RPCs
------------
Note: some low-level RPC changes mainly useful for testing are described in the
Low-level Changes section below.
-- `sendmany` no longer has a `minconf` argument. This argument was not
- well specified and would lead to RPC errors even when the wallet's
- coin selection succeeded. Users who want to influence coin selection
- can use the existing `-spendzeroconfchange`, `-limitancestorcount`,
- `-limitdescendantcount` and `-walletrejectlongchains` configuration
- arguments. (#15596)
-
-- `getbalance` and `sendtoaddress`, plus the new RPCs `getbalances` and
- `createwallet`, now accept an "avoid_reuse" parameter that controls
- whether already used addresses should be included in the operation.
- Additionally, `sendtoaddress` will avoid partial spends when
- `avoid_reuse` is enabled even if this feature is not already enabled
- via the `-avoidpartialspends` command line flag because not doing so
- would risk using up the "wrong" UTXO for an address reuse case.
- (#13756)
-
-- RPCs which have an `include_watchonly` argument or `includeWatching` option now default to `true` for watch-only
- wallets. Affected RPCs are: `getbalance`, `listreceivedbyaddress`, `listreceivedbylabel`, `listtransactions`,
- `listsinceblock`, `gettransaction`, `walletcreatefundedpsbt`, and `fundrawtransaction`. (#16383)
-
-- `listunspent` now returns a "reused" bool for each output if the
- wallet flag "avoid_reuse" is enabled. (#13756)
-
-- `getblockstats` now uses BlockUndo data instead of the transaction
- index, making it much faster, no longer dependent on the `-txindex`
- configuration option, and functional for all non-pruned blocks.
- (#14802)
-
-- `utxoupdatepsbt` now accepts a `descriptors` parameter that will fill
- out input and output scripts and keys when known. P2SH-witness inputs
- will be filled in from the UTXO set when a descriptor is provided that
- shows they're spending segwit outputs. See the RPC help text for full
- details. (#15427)
-
-- `sendrawtransaction` and `testmempoolaccept` no longer accept a
- `allowhighfees` parameter to fail mempool acceptance if the
- transaction fee exceedes the value of the configuration option
- `-maxtxfee`. Now there is a hardcoded default maximum feerate that
- can be changed when calling either RPC using a `maxfeerate` parameter.
- (#15620)
-
-- `getmempoolancestors`, `getmempooldescendants`, `getmempoolentry`, and
- `getrawmempool` no longer return a `size` field unless the
- configuration option `-deprecatedrpc=size` is used. Instead a new
- `vsize` field is returned with the transaction's virtual size
- (consistent with other RPCs such as `getrawtransaction`). (#15637)
-
-- `getwalletinfo` now includes a `scanning` field that is either `false`
- (no scanning) or an object with information about the duration and
- progress of the wallet's scanning historical blocks for transactions
- affecting its balances. (#15730)
-
-- `gettransaction` now accepts a third (boolean) argument `verbose`. If
- set to `true`, a new `decoded` field will be added to the response containing
- the decoded transaction. This field is equivalent to RPC `decoderawtransaction`,
- or RPC `getrawtransaction` when `verbose` is passed.
-
-- `createwallet` accepts a new `passphrase` parameter. If set, this
- will create the new wallet encrypted with the given passphrase. If
- unset (the default) or set to an empty string, no encryption will be
- used. (#16394)
-
-- `getchaintxstats` RPC now returns the additional key of
- `window_final_block_height`.
-
-- `getmempoolentry` now provides a `weight` field containing the
- transaction weight as defined in BIP141. (#16647)
-
-- The `getnetworkinfo` and `getpeerinfo` commands now contain a new field with decoded network service flags.
-
-- `getdescriptorinfo` now returns an additional `checksum` field
- containing the checksum for the unmodified descriptor provided by the
- user (that is, before the descriptor is normalized for the
- `descriptor` field). (#15986)
-
-- `joinpsbts` will shuffle the order of the inputs and outputs of the resulting joined psbt.
- Previously inputs and outputs were added in the order that the PSBTs were provided which makes correlating inputs to outputs extremely easy.
-
-- `walletcreatefundedpsbt` now signals BIP125 Replace-by-Fee if the
- `-walletrbf` configuration option is set to true. (#15911)
-
GUI changes
-----------
-- Provides bech32 addresses by default. The user may change the address
- during invoice generation using a GUI toggle, or the default address
- type may be changed by the `-addresstype` configuration option.
- (#15711, #16497)
-
-- In 0.18.0 a `./configure` flag was introduced to allow disabling BIP70 support in the GUI (support was enabled by default). In 0.19.0 this flag is now __disabled__ by default.
-- If you want compile Bitcoin Core with BIP70 support in the GUI, you can pass `--enable-bip70` to `./configure`.
-
-Deprecated or removed configuration options
--------------------------------------------
-
-- `-mempoolreplacement` is removed, although default node behavior
- remains the same. This option previously allowed the user to prevent
- the node from accepting or relaying BIP125 transaction replacements.
- This is different from the remaining configuration option
- `-walletrbf`. (#16171)
-
-Deprecated or removed RPCs
---------------------------
-
-- `bumpfee` no longer accepts a `totalFee` option unless the
- configuration parameter `deprecatedrpc=totalFee` is specified. This
- parameter will be fully removed in a subsequent release. (#15996)
-
-- `generate` is now removed after being deprecated in Bitcoin Core 0.18.
- Use the `generatetoaddress` RPC instead. (#15492)
-
-P2P changes
------------
+Wallet
+------
-- BIP 61 reject messages were deprecated in v0.18. They are now disabled
- by default, but can be enabled by setting the `-enablebip61` command
- line option. BIP 61 reject messages will be removed entirely in a
- future version of Bitcoin Core. (#14054)
-
-- To eliminate well-known denial-of-service vectors in Bitcoin Core,
- especially for nodes with spinning disks, the default value for the
- `-peerbloomfilters` configuration option has been changed to false.
- This prevents Bitcoin Core from sending the BIP111 NODE_BLOOM service
- flag, accepting BIP37 bloom filters, or serving merkle blocks or
- transactions matching a bloom filter. Users who still want to provide
- bloom filter support may either set the configuration option to true
- to re-enable both BIP111 and BIP37 support or enable just BIP37
- support for specific peers using the updated `-whitelist` and
- `-whitebind` configuration options described elsewhere in these
- release notes. For the near future, lightweight clients using public
- BIP111/BIP37 nodes should still be able to connect to older versions
- of Bitcoin Core and nodes that have manually enabled BIP37 support,
- but developers of such software should consider migrating to either
- using specific BIP37 nodes or an alternative transaction filtering
- system. (#16152)
-
-Miscellaneous CLI Changes
--------------------------
-
-- The `testnet` field in `bitcoin-cli -getinfo` has been renamed to
- `chain` and now returns the current network name as defined in BIP70
- (main, test, regtest). (#15566)
+- The wallet now by default uses bech32 addresses when using RPC, and creates native segwit change outputs.
Low-level changes
=================
-RPC
----
-
-- `getblockchaininfo` no longer returns a `bip9_softforks` object.
- Instead, information has been moved into the `softforks` object and
- an additional `type` field describes how Bitcoin Core determines
- whether that soft fork is active (e.g. BIP9 or BIP90). See the RPC
- help for details. (#16060)
-
-- `getblocktemplate` no longer returns a `rules` array containing `CSV`
- and `segwit` (the BIP9 deployments that are currently in active
- state). (#16060)
-
-- `getrpcinfo` now returns a `logpath` field with the path to
- `debug.log`. (#15483)
-
Tests
-----
-- The regression test chain enabled by the `-regtest` command line flag
- now requires transactions to not violate standard policy by default.
- This is the same default used for mainnet and makes it easier to test
- mainnet behavior on regtest. Note that the testnet still allows
- non-standard txs by default and that the policy can be locally
- adjusted with the `-acceptnonstdtxn` command line flag for both test
- chains. (#15891)
-
-Configuration
-------------
-
-- A setting specified in the default section but not also specified in a
- network-specific section (e.g. testnet) will now produce an error
- preventing startup instead of just a warning unless the network is
- mainnet. This prevents settings intended for mainnet from being
- applied to testnet or regtest. (#15629)
-
-- On platforms supporting `thread_local`, log lines can be prefixed with
- the name of the thread that caused the log. To enable this behavior,
- use `-logthreadnames=1`. (#15849)
-
-Network
--------
-
-- When fetching a transaction announced by multiple peers, previous versions of
- Bitcoin Core would sequentially attempt to download the transaction from each
- announcing peer until the transaction is received, in the order that those
- peers' announcements were received. In this release, the download logic has
- changed to randomize the fetch order across peers and to prefer sending
- download requests to outbound peers over inbound peers. This fixes an issue
- where inbound peers could prevent a node from getting a transaction.
- (#14897, #15834)
-
-- If a Tor hidden service is being used, Bitcoin Core will be bound to
- the standard port 8333 even if a different port is configured for
- clearnet connections. This prevents leaking node identity through use
- of identical non-default port numbers. (#15651)
-
-Mempool and transaction relay
------------------------------
-
-- Allows one extra single-ancestor transaction per package. Previously,
- if a transaction in the mempool had 25 descendants, or it and all of
- its descendants were over 101,000 vbytes, any newly-received
- transaction that was also a descendant would be ignored. Now, one
- extra descendant will be allowed provided it is an immediate
- descendant (child) and the child's size is 10,000 vbytes or less.
- This makes it possible for two-party contract protocols such as
- Lightning Network to give each participant an output they can spend
- immediately for Child-Pays-For-Parent (CPFP) fee bumping without
- allowing one malicious participant to fill the entire package and thus
- prevent the other participant from spending their output. (#15681)
-
-- Transactions with outputs paying v1 to v16 witness versions (future
- segwit versions) are now accepted into the mempool, relayed, and
- mined. Attempting to spend those outputs remains forbidden by policy
- ("non-standard"). When this change has been widely deployed, wallets
- and services can accept any valid bech32 Bitcoin address without
- concern that transactions paying future segwit versions will become
- stuck in an unconfirmed state. (#15846)
-
-- Legacy transactions (transactions with no segwit inputs) must now be
- sent using the legacy encoding format, enforcing the rule specified in
- BIP144. (#14039)
-
-Wallet
-------
-
-- When in pruned mode, a rescan that was triggered by an `importwallet`,
- `importpubkey`, `importaddress`, or `importprivkey` RPC will only fail
- when blocks have been pruned. Previously it would fail when `-prune`
- has been set. This change allows setting `-prune` to a high value
- (e.g. the disk size) without the calls to any of the import RPCs
- failing until the first block is pruned. (#15870)
-
-- When creating a transaction with a fee above `-maxtxfee` (default 0.1
- BTC), the RPC commands `walletcreatefundedpsbt` and
- `fundrawtransaction` will now fail instead of rounding down the fee.
- Be aware that the `feeRate` argument is specified in BTC per 1,000
- vbytes, not satoshi per vbyte. (#16257)
-
-- A new wallet flag `avoid_reuse` has been added (default off). When
- enabled, a wallet will distinguish between used and unused addresses,
- and default to not use the former in coin selection. When setting
- this flag on an existing wallet, rescanning the blockchain is required
- to correctly mark previously used destinations. Together with "avoid
- partial spends" (added in Bitcoin Core v0.17.0), this can eliminate a
- serious privacy issue where a malicious user can track spends by
- sending small payments to a previously-paid address that would then
- be included with unrelated inputs in future payments. (#13756)
-
-Build system changes
---------------------
-
-- Python >=3.5 is now required by all aspects of the project. This
- includes the build systems, test framework and linters. The previously
- supported minimum (3.4), was EOL in March 2019. (#14954)
-
-- The minimum supported miniUPnPc API version is set to 10. This keeps
- compatibility with Ubuntu 16.04 LTS and Debian 8 `libminiupnpc-dev`
- packages. Please note, on Debian this package is still vulnerable to
- [CVE-2017-8798](https://security-tracker.debian.org/tracker/CVE-2017-8798)
- (in jessie only) and
- [CVE-2017-1000494](https://security-tracker.debian.org/tracker/CVE-2017-1000494)
- (both in jessie and in stretch). (#15993)
+- `-fallbackfee` was 0 (disabled) by default for the main chain, but 0.0002 by default for the test chains. Now it is 0
+ by default for all chains. Testnet and regtest users will have to add `fallbackfee=0.0002` to their configuration if
+ they weren't setting it and they want it to keep working like before. (#16524)
Credits
=======
@@ -393,4 +102,5 @@ Credits
Thanks to everyone who directly contributed to this release:
-As well as everyone that helped translating on [Transifex](https://www.transifex.com/bitcoin/bitcoin/).
+As well as to everyone that helped with translations on
+[Transifex](https://www.transifex.com/bitcoin/bitcoin/).
diff --git a/doc/release-process.md b/doc/release-process.md
index 551bde78a3..2c3c4e3869 100644
--- a/doc/release-process.md
+++ b/doc/release-process.md
@@ -14,19 +14,9 @@ Release Process
* Update [bips.md](bips.md) to account for changes since the last release (don't forget to bump the version number on the first line).
* Update version in `configure.ac` (don't forget to set `CLIENT_VERSION_RC` to `0`).
* Write release notes (see "Write the release notes" below).
-* Update `src/chainparams.cpp` nMinimumChainWork with information from the getblockchaininfo rpc.
-* Update `src/chainparams.cpp` defaultAssumeValid with information from the getblockhash rpc.
- - The selected value must not be orphaned so it may be useful to set the value two blocks back from the tip.
- - Testnet should be set some tens of thousands back from the tip due to reorgs there.
- - This update should be reviewed with a reindex-chainstate with assumevalid=0 to catch any defect
- that causes rejection of blocks in the past history.
### Before every major release
-* Update hardcoded [seeds](/contrib/seeds/README.md), see [this pull request](https://github.com/bitcoin/bitcoin/pull/7415) for an example.
-* Update [`src/chainparams.cpp`](/src/chainparams.cpp) m_assumed_blockchain_size and m_assumed_chain_state_size with the current size plus some overhead (see [this](#how-to-calculate-m_assumed_blockchain_size-and-m_assumed_chain_state_size) for information on how to calculate them).
-* Update `src/chainparams.cpp` chainTxData with statistics about the transaction count and rate. Use the output of the RPC `getchaintxstats`, see
- [this pull request](https://github.com/bitcoin/bitcoin/pull/17002) for an example. Reviewers can verify the results by running `getchaintxstats <window_block_count> <window_last_block_hash>` with the `window_block_count` and `window_last_block_hash` from your output.
* On both the master branch and the new release branch:
- update `CLIENT_VERSION_MINOR` in [`configure.ac`](../configure.ac)
- update `CLIENT_VERSION_MINOR`, `PACKAGE_VERSION`, and `PACKAGE_STRING` in [`build_msvc/bitcoin_config.h`](/build_msvc/bitcoin_config.h)
@@ -36,6 +26,16 @@ Release Process
#### Before branch-off
+* Update hardcoded [seeds](/contrib/seeds/README.md), see [this pull request](https://github.com/bitcoin/bitcoin/pull/7415) for an example.
+* Update [`src/chainparams.cpp`](/src/chainparams.cpp) m_assumed_blockchain_size and m_assumed_chain_state_size with the current size plus some overhead (see [this](#how-to-calculate-m_assumed_blockchain_size-and-m_assumed_chain_state_size) for information on how to calculate them).
+* Update `src/chainparams.cpp` chainTxData with statistics about the transaction count and rate. Use the output of the RPC `getchaintxstats`, see
+ [this pull request](https://github.com/bitcoin/bitcoin/pull/17002) for an example. Reviewers can verify the results by running `getchaintxstats <window_block_count> <window_last_block_hash>` with the `window_block_count` and `window_last_block_hash` from your output.
+* Update `src/chainparams.cpp` nMinimumChainWork with information from the getblockchaininfo rpc.
+* Update `src/chainparams.cpp` defaultAssumeValid with information from the getblockhash rpc.
+ - The selected value must not be orphaned so it may be useful to set the value two blocks back from the tip.
+ - Testnet should be set some tens of thousands back from the tip due to reorgs there.
+ - This update should be reviewed with a reindex-chainstate with assumevalid=0 to catch any defect
+ that causes rejection of blocks in the past history.
- Clear the release notes and move them to the wiki (see "Write the release notes" below).
#### After branch-off (on master)
diff --git a/src/Makefile.am b/src/Makefile.am
index 1ef62a656d..84254e45d1 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -209,6 +209,7 @@ BITCOIN_CORE_H = \
util/error.h \
util/fees.h \
util/system.h \
+ util/macros.h \
util/memory.h \
util/moneystr.h \
util/rbf.h \
@@ -520,6 +521,8 @@ endif
libbitcoin_cli_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
libbitcoin_cli_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
libbitcoin_cli_a_SOURCES = \
+ compat/stdin.h \
+ compat/stdin.cpp \
rpc/client.cpp \
$(BITCOIN_CORE_H)
diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include
index a8d3154107..9ab7f02e22 100644
--- a/src/Makefile.qt.include
+++ b/src/Makefile.qt.include
@@ -353,9 +353,9 @@ QT_QM=$(QT_TS:.ts=.qm)
SECONDARY: $(QT_QM)
-$(srcdir)/qt/bitcoinstrings.cpp: $(libbitcoin_server_a_SOURCES) $(libbitcoin_wallet_a_SOURCES) $(libbitcoin_common_a_SOURCES) $(libbitcoin_zmq_a_SOURCES) $(libbitcoin_consensus_a_SOURCES) $(libbitcoin_util_a_SOURCES)
+$(srcdir)/qt/bitcoinstrings.cpp: FORCE
@test -n $(XGETTEXT) || echo "xgettext is required for updating translations"
- $(AM_V_GEN) cd $(srcdir); XGETTEXT=$(XGETTEXT) COPYRIGHT_HOLDERS="$(COPYRIGHT_HOLDERS)" $(PYTHON) ../share/qt/extract_strings_qt.py $^
+ $(AM_V_GEN) cd $(srcdir); XGETTEXT=$(XGETTEXT) COPYRIGHT_HOLDERS="$(COPYRIGHT_HOLDERS)" $(PYTHON) ../share/qt/extract_strings_qt.py $(libbitcoin_server_a_SOURCES) $(libbitcoin_wallet_a_SOURCES) $(libbitcoin_common_a_SOURCES) $(libbitcoin_zmq_a_SOURCES) $(libbitcoin_consensus_a_SOURCES) $(libbitcoin_util_a_SOURCES)
translate: $(srcdir)/qt/bitcoinstrings.cpp $(QT_FORMS_UI) $(QT_FORMS_UI) $(BITCOIN_QT_BASE_CPP) qt/bitcoin.cpp $(BITCOIN_QT_WINDOWS_CPP) $(BITCOIN_QT_WALLET_CPP) $(BITCOIN_QT_H) $(BITCOIN_MM)
@test -n $(LUPDATE) || echo "lupdate is required for updating translations"
diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp
index a6756fcce7..73773c4ec5 100644
--- a/src/bitcoin-cli.cpp
+++ b/src/bitcoin-cli.cpp
@@ -27,6 +27,7 @@
#include <support/events.h>
#include <univalue.h>
+#include <compat/stdin.h>
const std::function<std::string(const char*)> G_TRANSLATION_FUN = nullptr;
@@ -58,7 +59,8 @@ static void SetupCliArgs()
gArgs.AddArg("-rpcwait", "Wait for RPC server to start", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
gArgs.AddArg("-rpcwallet=<walletname>", "Send RPC for non-default wallet on RPC server (needs to exactly match corresponding -wallet option passed to bitcoind). This changes the RPC endpoint used, e.g. http://127.0.0.1:8332/wallet/<walletname>", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
gArgs.AddArg("-stdin", "Read extra arguments from standard input, one per line until EOF/Ctrl-D (recommended for sensitive information such as passphrases). When combined with -stdinrpcpass, the first line from standard input is used for the RPC password.", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
- gArgs.AddArg("-stdinrpcpass", "Read RPC password from standard input as a single line. When combined with -stdin, the first line from standard input is used for the RPC password.", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-stdinrpcpass", "Read RPC password from standard input as a single line. When combined with -stdin, the first line from standard input is used for the RPC password. When combined with -stdinwalletpassphrase, -stdinrpcpass consumes the first line, and -stdinwalletpassphrase consumes the second.", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-stdinwalletpassphrase", "Read wallet passphrase from standard input as a single line. When combined with -stdin, the first line from standard input is used for the wallet passphrase.", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
}
/** libevent event log callback */
@@ -411,18 +413,47 @@ static int CommandLineRPC(int argc, char *argv[])
}
std::string rpcPass;
if (gArgs.GetBoolArg("-stdinrpcpass", false)) {
+ NO_STDIN_ECHO();
+ if (!StdinReady()) {
+ fputs("RPC password> ", stderr);
+ fflush(stderr);
+ }
if (!std::getline(std::cin, rpcPass)) {
throw std::runtime_error("-stdinrpcpass specified but failed to read from standard input");
}
+ if (StdinTerminal()) {
+ fputc('\n', stdout);
+ }
gArgs.ForceSetArg("-rpcpassword", rpcPass);
}
std::vector<std::string> args = std::vector<std::string>(&argv[1], &argv[argc]);
+ if (gArgs.GetBoolArg("-stdinwalletpassphrase", false)) {
+ NO_STDIN_ECHO();
+ std::string walletPass;
+ if (args.size() < 1 || args[0].substr(0, 16) != "walletpassphrase") {
+ throw std::runtime_error("-stdinwalletpassphrase is only applicable for walletpassphrase(change)");
+ }
+ if (!StdinReady()) {
+ fputs("Wallet passphrase> ", stderr);
+ fflush(stderr);
+ }
+ if (!std::getline(std::cin, walletPass)) {
+ throw std::runtime_error("-stdinwalletpassphrase specified but failed to read from standard input");
+ }
+ if (StdinTerminal()) {
+ fputc('\n', stdout);
+ }
+ args.insert(args.begin() + 1, walletPass);
+ }
if (gArgs.GetBoolArg("-stdin", false)) {
// Read one arg per line from stdin and append
std::string line;
while (std::getline(std::cin, line)) {
args.push_back(line);
}
+ if (StdinTerminal()) {
+ fputc('\n', stdout);
+ }
}
std::unique_ptr<BaseRequestHandler> rh;
std::string method;
diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp
index 615b955f6e..17989a4214 100644
--- a/src/bitcoind.cpp
+++ b/src/bitcoind.cpp
@@ -45,7 +45,7 @@ static bool AppInit(int argc, char* argv[])
bool fRet = false;
- util::ThreadRename("init");
+ util::ThreadSetInternalName("init");
//
// Parameters
diff --git a/src/compat/stdin.cpp b/src/compat/stdin.cpp
new file mode 100644
index 0000000000..4f2ba1e9c4
--- /dev/null
+++ b/src/compat/stdin.cpp
@@ -0,0 +1,72 @@
+// Copyright (c) 2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#if defined(HAVE_CONFIG_H)
+#include <config/bitcoin-config.h>
+#endif
+
+#include <cstdio> // for fileno(), stdin
+
+#ifdef WIN32
+#include <windows.h> // for SetStdinEcho()
+#include <io.h> // for isatty()
+#else
+#include <termios.h> // for SetStdinEcho()
+#include <unistd.h> // for SetStdinEcho(), isatty()
+#include <sys/poll.h> // for StdinReady()
+#endif
+
+#include <compat/stdin.h>
+
+// https://stackoverflow.com/questions/1413445/reading-a-password-from-stdcin
+void SetStdinEcho(bool enable)
+{
+#ifdef WIN32
+ HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
+ DWORD mode;
+ GetConsoleMode(hStdin, &mode);
+ if (!enable) {
+ mode &= ~ENABLE_ECHO_INPUT;
+ } else {
+ mode |= ENABLE_ECHO_INPUT;
+ }
+ SetConsoleMode(hStdin, mode);
+#else
+ struct termios tty;
+ tcgetattr(STDIN_FILENO, &tty);
+ if (!enable) {
+ tty.c_lflag &= ~ECHO;
+ } else {
+ tty.c_lflag |= ECHO;
+ }
+ (void)tcsetattr(STDIN_FILENO, TCSANOW, &tty);
+#endif
+}
+
+bool StdinTerminal()
+{
+#ifdef WIN32
+ return _isatty(_fileno(stdin));
+#else
+ return isatty(fileno(stdin));
+#endif
+}
+
+bool StdinReady()
+{
+ if (!StdinTerminal()) {
+ return true;
+ }
+#ifdef WIN32
+ return false;
+#else
+ struct pollfd fds;
+ fds.fd = 0; /* this is STDIN */
+ fds.events = POLLIN;
+ return poll(&fds, 1, 0) == 1;
+#endif
+}
+
+NoechoInst::NoechoInst() { SetStdinEcho(false); }
+NoechoInst::~NoechoInst() { SetStdinEcho(true); }
diff --git a/src/compat/stdin.h b/src/compat/stdin.h
new file mode 100644
index 0000000000..468fe4d6a6
--- /dev/null
+++ b/src/compat/stdin.h
@@ -0,0 +1,18 @@
+// Copyright (c) 2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_COMPAT_STDIN_H
+#define BITCOIN_COMPAT_STDIN_H
+
+struct NoechoInst {
+ NoechoInst();
+ ~NoechoInst();
+};
+
+#define NO_STDIN_ECHO() NoechoInst _no_echo
+
+bool StdinTerminal();
+bool StdinReady();
+
+#endif // BITCOIN_COMPAT_STDIN_H
diff --git a/src/interfaces/node.cpp b/src/interfaces/node.cpp
index c80a8789fc..3d89e17163 100644
--- a/src/interfaces/node.cpp
+++ b/src/interfaces/node.cpp
@@ -201,7 +201,6 @@ public:
return GuessVerificationProgress(Params().TxData(), tip);
}
bool isInitialBlockDownload() override { return ::ChainstateActive().IsInitialBlockDownload(); }
- bool isAddressTypeSet() override { return !::gArgs.GetArg("-addresstype", "").empty(); }
bool getReindex() override { return ::fReindex; }
bool getImporting() override { return ::fImporting; }
void setNetworkActive(bool active) override
diff --git a/src/interfaces/node.h b/src/interfaces/node.h
index 2f4f396e72..688ff434ba 100644
--- a/src/interfaces/node.h
+++ b/src/interfaces/node.h
@@ -155,9 +155,6 @@ public:
//! Is initial block download.
virtual bool isInitialBlockDownload() = 0;
- //! Is -addresstype set.
- virtual bool isAddressTypeSet() = 0;
-
//! Get reindex.
virtual bool getReindex() = 0;
diff --git a/src/net.h b/src/net.h
index f33147155a..44655abf80 100644
--- a/src/net.h
+++ b/src/net.h
@@ -761,7 +761,7 @@ public:
// Used for BIP35 mempool sending
bool fSendMempool GUARDED_BY(cs_tx_inventory){false};
// Last time a "MEMPOOL" request was serviced.
- std::atomic<int64_t> timeLastMempoolReq{0};
+ std::atomic<std::chrono::seconds> m_last_mempool_req{std::chrono::seconds{0}};
int64_t nNextInvSend{0};
CCriticalSection cs_feeFilter;
diff --git a/src/net_processing.cpp b/src/net_processing.cpp
index f029c9de20..b6839dcf21 100644
--- a/src/net_processing.cpp
+++ b/src/net_processing.cpp
@@ -1532,11 +1532,11 @@ void static ProcessGetData(CNode* pfrom, const CChainParams& chainparams, CConnm
if (mi != mapRelay.end()) {
connman->PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::TX, *mi->second));
push = true;
- } else if (pfrom->m_tx_relay->timeLastMempoolReq) {
+ } else if (pfrom->m_tx_relay->m_last_mempool_req.load().count()) {
auto txinfo = mempool.info(inv.hash);
// To protect privacy, do not answer getdata using the mempool when
// that TX couldn't have been INVed in reply to a MEMPOOL request.
- if (txinfo.tx && txinfo.nTime <= pfrom->m_tx_relay->timeLastMempoolReq) {
+ if (txinfo.tx && txinfo.m_time <= pfrom->m_tx_relay->m_last_mempool_req.load()) {
connman->PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::TX, *txinfo.tx));
push = true;
}
@@ -3789,10 +3789,10 @@ bool PeerLogicValidation::SendMessages(CNode* pto)
if (fSendTrickle && pto->m_tx_relay->fSendMempool) {
auto vtxinfo = mempool.infoAll();
pto->m_tx_relay->fSendMempool = false;
- CAmount filterrate = 0;
+ CFeeRate filterrate;
{
LOCK(pto->m_tx_relay->cs_feeFilter);
- filterrate = pto->m_tx_relay->minFeeFilter;
+ filterrate = CFeeRate(pto->m_tx_relay->minFeeFilter);
}
LOCK(pto->m_tx_relay->cs_filter);
@@ -3801,9 +3801,9 @@ bool PeerLogicValidation::SendMessages(CNode* pto)
const uint256& hash = txinfo.tx->GetHash();
CInv inv(MSG_TX, hash);
pto->m_tx_relay->setInventoryTxToSend.erase(hash);
- if (filterrate) {
- if (txinfo.feeRate.GetFeePerK() < filterrate)
- continue;
+ // Don't send transactions that peers will not put into their mempool
+ if (txinfo.fee < filterrate.GetFee(txinfo.vsize)) {
+ continue;
}
if (pto->m_tx_relay->pfilter) {
if (!pto->m_tx_relay->pfilter->IsRelevantAndUpdate(*txinfo.tx)) continue;
@@ -3815,7 +3815,7 @@ bool PeerLogicValidation::SendMessages(CNode* pto)
vInv.clear();
}
}
- pto->m_tx_relay->timeLastMempoolReq = GetTime();
+ pto->m_tx_relay->m_last_mempool_req = GetTime<std::chrono::seconds>();
}
// Determine transactions to relay
@@ -3826,10 +3826,10 @@ bool PeerLogicValidation::SendMessages(CNode* pto)
for (std::set<uint256>::iterator it = pto->m_tx_relay->setInventoryTxToSend.begin(); it != pto->m_tx_relay->setInventoryTxToSend.end(); it++) {
vInvTx.push_back(it);
}
- CAmount filterrate = 0;
+ CFeeRate filterrate;
{
LOCK(pto->m_tx_relay->cs_feeFilter);
- filterrate = pto->m_tx_relay->minFeeFilter;
+ filterrate = CFeeRate(pto->m_tx_relay->minFeeFilter);
}
// Topologically and fee-rate sort the inventory we send for privacy and priority reasons.
// A heap is used so that not all items need sorting if only a few are being sent.
@@ -3856,7 +3856,8 @@ bool PeerLogicValidation::SendMessages(CNode* pto)
if (!txinfo.tx) {
continue;
}
- if (filterrate && txinfo.feeRate.GetFeePerK() < filterrate) {
+ // Peer told you to not send transactions at that feerate? Don't bother sending it.
+ if (txinfo.fee < filterrate.GetFee(txinfo.vsize)) {
continue;
}
if (pto->m_tx_relay->pfilter && !pto->m_tx_relay->pfilter->IsRelevantAndUpdate(*txinfo.tx)) continue;
diff --git a/src/policy/feerate.h b/src/policy/feerate.h
index 85d7d22b4f..d081f2ce8e 100644
--- a/src/policy/feerate.h
+++ b/src/policy/feerate.h
@@ -25,7 +25,7 @@ public:
/** Fee rate of 0 satoshis per kB */
CFeeRate() : nSatoshisPerK(0) { }
template<typename I>
- CFeeRate(const I _nSatoshisPerK): nSatoshisPerK(_nSatoshisPerK) {
+ explicit CFeeRate(const I _nSatoshisPerK): nSatoshisPerK(_nSatoshisPerK) {
// We've previously had bugs creep in from silent double->int conversion...
static_assert(std::is_integral<I>::value, "CFeeRate should be used without floats");
}
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp
index ec6075c8fb..86f4dc91a1 100644
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -416,7 +416,7 @@ int GuiMain(int argc, char* argv[])
std::tie(argc, argv) = winArgs.get();
#endif
SetupEnvironment();
- util::ThreadRename("main");
+ util::ThreadSetInternalName("main");
std::unique_ptr<interfaces::Node> node = interfaces::MakeNode();
diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp
index 00d83d23dd..806cc3c41e 100644
--- a/src/qt/paymentserver.cpp
+++ b/src/qt/paymentserver.cpp
@@ -82,7 +82,7 @@ static QString ipcServerName()
// the main GUI window is up and ready to ask the user
// to send payment.
-static QList<QString> savedPaymentRequests;
+static QSet<QString> savedPaymentRequests;
//
// Sending to the server is done synchronously, at startup.
@@ -107,7 +107,8 @@ void PaymentServer::ipcParseCommandLine(interfaces::Node& node, int argc, char*
// will start a mainnet instance and throw a "wrong network" error.
if (arg.startsWith(BITCOIN_IPC_PREFIX, Qt::CaseInsensitive)) // bitcoin: URI
{
- savedPaymentRequests.append(arg);
+ if (savedPaymentRequests.contains(arg)) continue;
+ savedPaymentRequests.insert(arg);
SendCoinsRecipient r;
if (GUIUtil::parseBitcoinURI(arg, &r) && !r.address.isEmpty())
@@ -127,7 +128,8 @@ void PaymentServer::ipcParseCommandLine(interfaces::Node& node, int argc, char*
#ifdef ENABLE_BIP70
else if (QFile::exists(arg)) // Filename
{
- savedPaymentRequests.append(arg);
+ if (savedPaymentRequests.contains(arg)) continue;
+ savedPaymentRequests.insert(arg);
PaymentRequestPlus request;
if (readPaymentRequestFromFile(arg, request))
@@ -280,7 +282,7 @@ void PaymentServer::handleURIOrFile(const QString& s)
{
if (saveURIs)
{
- savedPaymentRequests.append(s);
+ savedPaymentRequests.insert(s);
return;
}
diff --git a/src/qt/receivecoinsdialog.cpp b/src/qt/receivecoinsdialog.cpp
index df8d5115d5..de453cf743 100644
--- a/src/qt/receivecoinsdialog.cpp
+++ b/src/qt/receivecoinsdialog.cpp
@@ -7,7 +7,6 @@
#include <qt/receivecoinsdialog.h>
#include <qt/forms/ui_receivecoinsdialog.h>
-#include <interfaces/node.h>
#include <qt/addresstablemodel.h>
#include <qt/optionsmodel.h>
#include <qt/platformstyle.h>
@@ -93,16 +92,10 @@ void ReceiveCoinsDialog::setModel(WalletModel *_model)
// Last 2 columns are set by the columnResizingFixer, when the table geometry is ready.
columnResizingFixer = new GUIUtil::TableViewLastColumnResizingFixer(tableView, AMOUNT_MINIMUM_COLUMN_WIDTH, DATE_COLUMN_WIDTH, this);
- if (model->node().isAddressTypeSet()) {
- // user explicitly set the type, use it
- if (model->wallet().getDefaultAddressType() == OutputType::BECH32) {
- ui->useBech32->setCheckState(Qt::Checked);
- } else {
- ui->useBech32->setCheckState(Qt::Unchecked);
- }
- } else {
- // Always fall back to bech32 in the gui
+ if (model->wallet().getDefaultAddressType() == OutputType::BECH32) {
ui->useBech32->setCheckState(Qt::Checked);
+ } else {
+ ui->useBech32->setCheckState(Qt::Unchecked);
}
// Set the button to be enabled or disabled based on whether the wallet can give out new addresses.
diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp
index a88119d8c5..003a31b248 100644
--- a/src/qt/sendcoinsdialog.cpp
+++ b/src/qt/sendcoinsdialog.cpp
@@ -927,11 +927,11 @@ void SendConfirmationDialog::updateYesButton()
if(secDelay > 0)
{
yesButton->setEnabled(false);
- yesButton->setText(tr("Yes") + " (" + QString::number(secDelay) + ")");
+ yesButton->setText(tr("Send") + " (" + QString::number(secDelay) + ")");
}
else
{
yesButton->setEnabled(true);
- yesButton->setText(tr("Yes"));
+ yesButton->setText(tr("Send"));
}
}
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index 02717fa80f..3463145f75 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -418,7 +418,7 @@ static void entryToJSON(const CTxMemPool& pool, UniValue& info, const CTxMemPool
info.pushKV("weight", (int)e.GetTxWeight());
info.pushKV("fee", ValueFromAmount(e.GetFee()));
info.pushKV("modifiedfee", ValueFromAmount(e.GetModifiedFee()));
- info.pushKV("time", e.GetTime());
+ info.pushKV("time", count_seconds(e.GetTime()));
info.pushKV("height", (int)e.GetHeight());
info.pushKV("descendantcount", e.GetCountWithDescendants());
info.pushKV("descendantsize", e.GetSizeWithDescendants());
diff --git a/src/script/descriptor.cpp b/src/script/descriptor.cpp
index b782ebbd1f..b223349eb1 100644
--- a/src/script/descriptor.cpp
+++ b/src/script/descriptor.cpp
@@ -593,15 +593,23 @@ public:
ComboDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Singleton(std::move(prov)), {}, "combo") {}
};
-/** A parsed multi(...) descriptor. */
+/** A parsed multi(...) or sortedmulti(...) descriptor */
class MultisigDescriptor final : public DescriptorImpl
{
const int m_threshold;
+ const bool m_sorted;
protected:
std::string ToStringExtra() const override { return strprintf("%i", m_threshold); }
- std::vector<CScript> MakeScripts(const std::vector<CPubKey>& keys, const CScript*, FlatSigningProvider&) const override { return Singleton(GetScriptForMultisig(m_threshold, keys)); }
+ std::vector<CScript> MakeScripts(const std::vector<CPubKey>& keys, const CScript*, FlatSigningProvider&) const override {
+ if (m_sorted) {
+ std::vector<CPubKey> sorted_keys(keys);
+ std::sort(sorted_keys.begin(), sorted_keys.end());
+ return Singleton(GetScriptForMultisig(m_threshold, sorted_keys));
+ }
+ return Singleton(GetScriptForMultisig(m_threshold, keys));
+ }
public:
- MultisigDescriptor(int threshold, std::vector<std::unique_ptr<PubkeyProvider>> providers) : DescriptorImpl(std::move(providers), {}, "multi"), m_threshold(threshold) {}
+ MultisigDescriptor(int threshold, std::vector<std::unique_ptr<PubkeyProvider>> providers, bool sorted = false) : DescriptorImpl(std::move(providers), {}, sorted ? "sortedmulti" : "multi"), m_threshold(threshold), m_sorted(sorted) {}
};
/** A parsed sh(...) descriptor. */
@@ -809,6 +817,7 @@ std::unique_ptr<PubkeyProvider> ParsePubkey(const Span<const char>& sp, bool per
std::unique_ptr<DescriptorImpl> ParseScript(Span<const char>& sp, ParseScriptContext ctx, FlatSigningProvider& out, std::string& error)
{
auto expr = Expr(sp);
+ bool sorted_multi = false;
if (Func("pk", expr)) {
auto pubkey = ParsePubkey(expr, ctx != ParseScriptContext::P2WSH, out, error);
if (!pubkey) return nullptr;
@@ -827,7 +836,7 @@ std::unique_ptr<DescriptorImpl> ParseScript(Span<const char>& sp, ParseScriptCon
error = "Cannot have combo in non-top level";
return nullptr;
}
- if (Func("multi", expr)) {
+ if ((sorted_multi = Func("sortedmulti", expr)) || Func("multi", expr)) {
auto threshold = Expr(expr);
uint32_t thres;
std::vector<std::unique_ptr<PubkeyProvider>> providers;
@@ -869,7 +878,7 @@ std::unique_ptr<DescriptorImpl> ParseScript(Span<const char>& sp, ParseScriptCon
return nullptr;
}
}
- return MakeUnique<MultisigDescriptor>(thres, std::move(providers));
+ return MakeUnique<MultisigDescriptor>(thres, std::move(providers), sorted_multi);
}
if (ctx != ParseScriptContext::P2WSH && Func("wpkh", expr)) {
auto pubkey = ParsePubkey(expr, false, out, error);
diff --git a/src/sync.h b/src/sync.h
index bdbdde1a2a..8ff6173142 100644
--- a/src/sync.h
+++ b/src/sync.h
@@ -7,6 +7,7 @@
#define BITCOIN_SYNC_H
#include <threadsafety.h>
+#include <util/macros.h>
#include <condition_variable>
#include <thread>
@@ -176,9 +177,6 @@ public:
template<typename MutexArg>
using DebugLock = UniqueLock<typename std::remove_reference<typename std::remove_pointer<MutexArg>::type>::type>;
-#define PASTE(x, y) x ## y
-#define PASTE2(x, y) PASTE(x, y)
-
#define LOCK(cs) DebugLock<decltype(cs)> PASTE2(criticalblock, __COUNTER__)(cs, #cs, __FILE__, __LINE__)
#define LOCK2(cs1, cs2) \
DebugLock<decltype(cs1)> criticalblock1(cs1, #cs1, __FILE__, __LINE__); \
diff --git a/src/test/descriptor_tests.cpp b/src/test/descriptor_tests.cpp
index 50ac0bd7b8..55726a4a8f 100644
--- a/src/test/descriptor_tests.cpp
+++ b/src/test/descriptor_tests.cpp
@@ -252,7 +252,10 @@ BOOST_AUTO_TEST_CASE(descriptor_test)
// Multisig constructions
Check("multi(1,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "multi(1,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"512103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea23552ae"}});
+ Check("sortedmulti(1,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "sortedmulti(1,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"512103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea23552ae"}});
+ Check("sortedmulti(1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "sortedmulti(1,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"512103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea23552ae"}});
Check("sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))", DEFAULT, {{"a91445a9a622a8b0a1269944be477640eedc447bbd8487"}}, {{0x8000006FUL,222},{0}});
+ Check("sortedmulti(2,xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc/*,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0/0/*)", "sortedmulti(2,xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/*,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0/0/*)", RANGE, {{"5221025d5fc65ebb8d44a5274b53bac21ff8307fec2334a32df05553459f8b1f7fe1b62102fbd47cc8034098f0e6a94c6aeee8528abf0a2153a5d8e46d325b7284c046784652ae"}, {"52210264fd4d1f5dea8ded94c61e9641309349b62f27fbffe807291f664e286bfbe6472103f4ece6dfccfa37b211eb3d0af4d0c61dba9ef698622dc17eecdf764beeb005a652ae"}, {"5221022ccabda84c30bad578b13c89eb3b9544ce149787e5b538175b1d1ba259cbb83321024d902e1a2fc7a8755ab5b694c575fce742c48d9ff192e63df5193e4c7afe1f9c52ae"}}, {{0}, {1}, {2}, {0, 0, 0}, {0, 0, 1}, {0, 0, 2}});
Check("wsh(multi(2,xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0,xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "wsh(multi(2,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", HARDENED | RANGE, {{"0020b92623201f3bb7c3771d45b2ad1d0351ea8fbf8cfe0a0e570264e1075fa1948f"},{"002036a08bbe4923af41cf4316817c93b8d37e2f635dd25cfff06bd50df6ae7ea203"},{"0020a96e7ab4607ca6b261bfe3245ffda9c746b28d3f59e83d34820ec0e2b36c139c"}}, {{0xFFFFFFFFUL,0}, {1,2,0}, {1,2,1}, {1,2,2}, {10, 20, 30, 40, 0x80000000UL}, {10, 20, 30, 40, 0x80000001UL}, {10, 20, 30, 40, 0x80000002UL}});
Check("sh(wsh(multi(16,KzoAz5CanayRKex3fSLQ2BwJpN7U52gZvxMyk78nDMHuqrUxuSJy,KwGNz6YCCQtYvFzMtrC6D3tKTKdBBboMrLTsjr2NYVBwapCkn7Mr,KxogYhiNfwxuswvXV66eFyKcCpm7dZ7TqHVqujHAVUjJxyivxQ9X,L2BUNduTSyZwZjwNHynQTF14mv2uz2NRq5n5sYWTb4FkkmqgEE9f,L1okJGHGn1kFjdXHKxXjwVVtmCMR2JA5QsbKCSpSb7ReQjezKeoD,KxDCNSST75HFPaW5QKpzHtAyaCQC7p9Vo3FYfi2u4dXD1vgMiboK,L5edQjFtnkcf5UWURn6UuuoFrabgDQUHdheKCziwN42aLwS3KizU,KzF8UWFcEC7BYTq8Go1xVimMkDmyNYVmXV5PV7RuDicvAocoPB8i,L3nHUboKG2w4VSJ5jYZ5CBM97oeK6YuKvfZxrefdShECcjEYKMWZ,KyjHo36dWkYhimKmVVmQTq3gERv3pnqA4xFCpvUgbGDJad7eS8WE,KwsfyHKRUTZPQtysN7M3tZ4GXTnuov5XRgjdF2XCG8faAPmFruRF,KzCUbGhN9LJhdeFfL9zQgTJMjqxdBKEekRGZX24hXdgCNCijkkap,KzgpMBwwsDLwkaC5UrmBgCYaBD2WgZ7PBoGYXR8KT7gCA9UTN5a3,KyBXTPy4T7YG4q9tcAM3LkvfRpD1ybHMvcJ2ehaWXaSqeGUxEdkP,KzJDe9iwJRPtKP2F2AoN6zBgzS7uiuAwhWCfGdNeYJ3PC1HNJ8M8,L1xbHrxynrqLKkoYc4qtoQPx6uy5qYXR5ZDYVYBSRmCV5piU3JG9)))","sh(wsh(multi(16,03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0,0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600,0362a74e399c39ed5593852a30147f2959b56bb827dfa3e60e464b02ccf87dc5e8,0261345b53de74a4d721ef877c255429961b7e43714171ac06168d7e08c542a8b8,02da72e8b46901a65d4374fe6315538d8f368557dda3a1dcf9ea903f3afe7314c8,0318c82dd0b53fd3a932d16e0ba9e278fcc937c582d5781be626ff16e201f72286,0297ccef1ef99f9d73dec9ad37476ddb232f1238aff877af19e72ba04493361009,02e502cfd5c3f972fe9a3e2a18827820638f96b6f347e54d63deb839011fd5765d,03e687710f0e3ebe81c1037074da939d409c0025f17eb86adb9427d28f0f7ae0e9,02c04d3a5274952acdbc76987f3184b346a483d43be40874624b29e3692c1df5af,02ed06e0f418b5b43a7ec01d1d7d27290fa15f75771cb69b642a51471c29c84acd,036d46073cbb9ffee90473f3da429abc8de7f8751199da44485682a989a4bebb24,02f5d1ff7c9029a80a4e36b9a5497027ef7f3e73384a4a94fbfe7c4e9164eec8bc,02e41deffd1b7cce11cde209a781adcffdabd1b91c0ba0375857a2bfd9302419f3,02d76625f7956a7fc505ab02556c23ee72d832f1bac391bcd2d3abce5710a13d06,0399eb0a5487515802dc14544cf10b3666623762fbed2ec38a3975716e2c29c232)))", SIGNABLE, {{"a9147fc63e13dc25e8a95a3cee3d9a714ac3afd96f1e87"}});
CheckUnparsable("sh(multi(16,KzoAz5CanayRKex3fSLQ2BwJpN7U52gZvxMyk78nDMHuqrUxuSJy,KwGNz6YCCQtYvFzMtrC6D3tKTKdBBboMrLTsjr2NYVBwapCkn7Mr,KxogYhiNfwxuswvXV66eFyKcCpm7dZ7TqHVqujHAVUjJxyivxQ9X,L2BUNduTSyZwZjwNHynQTF14mv2uz2NRq5n5sYWTb4FkkmqgEE9f,L1okJGHGn1kFjdXHKxXjwVVtmCMR2JA5QsbKCSpSb7ReQjezKeoD,KxDCNSST75HFPaW5QKpzHtAyaCQC7p9Vo3FYfi2u4dXD1vgMiboK,L5edQjFtnkcf5UWURn6UuuoFrabgDQUHdheKCziwN42aLwS3KizU,KzF8UWFcEC7BYTq8Go1xVimMkDmyNYVmXV5PV7RuDicvAocoPB8i,L3nHUboKG2w4VSJ5jYZ5CBM97oeK6YuKvfZxrefdShECcjEYKMWZ,KyjHo36dWkYhimKmVVmQTq3gERv3pnqA4xFCpvUgbGDJad7eS8WE,KwsfyHKRUTZPQtysN7M3tZ4GXTnuov5XRgjdF2XCG8faAPmFruRF,KzCUbGhN9LJhdeFfL9zQgTJMjqxdBKEekRGZX24hXdgCNCijkkap,KzgpMBwwsDLwkaC5UrmBgCYaBD2WgZ7PBoGYXR8KT7gCA9UTN5a3,KyBXTPy4T7YG4q9tcAM3LkvfRpD1ybHMvcJ2ehaWXaSqeGUxEdkP,KzJDe9iwJRPtKP2F2AoN6zBgzS7uiuAwhWCfGdNeYJ3PC1HNJ8M8,L1xbHrxynrqLKkoYc4qtoQPx6uy5qYXR5ZDYVYBSRmCV5piU3JG9))","sh(multi(16,03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0,0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600,0362a74e399c39ed5593852a30147f2959b56bb827dfa3e60e464b02ccf87dc5e8,0261345b53de74a4d721ef877c255429961b7e43714171ac06168d7e08c542a8b8,02da72e8b46901a65d4374fe6315538d8f368557dda3a1dcf9ea903f3afe7314c8,0318c82dd0b53fd3a932d16e0ba9e278fcc937c582d5781be626ff16e201f72286,0297ccef1ef99f9d73dec9ad37476ddb232f1238aff877af19e72ba04493361009,02e502cfd5c3f972fe9a3e2a18827820638f96b6f347e54d63deb839011fd5765d,03e687710f0e3ebe81c1037074da939d409c0025f17eb86adb9427d28f0f7ae0e9,02c04d3a5274952acdbc76987f3184b346a483d43be40874624b29e3692c1df5af,02ed06e0f418b5b43a7ec01d1d7d27290fa15f75771cb69b642a51471c29c84acd,036d46073cbb9ffee90473f3da429abc8de7f8751199da44485682a989a4bebb24,02f5d1ff7c9029a80a4e36b9a5497027ef7f3e73384a4a94fbfe7c4e9164eec8bc,02e41deffd1b7cce11cde209a781adcffdabd1b91c0ba0375857a2bfd9302419f3,02d76625f7956a7fc505ab02556c23ee72d832f1bac391bcd2d3abce5710a13d06,0399eb0a5487515802dc14544cf10b3666623762fbed2ec38a3975716e2c29c232))", "P2SH script is too large, 547 bytes is larger than 520 bytes"); // P2SH does not fit 16 compressed pubkeys in a redeemscript
diff --git a/src/test/fuzz/deserialize.cpp b/src/test/fuzz/deserialize.cpp
index 9364ac4a32..3a74143dc2 100644
--- a/src/test/fuzz/deserialize.cpp
+++ b/src/test/fuzz/deserialize.cpp
@@ -23,7 +23,7 @@
#include <test/fuzz/fuzz.h>
-void test_one_input(std::vector<uint8_t> buffer)
+void test_one_input(const std::vector<uint8_t>& buffer)
{
CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION);
try {
diff --git a/src/test/fuzz/fuzz.cpp b/src/test/fuzz/fuzz.cpp
index 0709da5563..cfa160dde2 100644
--- a/src/test/fuzz/fuzz.cpp
+++ b/src/test/fuzz/fuzz.cpp
@@ -30,7 +30,8 @@ static void initialize()
// This function is used by libFuzzer
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
{
- test_one_input(std::vector<uint8_t>(data, data + size));
+ const std::vector<uint8_t> input(data, data + size);
+ test_one_input(input);
return 0;
}
diff --git a/src/test/fuzz/fuzz.h b/src/test/fuzz/fuzz.h
index 4e009d9b54..573bd572db 100644
--- a/src/test/fuzz/fuzz.h
+++ b/src/test/fuzz/fuzz.h
@@ -9,6 +9,6 @@
#include <vector>
-void test_one_input(std::vector<uint8_t> buffer);
+void test_one_input(const std::vector<uint8_t>& buffer);
#endif // BITCOIN_TEST_FUZZ_FUZZ_H
diff --git a/src/test/fuzz/script_flags.cpp b/src/test/fuzz/script_flags.cpp
index 9b90d66755..0bf5cd5c72 100644
--- a/src/test/fuzz/script_flags.cpp
+++ b/src/test/fuzz/script_flags.cpp
@@ -11,7 +11,7 @@
/** Flags that are not forbidden by an assert */
static bool IsValidFlagCombination(unsigned flags);
-void test_one_input(std::vector<uint8_t> buffer)
+void test_one_input(const std::vector<uint8_t>& buffer)
{
CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION);
try {
diff --git a/src/txdb.cpp b/src/txdb.cpp
index 18be07e6db..536bfee901 100644
--- a/src/txdb.cpp
+++ b/src/txdb.cpp
@@ -145,7 +145,7 @@ size_t CCoinsViewDB::EstimateSize() const
return db.EstimateSize(DB_COIN, (char)(DB_COIN+1));
}
-CBlockTreeDB::CBlockTreeDB(size_t nCacheSize, bool fMemory, bool fWipe) : CDBWrapper(gArgs.IsArgSet("-blocksdir") ? GetDataDir() / "blocks" / "index" : GetBlocksDir() / "index", nCacheSize, fMemory, fWipe) {
+CBlockTreeDB::CBlockTreeDB(size_t nCacheSize, bool fMemory, bool fWipe) : CDBWrapper(GetDataDir() / "blocks" / "index", nCacheSize, fMemory, fWipe) {
}
bool CBlockTreeDB::ReadBlockFileInfo(int nFile, CBlockFileInfo &info) {
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index 9257cff718..e4c1fd4bc6 100644
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -773,7 +773,7 @@ void CTxMemPool::queryHashes(std::vector<uint256>& vtxid) const
}
static TxMempoolInfo GetInfo(CTxMemPool::indexed_transaction_set::const_iterator it) {
- return TxMempoolInfo{it->GetSharedTx(), it->GetTime(), CFeeRate(it->GetFee(), it->GetTxSize()), it->GetModifiedFee() - it->GetFee()};
+ return TxMempoolInfo{it->GetSharedTx(), it->GetTime(), it->GetFee(), it->GetTxSize(), it->GetModifiedFee() - it->GetFee()};
}
std::vector<TxMempoolInfo> CTxMemPool::infoAll() const
@@ -917,7 +917,8 @@ void CTxMemPool::RemoveStaged(setEntries &stage, bool updateDescendants, MemPool
}
}
-int CTxMemPool::Expire(int64_t time) {
+int CTxMemPool::Expire(std::chrono::seconds time)
+{
AssertLockHeld(cs);
indexed_transaction_set::index<entry_time>::type::iterator it = mapTx.get<entry_time>().begin();
setEntries toremove;
diff --git a/src/txmempool.h b/src/txmempool.h
index 6e5ba445d3..229a923a28 100644
--- a/src/txmempool.h
+++ b/src/txmempool.h
@@ -102,7 +102,7 @@ public:
const CAmount& GetFee() const { return nFee; }
size_t GetTxSize() const;
size_t GetTxWeight() const { return nTxWeight; }
- int64_t GetTime() const { return nTime; }
+ std::chrono::seconds GetTime() const { return std::chrono::seconds{nTime}; }
unsigned int GetHeight() const { return entryHeight; }
int64_t GetSigOpCost() const { return sigOpCost; }
int64_t GetModifiedFee() const { return nFee + feeDelta; }
@@ -332,10 +332,13 @@ struct TxMempoolInfo
CTransactionRef tx;
/** Time the transaction entered the mempool. */
- int64_t nTime;
+ std::chrono::seconds m_time;
- /** Feerate of the transaction. */
- CFeeRate feeRate;
+ /** Fee of the transaction. */
+ CAmount fee;
+
+ /** Virtual size of the transaction. */
+ size_t vsize;
/** The fee delta. */
int64_t nFeeDelta;
@@ -657,7 +660,7 @@ public:
void TrimToSize(size_t sizelimit, std::vector<COutPoint>* pvNoSpendsRemaining = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs);
/** Expire all transaction (and their dependencies) in the mempool older than time. Return the number of removed transactions. */
- int Expire(int64_t time) EXCLUSIVE_LOCKS_REQUIRED(cs);
+ int Expire(std::chrono::seconds time) EXCLUSIVE_LOCKS_REQUIRED(cs);
/**
* Calculate the ancestor and descendant count for the given transaction.
diff --git a/src/util/macros.h b/src/util/macros.h
new file mode 100644
index 0000000000..36ea87c0fe
--- /dev/null
+++ b/src/util/macros.h
@@ -0,0 +1,11 @@
+// Copyright (c) 2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_UTIL_MACROS_H
+#define BITCOIN_UTIL_MACROS_H
+
+#define PASTE(x, y) x ## y
+#define PASTE2(x, y) PASTE(x, y)
+
+#endif // BITCOIN_UTIL_MACROS_H
diff --git a/src/util/threadnames.cpp b/src/util/threadnames.cpp
index c25e9ed661..168f9325d0 100644
--- a/src/util/threadnames.cpp
+++ b/src/util/threadnames.cpp
@@ -60,3 +60,8 @@ void util::ThreadRename(std::string&& name)
SetThreadName(("b-" + name).c_str());
SetInternalName(std::move(name));
}
+
+void util::ThreadSetInternalName(std::string&& name)
+{
+ SetInternalName(std::move(name));
+}
diff --git a/src/util/threadnames.h b/src/util/threadnames.h
index aaf07b9bf8..69a1b55bfe 100644
--- a/src/util/threadnames.h
+++ b/src/util/threadnames.h
@@ -10,8 +10,13 @@
namespace util {
//! Rename a thread both in terms of an internal (in-memory) name as well
//! as its system thread name.
+//! @note Do not call this for the main thread, as this will interfere with
+//! UNIX utilities such as top and killall. Use ThreadSetInternalName instead.
void ThreadRename(std::string&&);
+//! Set the internal (in-memory) name of the current thread only.
+void ThreadSetInternalName(std::string&&);
+
//! Get the thread's internal (in-memory) name; used e.g. for identification in
//! logging.
const std::string& ThreadGetInternalName();
diff --git a/src/util/time.h b/src/util/time.h
index e4f9996777..c0470a2136 100644
--- a/src/util/time.h
+++ b/src/util/time.h
@@ -11,6 +11,14 @@
#include <chrono>
/**
+ * Helper to count the seconds of a duration.
+ *
+ * All durations should be using std::chrono and calling this should generally be avoided in code. Though, it is still
+ * preferred to an inline t.count() to protect against a reliance on the exact type of t.
+ */
+inline int64_t count_seconds(std::chrono::seconds t) { return t.count(); }
+
+/**
* DEPRECATED
* Use either GetSystemTimeInSeconds (not mockable) or GetTime<T> (mockable)
*/
diff --git a/src/validation.cpp b/src/validation.cpp
index ac98bd61c7..726f251c5a 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -314,10 +314,10 @@ bool CheckSequenceLocks(const CTxMemPool& pool, const CTransaction& tx, int flag
// Returns the script flags which should be checked for a given block
static unsigned int GetBlockScriptFlags(const CBlockIndex* pindex, const Consensus::Params& chainparams);
-static void LimitMempoolSize(CTxMemPool& pool, size_t limit, unsigned long age)
+static void LimitMempoolSize(CTxMemPool& pool, size_t limit, std::chrono::seconds age)
EXCLUSIVE_LOCKS_REQUIRED(pool.cs, ::cs_main)
{
- int expired = pool.Expire(GetTime() - age);
+ int expired = pool.Expire(GetTime<std::chrono::seconds>() - age);
if (expired != 0) {
LogPrint(BCLog::MEMPOOL, "Expired %i transactions from the memory pool\n", expired);
}
@@ -389,7 +389,7 @@ static void UpdateMempoolForReorg(DisconnectedBlockTransactions& disconnectpool,
// We also need to remove any now-immature transactions
mempool.removeForReorg(&::ChainstateActive().CoinsTip(), ::ChainActive().Tip()->nHeight + 1, STANDARD_LOCKTIME_VERIFY_FLAGS);
// Re-limit mempool size, in case we added any transactions
- LimitMempoolSize(mempool, gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000, gArgs.GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY) * 60 * 60);
+ LimitMempoolSize(mempool, gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000, std::chrono::hours{gArgs.GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY)});
}
// Used to avoid mempool polluting consensus critical paths if CCoinsViewMempool
@@ -1011,7 +1011,7 @@ bool MemPoolAccept::Finalize(ATMPArgs& args, Workspace& ws)
// trim mempool and check if tx was trimmed
if (!bypass_limits) {
- LimitMempoolSize(m_pool, gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000, gArgs.GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY) * 60 * 60);
+ LimitMempoolSize(m_pool, gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000, std::chrono::hours{gArgs.GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY)});
if (!m_pool.exists(hash))
return state.Invalid(ValidationInvalidReason::TX_MEMPOOL_POLICY, false, REJECT_INSUFFICIENTFEE, "mempool full");
}
@@ -5041,8 +5041,8 @@ bool DumpMempool(const CTxMemPool& pool)
file << (uint64_t)vinfo.size();
for (const auto& i : vinfo) {
file << *(i.tx);
- file << (int64_t)i.nTime;
- file << (int64_t)i.nFeeDelta;
+ file << int64_t{count_seconds(i.m_time)};
+ file << int64_t{i.nFeeDelta};
mapDeltas.erase(i.tx->GetHash());
}
diff --git a/src/wallet/feebumper.cpp b/src/wallet/feebumper.cpp
index 619197a57a..b87231293f 100644
--- a/src/wallet/feebumper.cpp
+++ b/src/wallet/feebumper.cpp
@@ -57,6 +57,86 @@ static feebumper::Result PreconditionChecks(interfaces::Chain::Lock& locked_chai
return feebumper::Result::OK;
}
+//! Check if the user provided a valid feeRate
+static feebumper::Result CheckFeeRate(const CWallet* wallet, const CWalletTx& wtx, const CFeeRate& newFeerate, const int64_t maxTxSize, std::vector<std::string>& errors) {
+ // check that fee rate is higher than mempool's minimum fee
+ // (no point in bumping fee if we know that the new tx won't be accepted to the mempool)
+ // This may occur if the user set FeeRate, TotalFee or paytxfee too low, if fallbackfee is too low, or, perhaps,
+ // in a rare situation where the mempool minimum fee increased significantly since the fee estimation just a
+ // moment earlier. In this case, we report an error to the user, who may adjust the fee.
+ CFeeRate minMempoolFeeRate = wallet->chain().mempoolMinFee();
+
+ if (newFeerate.GetFeePerK() < minMempoolFeeRate.GetFeePerK()) {
+ errors.push_back(strprintf(
+ "New fee rate (%s) is lower than the minimum fee rate (%s) to get into the mempool -- ",
+ FormatMoney(newFeerate.GetFeePerK()),
+ FormatMoney(minMempoolFeeRate.GetFeePerK())));
+ return feebumper::Result::WALLET_ERROR;
+ }
+
+ CAmount new_total_fee = newFeerate.GetFee(maxTxSize);
+
+ CFeeRate incrementalRelayFee = std::max(wallet->chain().relayIncrementalFee(), CFeeRate(WALLET_INCREMENTAL_RELAY_FEE));
+
+ // Given old total fee and transaction size, calculate the old feeRate
+ CAmount old_fee = wtx.GetDebit(ISMINE_SPENDABLE) - wtx.tx->GetValueOut();
+ const int64_t txSize = GetVirtualTransactionSize(*(wtx.tx));
+ CFeeRate nOldFeeRate(old_fee, txSize);
+ // Min total fee is old fee + relay fee
+ CAmount minTotalFee = nOldFeeRate.GetFee(maxTxSize) + incrementalRelayFee.GetFee(maxTxSize);
+
+ if (new_total_fee < minTotalFee) {
+ errors.push_back(strprintf("Insufficient total fee %s, must be at least %s (oldFee %s + incrementalFee %s)",
+ FormatMoney(new_total_fee), FormatMoney(minTotalFee), FormatMoney(nOldFeeRate.GetFee(maxTxSize)), FormatMoney(incrementalRelayFee.GetFee(maxTxSize))));
+ return feebumper::Result::INVALID_PARAMETER;
+ }
+
+ CAmount requiredFee = GetRequiredFee(*wallet, maxTxSize);
+ if (new_total_fee < requiredFee) {
+ errors.push_back(strprintf("Insufficient total fee (cannot be less than required fee %s)",
+ FormatMoney(requiredFee)));
+ return feebumper::Result::INVALID_PARAMETER;
+ }
+
+ // Check that in all cases the new fee doesn't violate maxTxFee
+ const CAmount max_tx_fee = wallet->m_default_max_tx_fee;
+ if (new_total_fee > max_tx_fee) {
+ errors.push_back(strprintf("Specified or calculated fee %s is too high (cannot be higher than -maxtxfee %s)",
+ FormatMoney(new_total_fee), FormatMoney(max_tx_fee)));
+ return feebumper::Result::WALLET_ERROR;
+ }
+
+ return feebumper::Result::OK;
+}
+
+static CFeeRate EstimateFeeRate(CWallet* wallet, const CWalletTx& wtx, CCoinControl& coin_control, CAmount& old_fee)
+{
+ // Get the fee rate of the original transaction. This is calculated from
+ // the tx fee/vsize, so it may have been rounded down. Add 1 satoshi to the
+ // result.
+ old_fee = wtx.GetDebit(ISMINE_SPENDABLE) - wtx.tx->GetValueOut();
+ int64_t txSize = GetVirtualTransactionSize(*(wtx.tx));
+ CFeeRate feerate(old_fee, txSize);
+ feerate += CFeeRate(1);
+
+ // The node has a configurable incremental relay fee. Increment the fee by
+ // the minimum of that and the wallet's conservative
+ // WALLET_INCREMENTAL_RELAY_FEE value to future proof against changes to
+ // network wide policy for incremental relay fee that our node may not be
+ // aware of. This ensures we're over the over the required relay fee rate
+ // (BIP 125 rule 4). The replacement tx will be at least as large as the
+ // original tx, so the total fee will be greater (BIP 125 rule 3)
+ CFeeRate node_incremental_relay_fee = wallet->chain().relayIncrementalFee();
+ CFeeRate wallet_incremental_relay_fee = CFeeRate(WALLET_INCREMENTAL_RELAY_FEE);
+ feerate += std::max(node_incremental_relay_fee, wallet_incremental_relay_fee);
+
+ // Fee rate must also be at least the wallet's GetMinimumFeeRate
+ CFeeRate min_feerate(GetMinimumFeeRate(*wallet, coin_control, /* feeCalc */ nullptr));
+
+ // Set the required fee rate for the replacement transaction in coin control.
+ return std::max(feerate, min_feerate);
+}
+
namespace feebumper {
bool TransactionCanBeBumped(const CWallet* wallet, const uint256& txid)
@@ -230,31 +310,18 @@ Result CreateRateBumpTransaction(CWallet* wallet, const uint256& txid, const CCo
}
}
- // Get the fee rate of the original transaction. This is calculated from
- // the tx fee/vsize, so it may have been rounded down. Add 1 satoshi to the
- // result.
- old_fee = wtx.GetDebit(ISMINE_SPENDABLE) - wtx.tx->GetValueOut();
- int64_t txSize = GetVirtualTransactionSize(*(wtx.tx));
- // Feerate of thing we are bumping
- CFeeRate feerate(old_fee, txSize);
- feerate += CFeeRate(1);
-
- // The node has a configurable incremental relay fee. Increment the fee by
- // the minimum of that and the wallet's conservative
- // WALLET_INCREMENTAL_RELAY_FEE value to future proof against changes to
- // network wide policy for incremental relay fee that our node may not be
- // aware of. This ensures we're over the over the required relay fee rate
- // (BIP 125 rule 4). The replacement tx will be at least as large as the
- // original tx, so the total fee will be greater (BIP 125 rule 3)
- CFeeRate node_incremental_relay_fee = wallet->chain().relayIncrementalFee();
- CFeeRate wallet_incremental_relay_fee = CFeeRate(WALLET_INCREMENTAL_RELAY_FEE);
- feerate += std::max(node_incremental_relay_fee, wallet_incremental_relay_fee);
-
- // Fee rate must also be at least the wallet's GetMinimumFeeRate
- CFeeRate min_feerate(GetMinimumFeeRate(*wallet, new_coin_control, /* feeCalc */ nullptr));
-
- // Set the required fee rate for the replacement transaction in coin control.
- new_coin_control.m_feerate = std::max(feerate, min_feerate);
+ if (coin_control.m_feerate) {
+ // The user provided a feeRate argument.
+ // We calculate this here to avoid compiler warning on the cs_wallet lock
+ const int64_t maxTxSize = CalculateMaximumSignedTxSize(*wtx.tx, wallet);
+ Result res = CheckFeeRate(wallet, wtx, *(new_coin_control.m_feerate), maxTxSize, errors);
+ if (res != Result::OK) {
+ return res;
+ }
+ } else {
+ // The user did not provide a feeRate argument
+ new_coin_control.m_feerate = EstimateFeeRate(wallet, wtx, new_coin_control, old_fee);
+ }
// Fill in required inputs we are double-spending(all of them)
// N.B.: bip125 doesn't require all the inputs in the replaced transaction to be
diff --git a/src/wallet/init.cpp b/src/wallet/init.cpp
index e766deadb7..43b6ead028 100644
--- a/src/wallet/init.cpp
+++ b/src/wallet/init.cpp
@@ -41,7 +41,8 @@ void WalletInit::AddWalletOptions() const
gArgs.AddArg("-discardfee=<amt>", strprintf("The fee rate (in %s/kB) that indicates your tolerance for discarding change by adding it to the fee (default: %s). "
"Note: An output is discarded if it is dust at this rate, but we will always discard up to the dust relay fee and a discard fee above that is limited by the fee estimate for the longest target",
CURRENCY_UNIT, FormatMoney(DEFAULT_DISCARD_FEE)), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
- gArgs.AddArg("-fallbackfee=<amt>", strprintf("A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s)",
+
+ gArgs.AddArg("-fallbackfee=<amt>", strprintf("A fee rate (in %s/kB) that will be used when fee estimation has insufficient data. 0 to entirely disable the fallbackfee feature. (default: %s)",
CURRENCY_UNIT, FormatMoney(DEFAULT_FALLBACK_FEE)), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
gArgs.AddArg("-keypool=<n>", strprintf("Set key pool size to <n> (default: %u)", DEFAULT_KEYPOOL_SIZE), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
gArgs.AddArg("-maxtxfee=<amt>", strprintf("Maximum total fees (in %s) to use in a single wallet transaction; setting this too low may abort large transactions (default: %s)",
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index a71145fc42..0904c03669 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -2327,7 +2327,7 @@ static UniValue settxfee(const JSONRPCRequest& request)
CAmount nAmount = AmountFromValue(request.params[0]);
CFeeRate tx_fee_rate(nAmount, 1000);
- if (tx_fee_rate == 0) {
+ if (tx_fee_rate == CFeeRate(0)) {
// automatic selection
} else if (tx_fee_rate < pwallet->chain().relayMinFee()) {
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("txfee cannot be less than min relay tx fee (%s)", pwallet->chain().relayMinFee().ToString()));
@@ -3309,7 +3309,7 @@ static UniValue bumpfee(const JSONRPCRequest& request)
"The command will fail if the wallet or mempool contains a transaction that spends one of T's outputs.\n"
"By default, the new fee will be calculated automatically using estimatesmartfee.\n"
"The user can specify a confirmation target for estimatesmartfee.\n"
- "Alternatively, the user can specify totalFee (DEPRECATED), or use RPC settxfee to set a higher fee rate.\n"
+ "Alternatively, the user can specify totalFee (DEPRECATED), or fee_rate (" + CURRENCY_UNIT + " per kB) for the new transaction .\n"
"At a minimum, the new fee rate must be high enough to pay an additional new relay fee (incrementalfee\n"
"returned by getnetworkinfo) to enter the node's mempool.\n",
{
@@ -3321,6 +3321,9 @@ static UniValue bumpfee(const JSONRPCRequest& request)
" In rare cases, the actual fee paid might be slightly higher than the specified\n"
" totalFee if the tx change output has to be removed because it is too close to\n"
" the dust threshold."},
+ {"fee_rate", RPCArg::Type::NUM, /* default */ "fallback to 'confTarget'", "FeeRate (NOT total fee) to pay, in " + CURRENCY_UNIT + " per kB\n"
+ " Specify a fee rate instead of relying on the built-in fee estimator.\n"
+ " Must be at least 0.0001 BTC per kB higher than the current transaction fee rate.\n"},
{"replaceable", RPCArg::Type::BOOL, /* default */ "true", "Whether the new transaction should still be\n"
" marked bip-125 replaceable. If true, the sequence numbers in the transaction will\n"
" be left unchanged from the original. If false, any input sequence numbers in the\n"
@@ -3362,13 +3365,15 @@ static UniValue bumpfee(const JSONRPCRequest& request)
{
{"confTarget", UniValueType(UniValue::VNUM)},
{"totalFee", UniValueType(UniValue::VNUM)},
+ {"fee_rate", UniValueType(UniValue::VNUM)},
{"replaceable", UniValueType(UniValue::VBOOL)},
{"estimate_mode", UniValueType(UniValue::VSTR)},
},
true, true);
-
- if (options.exists("confTarget") && options.exists("totalFee")) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, "confTarget and totalFee options should not both be set. Please provide either a confirmation target for fee estimation or an explicit total fee for the transaction.");
+ if (options.exists("confTarget") && (options.exists("totalFee") || options.exists("fee_rate"))) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "confTarget can't be set with totalFee or fee_rate. Please provide either a confirmation target in blocks for automatic fee estimation, or an explicit fee rate.");
+ } else if (options.exists("fee_rate") && options.exists("totalFee")) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "fee_rate can't be set along with totalFee.");
} else if (options.exists("confTarget")) { // TODO: alias this to conf_target
coin_control.m_confirm_target = ParseConfirmTarget(options["confTarget"], pwallet->chain().estimateMaxBlocks());
} else if (options.exists("totalFee")) {
@@ -3379,6 +3384,12 @@ static UniValue bumpfee(const JSONRPCRequest& request)
if (totalFee <= 0) {
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid totalFee %s (must be greater than 0)", FormatMoney(totalFee)));
}
+ } else if (options.exists("fee_rate")) {
+ CFeeRate fee_rate(AmountFromValue(options["fee_rate"]));
+ if (fee_rate <= CFeeRate(0)) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid fee_rate %s (must be greater than 0)", fee_rate.ToString()));
+ }
+ coin_control.m_feerate = fee_rate;
}
if (options.exists("replaceable")) {
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 7cf09d554b..09f08220db 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -3376,6 +3376,7 @@ DBErrors CWallet::ZapSelectTx(std::vector<uint256>& vHashIn, std::vector<uint256
const auto& it = mapWallet.find(hash);
wtxOrdered.erase(it->second.m_it_wtxOrdered);
mapWallet.erase(it);
+ NotifyTransactionChanged(this, hash, CT_DELETED);
}
if (nZapSelectTxRet == DBErrors::NEED_REWRITE)
@@ -4420,7 +4421,6 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
walletInstance->m_min_fee = CFeeRate(n);
}
- walletInstance->m_allow_fallback_fee = Params().IsTestChain();
if (gArgs.IsArgSet("-fallbackfee")) {
CAmount nFeePerK = 0;
if (!ParseMoney(gArgs.GetArg("-fallbackfee", ""), nFeePerK)) {
@@ -4432,8 +4432,10 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
_("This is the transaction fee you may pay when fee estimates are not available.").translated);
}
walletInstance->m_fallback_fee = CFeeRate(nFeePerK);
- walletInstance->m_allow_fallback_fee = nFeePerK != 0; //disable fallback fee in case value was set to 0, enable if non-null value
}
+ // Disable fallback fee in case value was set to 0, enable if non-null value
+ walletInstance->m_allow_fallback_fee = walletInstance->m_fallback_fee.GetFeePerK() != 0;
+
if (gArgs.IsArgSet("-discardfee")) {
CAmount nFeePerK = 0;
if (!ParseMoney(gArgs.GetArg("-discardfee", ""), nFeePerK)) {
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index 3428e8e001..006775e83b 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -63,7 +63,7 @@ static const unsigned int DEFAULT_KEYPOOL_SIZE = 1000;
//! -paytxfee default
constexpr CAmount DEFAULT_PAY_TX_FEE = 0;
//! -fallbackfee default
-static const CAmount DEFAULT_FALLBACK_FEE = 20000;
+static const CAmount DEFAULT_FALLBACK_FEE = 0;
//! -discardfee default
static const CAmount DEFAULT_DISCARD_FEE = 10000;
//! -mintxfee default
@@ -120,7 +120,7 @@ enum WalletFeature
};
//! Default for -addresstype
-constexpr OutputType DEFAULT_ADDRESS_TYPE{OutputType::P2SH_SEGWIT};
+constexpr OutputType DEFAULT_ADDRESS_TYPE{OutputType::BECH32};
//! Default for -changetype
constexpr OutputType DEFAULT_CHANGE_TYPE{OutputType::CHANGE_AUTO};
@@ -1167,7 +1167,7 @@ public:
unsigned int m_confirm_target{DEFAULT_TX_CONFIRM_TARGET};
bool m_spend_zero_conf_change{DEFAULT_SPEND_ZEROCONF_CHANGE};
bool m_signal_rbf{DEFAULT_WALLET_RBF};
- bool m_allow_fallback_fee{true}; //!< will be defined via chainparams
+ bool m_allow_fallback_fee{true}; //!< will be false if -fallbackfee=0
CFeeRate m_min_fee{DEFAULT_TRANSACTION_MINFEE}; //!< Override with -mintxfee
/**
* If fee estimation does not have enough data to provide estimates, use this fee instead.
diff --git a/test/functional/data/rpc_bip67.json b/test/functional/data/rpc_bip67.json
new file mode 100644
index 0000000000..4d6f793d4a
--- /dev/null
+++ b/test/functional/data/rpc_bip67.json
@@ -0,0 +1,58 @@
+[
+ {
+ "keys": [
+ "02ff12471208c14bd580709cb2358d98975247d8765f92bc25eab3b2763ed605f8",
+ "02fe6f0a5a297eb38c391581c4413e084773ea23954d93f7753db7dc0adc188b2f"
+ ],
+ "sorted_keys": [
+ "02fe6f0a5a297eb38c391581c4413e084773ea23954d93f7753db7dc0adc188b2f",
+ "02ff12471208c14bd580709cb2358d98975247d8765f92bc25eab3b2763ed605f8"
+ ],
+ "script": "522102fe6f0a5a297eb38c391581c4413e084773ea23954d93f7753db7dc0adc188b2f2102ff12471208c14bd580709cb2358d98975247d8765f92bc25eab3b2763ed605f852ae",
+ "address": "2N19tNw3Ss4L9QDERtCw7FhXb6jBsYmeXNu"
+ },
+ {
+ "keys": [
+ "02632b12f4ac5b1d1b72b2a3b508c19172de44f6f46bcee50ba33f3f9291e47ed0",
+ "027735a29bae7780a9755fae7a1c4374c656ac6a69ea9f3697fda61bb99a4f3e77",
+ "02e2cc6bd5f45edd43bebe7cb9b675f0ce9ed3efe613b177588290ad188d11b404"
+ ],
+ "sorted_keys": [
+ "02632b12f4ac5b1d1b72b2a3b508c19172de44f6f46bcee50ba33f3f9291e47ed0",
+ "027735a29bae7780a9755fae7a1c4374c656ac6a69ea9f3697fda61bb99a4f3e77",
+ "02e2cc6bd5f45edd43bebe7cb9b675f0ce9ed3efe613b177588290ad188d11b404"
+ ],
+ "script": "522102632b12f4ac5b1d1b72b2a3b508c19172de44f6f46bcee50ba33f3f9291e47ed021027735a29bae7780a9755fae7a1c4374c656ac6a69ea9f3697fda61bb99a4f3e772102e2cc6bd5f45edd43bebe7cb9b675f0ce9ed3efe613b177588290ad188d11b40453ae",
+ "address": "2N3sVXU7MZefmYnZhrVX2bA7LyH6vygFZZ7"
+ },
+ {
+ "keys": [
+ "030000000000000000000000000000000000004141414141414141414141414141",
+ "020000000000000000000000000000000000004141414141414141414141414141",
+ "020000000000000000000000000000000000004141414141414141414141414140",
+ "030000000000000000000000000000000000004141414141414141414141414140"
+ ],
+ "sorted_keys": [
+ "020000000000000000000000000000000000004141414141414141414141414140",
+ "020000000000000000000000000000000000004141414141414141414141414141",
+ "030000000000000000000000000000000000004141414141414141414141414140",
+ "030000000000000000000000000000000000004141414141414141414141414141"
+ ],
+ "script": "522102000000000000000000000000000000000000414141414141414141414141414021020000000000000000000000000000000000004141414141414141414141414141210300000000000000000000000000000000000041414141414141414141414141402103000000000000000000000000000000000000414141414141414141414141414154ae",
+ "address": "2Mt3L9TcDUAfLpSoyB3SNYtJGLiU49DKEWJ"
+ },
+ {
+ "keys": [
+ "022df8750480ad5b26950b25c7ba79d3e37d75f640f8e5d9bcd5b150a0f85014da",
+ "03e3818b65bcc73a7d64064106a859cc1a5a728c4345ff0b641209fba0d90de6e9",
+ "021f2f6e1e50cb6a953935c3601284925decd3fd21bc445712576873fb8c6ebc18"
+ ],
+ "sorted_keys": [
+ "021f2f6e1e50cb6a953935c3601284925decd3fd21bc445712576873fb8c6ebc18",
+ "022df8750480ad5b26950b25c7ba79d3e37d75f640f8e5d9bcd5b150a0f85014da",
+ "03e3818b65bcc73a7d64064106a859cc1a5a728c4345ff0b641209fba0d90de6e9"
+ ],
+ "script": "5221021f2f6e1e50cb6a953935c3601284925decd3fd21bc445712576873fb8c6ebc1821022df8750480ad5b26950b25c7ba79d3e37d75f640f8e5d9bcd5b150a0f85014da2103e3818b65bcc73a7d64064106a859cc1a5a728c4345ff0b641209fba0d90de6e953ae",
+ "address": "2NFd5JqpwmQNz3gevZJ3rz9ofuHvqaP9Cye"
+ }
+]
diff --git a/test/functional/feature_bip68_sequence.py b/test/functional/feature_bip68_sequence.py
index fe6f9eade1..677362756c 100755
--- a/test/functional/feature_bip68_sequence.py
+++ b/test/functional/feature_bip68_sequence.py
@@ -29,9 +29,10 @@ NOT_FINAL_ERROR = "non-BIP68-final (code 64)"
class BIP68Test(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 2
+ # TODO remove output type argument and fix resulting "tx-size-small" errors
self.extra_args = [
- ["-acceptnonstdtxn=1"],
- ["-acceptnonstdtxn=0"],
+ ["-acceptnonstdtxn=1", "-addresstype=p2sh-segwit"],
+ ["-acceptnonstdtxn=0", "-addresstype=p2sh-segwit"],
]
def skip_test_if_missing_module(self):
diff --git a/test/functional/feature_rbf.py b/test/functional/feature_rbf.py
index fd79df0b07..a1d4ce4c73 100755
--- a/test/functional/feature_rbf.py
+++ b/test/functional/feature_rbf.py
@@ -65,6 +65,7 @@ def make_utxo(node, amount, confirmed=True, scriptPubKey=CScript([1])):
class ReplaceByFeeTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 1
+ # TODO remove output type argument and fix resulting "tx-size-small" errors
self.extra_args = [
[
"-acceptnonstdtxn=1",
@@ -73,6 +74,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
"-limitancestorsize=101",
"-limitdescendantcount=200",
"-limitdescendantsize=101",
+ "-addresstype=p2sh-segwit",
],
]
diff --git a/test/functional/mempool_persist.py b/test/functional/mempool_persist.py
index bb0169ee52..398fdeb326 100755
--- a/test/functional/mempool_persist.py
+++ b/test/functional/mempool_persist.py
@@ -37,9 +37,15 @@ Test is as follows:
"""
from decimal import Decimal
import os
+import time
from test_framework.test_framework import BitcoinTestFramework
-from test_framework.util import assert_equal, assert_raises_rpc_error, wait_until
+from test_framework.util import (
+ assert_equal,
+ assert_greater_than_or_equal,
+ assert_raises_rpc_error,
+ wait_until,
+)
class MempoolPersistTest(BitcoinTestFramework):
@@ -51,18 +57,13 @@ class MempoolPersistTest(BitcoinTestFramework):
self.skip_if_no_wallet()
def run_test(self):
- chain_height = self.nodes[0].getblockcount()
- assert_equal(chain_height, 200)
-
- self.log.debug("Mine a single block to get out of IBD")
- self.nodes[0].generate(1)
- self.sync_all()
-
self.log.debug("Send 5 transactions from node2 (to its own address)")
+ tx_creation_time_lower = int(time.time())
for i in range(5):
last_txid = self.nodes[2].sendtoaddress(self.nodes[2].getnewaddress(), Decimal("10"))
node2_balance = self.nodes[2].getbalance()
self.sync_all()
+ tx_creation_time_higher = int(time.time())
self.log.debug("Verify that node0 and node1 have 5 transactions in their mempools")
assert_equal(len(self.nodes[0].getrawmempool()), 5)
@@ -75,6 +76,10 @@ class MempoolPersistTest(BitcoinTestFramework):
fees = self.nodes[0].getmempoolentry(txid=last_txid)['fees']
assert_equal(fees['base'] + Decimal('0.00001000'), fees['modified'])
+ tx_creation_time = self.nodes[0].getmempoolentry(txid=last_txid)['time']
+ assert_greater_than_or_equal(tx_creation_time, tx_creation_time_lower)
+ assert_greater_than_or_equal(tx_creation_time_higher, tx_creation_time)
+
self.log.debug("Stop-start the nodes. Verify that node0 has the transactions in its mempool and node1 does not. Verify that node2 calculates its balance correctly after loading wallet transactions.")
self.stop_nodes()
# Give this node a head-start, so we can be "extra-sure" that it didn't load anything later
@@ -93,6 +98,9 @@ class MempoolPersistTest(BitcoinTestFramework):
fees = self.nodes[0].getmempoolentry(txid=last_txid)['fees']
assert_equal(fees['base'] + Decimal('0.00001000'), fees['modified'])
+ self.log.debug('Verify time is loaded correctly')
+ assert_equal(tx_creation_time, self.nodes[0].getmempoolentry(txid=last_txid)['time'])
+
# Verify accounting of mempool transactions after restart is correct
self.nodes[2].syncwithvalidationinterfacequeue() # Flush mempool to wallet
assert_equal(node2_balance, self.nodes[2].getbalance())
diff --git a/test/functional/p2p_feefilter.py b/test/functional/p2p_feefilter.py
index 7f901b1886..4f242bd94a 100755
--- a/test/functional/p2p_feefilter.py
+++ b/test/functional/p2p_feefilter.py
@@ -41,6 +41,12 @@ class TestP2PConn(P2PInterface):
class FeeFilterTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 2
+ # We lower the various required feerates for this test
+ # to catch a corner-case where feefilter used to slightly undercut
+ # mempool and wallet feerate calculation based on GetFee
+ # rounding down 3 places, leading to stranded transactions.
+ # See issue #16499
+ self.extra_args = [["-minrelaytxfee=0.00000100", "-mintxfee=0.00000100"]]*self.num_nodes
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
@@ -54,22 +60,25 @@ class FeeFilterTest(BitcoinTestFramework):
self.nodes[0].add_p2p_connection(TestP2PConn())
- # Test that invs are received for all txs at feerate of 20 sat/byte
- node1.settxfee(Decimal("0.00020000"))
+ # Test that invs are received by test connection for all txs at
+ # feerate of .2 sat/byte
+ node1.settxfee(Decimal("0.00000200"))
txids = [node1.sendtoaddress(node1.getnewaddress(), 1) for x in range(3)]
assert allInvsMatch(txids, self.nodes[0].p2p)
self.nodes[0].p2p.clear_invs()
- # Set a filter of 15 sat/byte
- self.nodes[0].p2p.send_and_ping(msg_feefilter(15000))
+ # Set a filter of .15 sat/byte on test connection
+ self.nodes[0].p2p.send_and_ping(msg_feefilter(150))
- # Test that txs are still being received (paying 20 sat/byte)
+ # Test that txs are still being received by test connection (paying .15 sat/byte)
+ node1.settxfee(Decimal("0.00000150"))
txids = [node1.sendtoaddress(node1.getnewaddress(), 1) for x in range(3)]
assert allInvsMatch(txids, self.nodes[0].p2p)
self.nodes[0].p2p.clear_invs()
- # Change tx fee rate to 10 sat/byte and test they are no longer received
- node1.settxfee(Decimal("0.00010000"))
+ # Change tx fee rate to .1 sat/byte and test they are no longer received
+ # by the test connection
+ node1.settxfee(Decimal("0.00000100"))
[node1.sendtoaddress(node1.getnewaddress(), 1) for x in range(3)]
self.sync_mempools() # must be sure node 0 has received all txs
diff --git a/test/functional/rpc_createmultisig.py b/test/functional/rpc_createmultisig.py
index 056e193d55..2a64a29967 100755
--- a/test/functional/rpc_createmultisig.py
+++ b/test/functional/rpc_createmultisig.py
@@ -4,6 +4,7 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test multisig RPCs"""
+from test_framework.descriptors import descsum_create
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_raises_rpc_error,
@@ -14,6 +15,8 @@ from test_framework.key import ECPubKey
import binascii
import decimal
import itertools
+import json
+import os
class RpcCreateMultiSigTest(BitcoinTestFramework):
def set_test_params(self):
@@ -72,6 +75,18 @@ class RpcCreateMultiSigTest(BitcoinTestFramework):
assert_equal(legacy_addr, node0.addmultisigaddress(2, keys, '', 'bech32')['address'])
assert_equal(legacy_addr, node0.addmultisigaddress(2, keys, '', 'p2sh-segwit')['address'])
+ self.log.info('Testing sortedmulti descriptors with BIP 67 test vectors')
+ with open(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'data/rpc_bip67.json'), encoding='utf-8') as f:
+ vectors = json.load(f)
+
+ for t in vectors:
+ key_str = ','.join(t['keys'])
+ desc = descsum_create('sh(sortedmulti(2,{}))'.format(key_str))
+ assert_equal(self.nodes[0].deriveaddresses(desc)[0], t['address'])
+ sorted_key_str = ','.join(t['sorted_keys'])
+ sorted_key_desc = descsum_create('sh(multi(2,{}))'.format(sorted_key_str))
+ assert_equal(self.nodes[0].deriveaddresses(sorted_key_desc)[0], t['address'])
+
def check_addmultisigaddress_errors(self):
self.log.info('Check that addmultisigaddress fails when the private keys are missing')
addresses = [self.nodes[1].getnewaddress(address_type='legacy') for _ in range(2)]
diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py
index 598e87558b..cde99a2219 100644
--- a/test/functional/test_framework/util.py
+++ b/test/functional/test_framework/util.py
@@ -244,7 +244,7 @@ class PortSeed:
# Must be initialized with a unique integer for each process
n = None
-def get_rpc_proxy(url, node_number, timeout=None, coveragedir=None):
+def get_rpc_proxy(url, node_number, *, timeout=None, coveragedir=None):
"""
Args:
url (str): URL of the RPC server to call
@@ -252,6 +252,7 @@ def get_rpc_proxy(url, node_number, timeout=None, coveragedir=None):
Kwargs:
timeout (int): HTTP timeout in seconds
+ coveragedir (str): Directory
Returns:
AuthServiceProxy. convenience object for making RPC calls.
@@ -307,6 +308,7 @@ def initialize_datadir(dirname, n, chain):
f.write("[{}]\n".format(chain_name_conf_section))
f.write("port=" + str(p2p_port(n)) + "\n")
f.write("rpcport=" + str(rpc_port(n)) + "\n")
+ f.write("fallbackfee=0.0002\n")
f.write("server=1\n")
f.write("keypool=1\n")
f.write("discover=0\n")
diff --git a/test/functional/wallet_address_types.py b/test/functional/wallet_address_types.py
index c41b31e2e1..b72f5c6008 100755
--- a/test/functional/wallet_address_types.py
+++ b/test/functional/wallet_address_types.py
@@ -345,7 +345,7 @@ class AddressTypeTest(BitcoinTestFramework):
self.sync_blocks()
assert_equal(self.nodes[4].getbalance(), 1)
- self.log.info("Nodes with addresstype=legacy never use a P2WPKH change output")
+ self.log.info("Nodes with addresstype=legacy never use a P2WPKH change output (unless changetype is set otherwise):")
self.test_change_output_type(0, [to_address_bech32_1], 'legacy')
self.log.info("Nodes with addresstype=p2sh-segwit only use a P2WPKH change output if any destination address is bech32:")
diff --git a/test/functional/wallet_basic.py b/test/functional/wallet_basic.py
index 96ea5c9c35..550037923e 100755
--- a/test/functional/wallet_basic.py
+++ b/test/functional/wallet_basic.py
@@ -317,7 +317,7 @@ class WalletTest(BitcoinTestFramework):
assert_raises_rpc_error(-5, "Invalid private key encoding", self.nodes[0].importprivkey, "invalid")
# This will raise an exception for importing an address with the PS2H flag
- temp_address = self.nodes[1].getnewaddress()
+ temp_address = self.nodes[1].getnewaddress("", "p2sh-segwit")
assert_raises_rpc_error(-5, "Cannot use the p2sh flag with an address - use a script instead", self.nodes[0].importaddress, temp_address, "label", False, True)
# This will raise an exception for attempting to dump the private key of an address you do not own
diff --git a/test/functional/wallet_bumpfee.py b/test/functional/wallet_bumpfee.py
index a7c79ec916..0948d47653 100755
--- a/test/functional/wallet_bumpfee.py
+++ b/test/functional/wallet_bumpfee.py
@@ -38,6 +38,7 @@ class BumpFeeTest(BitcoinTestFramework):
"-walletrbf={}".format(i),
"-mintxfee=0.00002",
"-deprecatedrpc=totalFee",
+ "-addresstype=p2sh-segwit", # TODO update constants in test and remove
] for i in range(self.num_nodes)]
def skip_test_if_missing_module(self):
@@ -67,7 +68,9 @@ class BumpFeeTest(BitcoinTestFramework):
self.log.info("Running tests")
dest_address = peer_node.getnewaddress()
- test_simple_bumpfee_succeeds(self, rbf_node, peer_node, dest_address)
+ test_simple_bumpfee_succeeds(self, "default", rbf_node, peer_node, dest_address)
+ test_simple_bumpfee_succeeds(self, "fee_rate", rbf_node, peer_node, dest_address)
+ test_feerate_args(self, rbf_node, peer_node, dest_address)
test_segwit_bumpfee_succeeds(rbf_node, dest_address)
test_nonrbf_bumpfee_fails(peer_node, dest_address)
test_notmine_bumpfee_fails(rbf_node, peer_node, dest_address)
@@ -88,12 +91,15 @@ class BumpFeeTest(BitcoinTestFramework):
self.log.info("Success")
-def test_simple_bumpfee_succeeds(self, rbf_node, peer_node, dest_address):
+def test_simple_bumpfee_succeeds(self, mode, rbf_node, peer_node, dest_address):
rbfid = spend_one_input(rbf_node, dest_address)
rbftx = rbf_node.gettransaction(rbfid)
self.sync_mempools((rbf_node, peer_node))
assert rbfid in rbf_node.getrawmempool() and rbfid in peer_node.getrawmempool()
- bumped_tx = rbf_node.bumpfee(rbfid)
+ if mode == "fee_rate":
+ bumped_tx = rbf_node.bumpfee(rbfid, {"fee_rate":0.0015})
+ else:
+ bumped_tx = rbf_node.bumpfee(rbfid)
assert_equal(bumped_tx["errors"], [])
assert bumped_tx["fee"] - abs(rbftx["fee"]) > 0
# check that bumped_tx propagates, original tx was evicted and has a wallet conflict
@@ -109,6 +115,22 @@ def test_simple_bumpfee_succeeds(self, rbf_node, peer_node, dest_address):
assert_equal(oldwtx["replaced_by_txid"], bumped_tx["txid"])
assert_equal(bumpedwtx["replaces_txid"], rbfid)
+def test_feerate_args(self, rbf_node, peer_node, dest_address):
+ rbfid = spend_one_input(rbf_node, dest_address)
+ self.sync_mempools((rbf_node, peer_node))
+ assert rbfid in rbf_node.getrawmempool() and rbfid in peer_node.getrawmempool()
+
+ assert_raises_rpc_error(-8, "confTarget can't be set with totalFee or fee_rate. Please provide either a confirmation target in blocks for automatic fee estimation, or an explicit fee rate.", rbf_node.bumpfee, rbfid, {"fee_rate":0.00001, "confTarget":1})
+ assert_raises_rpc_error(-8, "confTarget can't be set with totalFee or fee_rate. Please provide either a confirmation target in blocks for automatic fee estimation, or an explicit fee rate.", rbf_node.bumpfee, rbfid, {"totalFee":0.00001, "confTarget":1})
+ assert_raises_rpc_error(-8, "fee_rate can't be set along with totalFee.", rbf_node.bumpfee, rbfid, {"fee_rate":0.00001, "totalFee":0.001})
+
+ # Bumping to just above minrelay should fail to increase total fee enough, at least
+ assert_raises_rpc_error(-8, "Insufficient total fee", rbf_node.bumpfee, rbfid, {"fee_rate":0.00001000})
+
+ assert_raises_rpc_error(-3, "Amount out of range", rbf_node.bumpfee, rbfid, {"fee_rate":-1})
+
+ assert_raises_rpc_error(-4, "is too high (cannot be higher than", rbf_node.bumpfee, rbfid, {"fee_rate":1})
+
def test_segwit_bumpfee_succeeds(rbf_node, dest_address):
# Create a transaction with segwit output, then create an RBF transaction
@@ -176,7 +198,6 @@ def test_bumpfee_with_descendant_fails(rbf_node, rbf_node_address, dest_address)
rbf_node.sendrawtransaction(tx["hex"])
assert_raises_rpc_error(-8, "Transaction has descendants in the wallet", rbf_node.bumpfee, parent_id)
-
def test_small_output_fails(rbf_node, dest_address):
# cannot bump fee with a too-small output
rbfid = spend_one_input(rbf_node, dest_address)
diff --git a/test/functional/wallet_import_with_label.py b/test/functional/wallet_import_with_label.py
index a623b75606..2a9051b1e8 100755
--- a/test/functional/wallet_import_with_label.py
+++ b/test/functional/wallet_import_with_label.py
@@ -100,8 +100,8 @@ class ImportWithLabel(BitcoinTestFramework):
"Test importprivkey won't label new dests with the same "
"label as others labeled dests for the same key."
)
- self.log.info("Import a watch-only legacy address with a label.")
- address4 = self.nodes[0].getnewaddress()
+ self.log.info("Import a watch-only p2sh-segwit address with a label.")
+ address4 = self.nodes[0].getnewaddress("", "p2sh-segwit")
label4_addr = "Test Label 4 for importaddress"
self.nodes[1].importaddress(address4, label4_addr)
test_address(self.nodes[1],