mirror of
https://github.com/ElementsProject/elements.git
synced 2026-08-16 13:01:19 +02:00
Merge caa2f3af29 into merged_master (Bitcoin PR #12134)
This commit is contained in:
commit
bca8bce3b7
12 changed files with 521 additions and 8 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -108,6 +108,9 @@ qrc_*.cpp
|
|||
.DS_Store
|
||||
build
|
||||
|
||||
# Previous releases
|
||||
releases
|
||||
|
||||
#lcov
|
||||
*.gcno
|
||||
*.gcda
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ cache:
|
|||
- $TRAVIS_BUILD_DIR/depends/built
|
||||
- $TRAVIS_BUILD_DIR/depends/sdk-sources
|
||||
- $TRAVIS_BUILD_DIR/ci/scratch/.ccache
|
||||
- $TRAVIS_BUILD_DIR/releases/$HOST
|
||||
# macOS
|
||||
- $HOME/Library/Caches/Homebrew
|
||||
- /usr/local/Homebrew
|
||||
|
|
@ -146,7 +147,7 @@ jobs:
|
|||
|
||||
# x86_64 Linux (uses qt5 dev package instead of depends Qt to speed up build and avoid timeout), no unit tests
|
||||
- stage: test
|
||||
name: 'x86_64 Linux [GOAL: install] [bionic] [uses qt5 dev package and some depends packages]'
|
||||
name: 'x86_64 Linux [GOAL: install] [bionic] [previous releases, uses qt5 dev package and some depends packages]'
|
||||
env: >-
|
||||
HOST=x86_64-unknown-linux-gnu
|
||||
PACKAGES="python3-zmq qtbase5-dev qttools5-dev-tools protobuf-compiler libdbus-1-dev libharfbuzz-dev libprotobuf-dev"
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ If the repository is not a fresh git clone, you might have to clean files from p
|
|||
|
||||
The ci needs to perform various sysadmin tasks such as installing packages or writing to the user's home directory.
|
||||
While most of the actions are done inside a docker container, this is not possible for all. Thus, cache directories,
|
||||
such as the depends cache or ccache, are mounted as read-write into the docker container. While it should be fine to run
|
||||
such as the depends cache, previous release binaries, or ccache, are mounted as read-write into the docker container. While it should be fine to run
|
||||
the ci system locally on you development box, the ci scripts can generally be assumed to have received less review and
|
||||
testing compared to other parts of the codebase. If you want to keep the work tree clean, you might want to run the ci
|
||||
system in a virtual machine with a Linux operating system of your choice.
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ export HOST=${HOST:-$("$BASE_ROOT_DIR/depends/config.guess")}
|
|||
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 TEST_PREVIOUS_RELEASES=${TEST_PREVIOUS_RELEASES:-false}
|
||||
export RUN_FUZZ_TESTS=${RUN_FUZZ_TESTS:-false}
|
||||
export CONTAINER_NAME=${CONTAINER_NAME:-ci_unnamed}
|
||||
export DOCKER_NAME_TAG=${DOCKER_NAME_TAG:-ubuntu:18.04}
|
||||
|
|
@ -50,6 +51,7 @@ export CCACHE_DIR=${CCACHE_DIR:-$BASE_SCRATCH_DIR/.ccache}
|
|||
export DEPENDS_DIR=${DEPENDS_DIR:-$BASE_ROOT_DIR/depends}
|
||||
# Folder where the build is done (bin and lib).
|
||||
export BASE_OUTDIR=${BASE_OUTDIR:-$BASE_SCRATCH_DIR/out/$HOST}
|
||||
export PREVIOUS_RELEASES_DIR=${PREVIOUS_RELEASES_DIR:-$BASE_ROOT_DIR/releases/$HOST}
|
||||
export SDK_URL=${SDK_URL:-https://bitcoincore.org/depends-sources/sdks}
|
||||
export WINEDEBUG=${WINEDEBUG:-fixme-all}
|
||||
export DOCKER_PACKAGES=${DOCKER_PACKAGES:-build-essential libtool autotools-dev automake pkg-config bsdmainutils curl ca-certificates ccache python3 rsync git procps}
|
||||
|
|
|
|||
|
|
@ -11,4 +11,5 @@ export PACKAGES="python3-zmq qtbase5-dev qttools5-dev-tools libdbus-1-dev libhar
|
|||
export DEP_OPTS="NO_QT=1 NO_UPNP=1 DEBUG=1 ALLOW_HOST_PACKAGES=1"
|
||||
export TEST_RUNNER_EXTRA="--coverage --extended --exclude feature_dbcrash" # Run extended tests so that coverage does not fail, but exclude the very slow dbcrash
|
||||
export GOAL="install"
|
||||
export TEST_PREVIOUS_RELEASES=true
|
||||
export BITCOIN_CONFIG="--enable-zmq --with-gui=qt5 --enable-glibc-back-compat --enable-reduce-exports --enable-debug CFLAGS=\"-g0 -O2 -funsigned-char\" CXXFLAGS=\"-g0 -O2 -funsigned-char\""
|
||||
|
|
|
|||
|
|
@ -40,12 +40,13 @@ fi
|
|||
|
||||
mkdir -p "${BASE_SCRATCH_DIR}"
|
||||
mkdir -p "${CCACHE_DIR}"
|
||||
mkdir -p "${PREVIOUS_RELEASES_DIR}"
|
||||
|
||||
export ASAN_OPTIONS="detect_stack_use_after_return=1:check_initialization_order=1:strict_init_order=1"
|
||||
export LSAN_OPTIONS="suppressions=${BASE_ROOT_DIR}/test/sanitizer_suppressions/lsan"
|
||||
export TSAN_OPTIONS="suppressions=${BASE_ROOT_DIR}/test/sanitizer_suppressions/tsan:log_path=${BASE_SCRATCH_DIR}/sanitizer-output/tsan"
|
||||
export UBSAN_OPTIONS="suppressions=${BASE_ROOT_DIR}/test/sanitizer_suppressions/ubsan:print_stacktrace=1:halt_on_error=1:report_error_type=1"
|
||||
env | grep -E '^(BITCOIN_CONFIG|BASE_|QEMU_|CCACHE_|WINEDEBUG|LC_ALL|BOOST_TEST_RANDOM|CONFIG_SHELL|(ASAN|LSAN|TSAN|UBSAN)_OPTIONS)' | tee /tmp/env
|
||||
env | grep -E '^(BITCOIN_CONFIG|BASE_|QEMU_|CCACHE_|WINEDEBUG|LC_ALL|BOOST_TEST_RANDOM|CONFIG_SHELL|(ASAN|LSAN|TSAN|UBSAN)_OPTIONS|TEST_PREVIOUS_RELEASES|PREVIOUS_RELEASES_DIR)' | tee /tmp/env
|
||||
if [[ $HOST = *-mingw32 ]]; then
|
||||
DOCKER_ADMIN="--cap-add SYS_ADMIN"
|
||||
elif [[ $BITCOIN_CONFIG = *--with-sanitizers=*address* ]]; then # If ran with (ASan + LSan), Docker needs access to ptrace (https://github.com/google/sanitizers/issues/764)
|
||||
|
|
@ -62,6 +63,7 @@ if [ -z "$RUN_CI_ON_HOST" ]; then
|
|||
--mount type=bind,src=$BASE_ROOT_DIR,dst=/ro_base,readonly \
|
||||
--mount type=bind,src=$CCACHE_DIR,dst=$CCACHE_DIR \
|
||||
--mount type=bind,src=$DEPENDS_DIR,dst=$DEPENDS_DIR \
|
||||
--mount type=bind,src=$PREVIOUS_RELEASES_DIR,dst=$PREVIOUS_RELEASES_DIR \
|
||||
-w $BASE_ROOT_DIR \
|
||||
--env-file /tmp/env \
|
||||
--name $CONTAINER_NAME \
|
||||
|
|
|
|||
|
|
@ -35,3 +35,8 @@ if [ -z "$NO_DEPENDS" ]; then
|
|||
fi
|
||||
DOCKER_EXEC $SHELL_OPTS make $MAKEJOBS -C depends HOST=$HOST $DEP_OPTS
|
||||
fi
|
||||
if [ "$TEST_PREVIOUS_RELEASES" = "true" ]; then
|
||||
BEGIN_FOLD previous-versions
|
||||
DOCKER_EXEC contrib/devtools/previous_release.sh -b -t "$PREVIOUS_RELEASES_DIR" v0.17.1 v0.18.1 v0.19.0.1
|
||||
END_FOLD
|
||||
fi
|
||||
|
|
|
|||
149
contrib/devtools/previous_release.sh
Executable file
149
contrib/devtools/previous_release.sh
Executable file
|
|
@ -0,0 +1,149 @@
|
|||
#!/usr/bin/env bash
|
||||
#
|
||||
# Copyright (c) 2018-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.
|
||||
#
|
||||
# Build previous releases.
|
||||
|
||||
export LC_ALL=C
|
||||
|
||||
CONFIG_FLAGS=""
|
||||
FUNCTIONAL_TESTS=0
|
||||
DELETE_EXISTING=0
|
||||
USE_DEPENDS=0
|
||||
DOWNLOAD_BINARY=0
|
||||
CONFIG_FLAGS=""
|
||||
TARGET="releases"
|
||||
|
||||
while getopts ":hfrdbt:" opt; do
|
||||
case $opt in
|
||||
h)
|
||||
echo "Usage: .previous_release.sh [options] tag1 tag2"
|
||||
echo " options:"
|
||||
echo " -h Print this message"
|
||||
echo " -f Configure for functional tests"
|
||||
echo " -r Remove existing directory"
|
||||
echo " -d Use depends"
|
||||
echo " -b Download release binary"
|
||||
echo " -t Target directory (default: releases)"
|
||||
exit 0
|
||||
;;
|
||||
f)
|
||||
FUNCTIONAL_TESTS=1
|
||||
CONFIG_FLAGS="$CONFIG_FLAGS --without-gui --disable-tests --disable-bench"
|
||||
;;
|
||||
r)
|
||||
DELETE_EXISTING=1
|
||||
;;
|
||||
d)
|
||||
USE_DEPENDS=1
|
||||
;;
|
||||
b)
|
||||
DOWNLOAD_BINARY=1
|
||||
;;
|
||||
t)
|
||||
TARGET=$OPTARG
|
||||
;;
|
||||
\?)
|
||||
echo "Invalid option: -$OPTARG" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
shift $((OPTIND-1))
|
||||
|
||||
if [ -z "$1" ]; then
|
||||
echo "Specify release tag(s), e.g.: .previous_release v0.15.1"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -d "$TARGET" ]; then
|
||||
mkdir -p $TARGET
|
||||
fi
|
||||
|
||||
if [ "$DOWNLOAD_BINARY" -eq "1" ]; then
|
||||
HOST="${HOST:-$(./depends/config.guess)}"
|
||||
case "$HOST" in
|
||||
x86_64-*-linux*)
|
||||
PLATFORM=x86_64-linux-gnu
|
||||
;;
|
||||
x86_64-apple-darwin*)
|
||||
PLATFORM=osx64
|
||||
;;
|
||||
*)
|
||||
echo "Not sure which binary to download for $HOST."
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
echo "Releases directory: $TARGET"
|
||||
pushd "$TARGET" || exit 1
|
||||
{
|
||||
for tag in "$@"
|
||||
do
|
||||
if [ "$DELETE_EXISTING" -eq "1" ]; then
|
||||
if [ -d "$tag" ]; then
|
||||
rm -r "$tag"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$DOWNLOAD_BINARY" -eq "0" ]; then
|
||||
|
||||
if [ ! -d "$tag" ]; then
|
||||
if [ -z $(git tag -l "$tag") ]; then
|
||||
echo "Tag $tag not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
git clone https://github.com/bitcoin/bitcoin "$tag"
|
||||
pushd "$tag" || exit 1
|
||||
{
|
||||
git checkout "$tag"
|
||||
if [ "$USE_DEPENDS" -eq "1" ]; then
|
||||
pushd depends || exit 1
|
||||
{
|
||||
if [ "$FUNCTIONAL_TESTS" -eq "1" ]; then
|
||||
make NO_QT=1
|
||||
else
|
||||
make
|
||||
fi
|
||||
HOST="${HOST:-$(./config.guess)}"
|
||||
}
|
||||
popd || exit 1
|
||||
CONFIG_FLAGS="--prefix=$PWD/depends/$HOST $CONFIG_FLAGS"
|
||||
fi
|
||||
./autogen.sh
|
||||
./configure $CONFIG_FLAGS
|
||||
make
|
||||
# Move binaries, so they're in the same place as in the release download:
|
||||
mkdir bin
|
||||
mv src/bitcoind src/bitcoin-cli src/bitcoin-tx bin
|
||||
if [ "$FUNCTIONAL_TESTS" -eq "0" ]; then
|
||||
mv src/qt/bitcoin-qt bin
|
||||
fi
|
||||
}
|
||||
popd || exit 1
|
||||
fi
|
||||
else
|
||||
if [ -d "$tag" ]; then
|
||||
echo "Using cached $tag"
|
||||
else
|
||||
mkdir "$tag"
|
||||
if [[ "$tag" =~ v(.*)(rc[0-9]+)$ ]]; then
|
||||
BIN_PATH="bin/bitcoin-core-${BASH_REMATCH[1]}/test.${BASH_REMATCH[2]}"
|
||||
else
|
||||
BIN_PATH="bin/bitcoin-core-${tag:1}"
|
||||
fi
|
||||
URL="https://bitcoin.org/$BIN_PATH/bitcoin-${tag:1}-$PLATFORM.tar.gz"
|
||||
echo "Fetching: $URL"
|
||||
curl -O $URL
|
||||
tar -zxf "bitcoin-${tag:1}-$PLATFORM.tar.gz" -C "$tag" --strip-components=1 "bitcoin-${tag:1}"
|
||||
rm "bitcoin-${tag:1}-$PLATFORM.tar.gz"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
}
|
||||
popd || exit 1
|
||||
335
test/functional/feature_backwards_compatibility.py
Executable file
335
test/functional/feature_backwards_compatibility.py
Executable file
|
|
@ -0,0 +1,335 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2018-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.
|
||||
"""Backwards compatibility functional test
|
||||
|
||||
Test various backwards compatibility scenarios. Download the previous node binaries:
|
||||
|
||||
contrib/devtools/previous_release.sh -b v0.19.0.1 v0.18.1 v0.17.1
|
||||
|
||||
Due to RPC changes introduced in various versions the below tests
|
||||
won't work for older versions without some patches or workarounds.
|
||||
|
||||
Use only the latest patch version of each release, unless a test specifically
|
||||
needs an older patch version.
|
||||
"""
|
||||
|
||||
import os
|
||||
import shutil
|
||||
|
||||
from test_framework.test_framework import BitcoinTestFramework, SkipTest
|
||||
from test_framework.descriptors import descsum_create
|
||||
|
||||
from test_framework.util import (
|
||||
assert_equal,
|
||||
sync_blocks,
|
||||
sync_mempools
|
||||
)
|
||||
|
||||
class BackwardsCompatibilityTest(BitcoinTestFramework):
|
||||
def set_test_params(self):
|
||||
self.setup_clean_chain = True
|
||||
self.num_nodes = 5
|
||||
# Add new version after each release:
|
||||
self.extra_args = [
|
||||
["-addresstype=bech32"], # Pre-release: use to mine blocks
|
||||
["-nowallet", "-walletrbf=1", "-addresstype=bech32"], # Pre-release: use to receive coins, swap wallets, etc
|
||||
["-nowallet", "-walletrbf=1", "-addresstype=bech32"], # v0.19.0.1
|
||||
["-nowallet", "-walletrbf=1", "-addresstype=bech32"], # v0.18.1
|
||||
["-nowallet", "-walletrbf=1", "-addresstype=bech32"] # v0.17.1
|
||||
]
|
||||
|
||||
def setup_nodes(self):
|
||||
if os.getenv("TEST_PREVIOUS_RELEASES") == "false":
|
||||
raise SkipTest("backwards compatibility tests")
|
||||
|
||||
releases_path = os.getenv("PREVIOUS_RELEASES_DIR") or os.getcwd() + "/releases"
|
||||
if not os.path.isdir(releases_path):
|
||||
if os.getenv("TEST_PREVIOUS_RELEASES") == "true":
|
||||
raise AssertionError("TEST_PREVIOUS_RELEASES=1 but releases missing: " + releases_path)
|
||||
raise SkipTest("This test requires binaries for previous releases")
|
||||
|
||||
self.add_nodes(self.num_nodes, extra_args=self.extra_args, versions=[
|
||||
None,
|
||||
None,
|
||||
190000,
|
||||
180100,
|
||||
170100
|
||||
], binary=[
|
||||
self.options.bitcoind,
|
||||
self.options.bitcoind,
|
||||
releases_path + "/v0.19.0.1/bin/bitcoind",
|
||||
releases_path + "/v0.18.1/bin/bitcoind",
|
||||
releases_path + "/v0.17.1/bin/bitcoind"
|
||||
], binary_cli=[
|
||||
self.options.bitcoincli,
|
||||
self.options.bitcoincli,
|
||||
releases_path + "/v0.19.0.1/bin/bitcoin-cli",
|
||||
releases_path + "/v0.18.1/bin/bitcoin-cli",
|
||||
releases_path + "/v0.17.1/bin/bitcoin-cli"
|
||||
])
|
||||
|
||||
self.start_nodes()
|
||||
|
||||
def run_test(self):
|
||||
self.nodes[0].generatetoaddress(101, self.nodes[0].getnewaddress())
|
||||
|
||||
sync_blocks(self.nodes)
|
||||
|
||||
# Sanity check the test framework:
|
||||
res = self.nodes[self.num_nodes - 1].getblockchaininfo()
|
||||
assert_equal(res['blocks'], 101)
|
||||
|
||||
node_master = self.nodes[self.num_nodes - 4]
|
||||
node_v19 = self.nodes[self.num_nodes - 3]
|
||||
node_v18 = self.nodes[self.num_nodes - 2]
|
||||
node_v17 = self.nodes[self.num_nodes - 1]
|
||||
|
||||
self.log.info("Test wallet backwards compatibility...")
|
||||
# Create a number of wallets and open them in older versions:
|
||||
|
||||
# w1: regular wallet, created on master: update this test when default
|
||||
# wallets can no longer be opened by older versions.
|
||||
node_master.createwallet(wallet_name="w1")
|
||||
wallet = node_master.get_wallet_rpc("w1")
|
||||
info = wallet.getwalletinfo()
|
||||
assert info['private_keys_enabled']
|
||||
assert info['keypoolsize'] > 0
|
||||
# Create a confirmed transaction, receiving coins
|
||||
address = wallet.getnewaddress()
|
||||
self.nodes[0].sendtoaddress(address, 10)
|
||||
sync_mempools(self.nodes)
|
||||
self.nodes[0].generate(1)
|
||||
sync_blocks(self.nodes)
|
||||
# Create a conflicting transaction using RBF
|
||||
return_address = self.nodes[0].getnewaddress()
|
||||
tx1_id = self.nodes[1].sendtoaddress(return_address, 1)
|
||||
tx2_id = self.nodes[1].bumpfee(tx1_id)["txid"]
|
||||
# Confirm the transaction
|
||||
sync_mempools(self.nodes)
|
||||
self.nodes[0].generate(1)
|
||||
sync_blocks(self.nodes)
|
||||
# Create another conflicting transaction using RBF
|
||||
tx3_id = self.nodes[1].sendtoaddress(return_address, 1)
|
||||
tx4_id = self.nodes[1].bumpfee(tx3_id)["txid"]
|
||||
# Abondon transaction, but don't confirm
|
||||
self.nodes[1].abandontransaction(tx3_id)
|
||||
|
||||
# w1_v19: regular wallet, created with v0.19
|
||||
node_v19.createwallet(wallet_name="w1_v19")
|
||||
wallet = node_v19.get_wallet_rpc("w1_v19")
|
||||
info = wallet.getwalletinfo()
|
||||
assert info['private_keys_enabled']
|
||||
assert info['keypoolsize'] > 0
|
||||
|
||||
# w1_v18: regular wallet, created with v0.18
|
||||
node_v18.createwallet(wallet_name="w1_v18")
|
||||
wallet = node_v18.get_wallet_rpc("w1_v18")
|
||||
info = wallet.getwalletinfo()
|
||||
assert info['private_keys_enabled']
|
||||
assert info['keypoolsize'] > 0
|
||||
|
||||
# w2: wallet with private keys disabled, created on master: update this
|
||||
# test when default wallets private keys disabled can no longer be
|
||||
# opened by older versions.
|
||||
node_master.createwallet(wallet_name="w2", disable_private_keys=True)
|
||||
wallet = node_master.get_wallet_rpc("w2")
|
||||
info = wallet.getwalletinfo()
|
||||
assert info['private_keys_enabled'] == False
|
||||
assert info['keypoolsize'] == 0
|
||||
|
||||
# w2_v19: wallet with private keys disabled, created with v0.19
|
||||
node_v19.createwallet(wallet_name="w2_v19", disable_private_keys=True)
|
||||
wallet = node_v19.get_wallet_rpc("w2_v19")
|
||||
info = wallet.getwalletinfo()
|
||||
assert info['private_keys_enabled'] == False
|
||||
assert info['keypoolsize'] == 0
|
||||
|
||||
# w2_v18: wallet with private keys disabled, created with v0.18
|
||||
node_v18.createwallet(wallet_name="w2_v18", disable_private_keys=True)
|
||||
wallet = node_v18.get_wallet_rpc("w2_v18")
|
||||
info = wallet.getwalletinfo()
|
||||
assert info['private_keys_enabled'] == False
|
||||
assert info['keypoolsize'] == 0
|
||||
|
||||
# w3: blank wallet, created on master: update this
|
||||
# test when default blank wallets can no longer be opened by older versions.
|
||||
node_master.createwallet(wallet_name="w3", blank=True)
|
||||
wallet = node_master.get_wallet_rpc("w3")
|
||||
info = wallet.getwalletinfo()
|
||||
assert info['private_keys_enabled']
|
||||
assert info['keypoolsize'] == 0
|
||||
|
||||
# w3_v19: blank wallet, created with v0.19
|
||||
node_v19.createwallet(wallet_name="w3_v19", blank=True)
|
||||
wallet = node_v19.get_wallet_rpc("w3_v19")
|
||||
info = wallet.getwalletinfo()
|
||||
assert info['private_keys_enabled']
|
||||
assert info['keypoolsize'] == 0
|
||||
|
||||
# w3_v18: blank wallet, created with v0.18
|
||||
node_v18.createwallet(wallet_name="w3_v18", blank=True)
|
||||
wallet = node_v18.get_wallet_rpc("w3_v18")
|
||||
info = wallet.getwalletinfo()
|
||||
assert info['private_keys_enabled']
|
||||
assert info['keypoolsize'] == 0
|
||||
|
||||
# Copy the wallets to older nodes:
|
||||
node_master_wallets_dir = os.path.join(node_master.datadir, "regtest/wallets")
|
||||
node_v19_wallets_dir = os.path.join(node_v19.datadir, "regtest/wallets")
|
||||
node_v18_wallets_dir = os.path.join(node_v18.datadir, "regtest/wallets")
|
||||
node_v17_wallets_dir = os.path.join(node_v17.datadir, "regtest/wallets")
|
||||
node_master.unloadwallet("w1")
|
||||
node_master.unloadwallet("w2")
|
||||
node_v19.unloadwallet("w1_v19")
|
||||
node_v19.unloadwallet("w2_v19")
|
||||
node_v18.unloadwallet("w1_v18")
|
||||
node_v18.unloadwallet("w2_v18")
|
||||
|
||||
# Copy wallets to v0.17
|
||||
for wallet in os.listdir(node_master_wallets_dir):
|
||||
shutil.copytree(
|
||||
os.path.join(node_master_wallets_dir, wallet),
|
||||
os.path.join(node_v17_wallets_dir, wallet)
|
||||
)
|
||||
for wallet in os.listdir(node_v18_wallets_dir):
|
||||
shutil.copytree(
|
||||
os.path.join(node_v18_wallets_dir, wallet),
|
||||
os.path.join(node_v17_wallets_dir, wallet)
|
||||
)
|
||||
|
||||
# Copy wallets to v0.18
|
||||
for wallet in os.listdir(node_master_wallets_dir):
|
||||
shutil.copytree(
|
||||
os.path.join(node_master_wallets_dir, wallet),
|
||||
os.path.join(node_v18_wallets_dir, wallet)
|
||||
)
|
||||
|
||||
# Copy wallets to v0.19
|
||||
for wallet in os.listdir(node_master_wallets_dir):
|
||||
shutil.copytree(
|
||||
os.path.join(node_master_wallets_dir, wallet),
|
||||
os.path.join(node_v19_wallets_dir, wallet)
|
||||
)
|
||||
|
||||
# Open the wallets in v0.19
|
||||
node_v19.loadwallet("w1")
|
||||
wallet = node_v19.get_wallet_rpc("w1")
|
||||
info = wallet.getwalletinfo()
|
||||
assert info['private_keys_enabled']
|
||||
assert info['keypoolsize'] > 0
|
||||
txs = wallet.listtransactions()
|
||||
assert_equal(len(txs), 5)
|
||||
assert_equal(txs[1]["txid"], tx1_id)
|
||||
assert_equal(txs[2]["walletconflicts"], [tx1_id])
|
||||
assert_equal(txs[1]["replaced_by_txid"], tx2_id)
|
||||
assert not(txs[1]["abandoned"])
|
||||
assert_equal(txs[1]["confirmations"], -1)
|
||||
assert_equal(txs[2]["blockindex"], 1)
|
||||
assert txs[3]["abandoned"]
|
||||
assert_equal(txs[4]["walletconflicts"], [tx3_id])
|
||||
assert_equal(txs[3]["replaced_by_txid"], tx4_id)
|
||||
assert not(hasattr(txs[3], "blockindex"))
|
||||
|
||||
node_v19.loadwallet("w2")
|
||||
wallet = node_v19.get_wallet_rpc("w2")
|
||||
info = wallet.getwalletinfo()
|
||||
assert info['private_keys_enabled'] == False
|
||||
assert info['keypoolsize'] == 0
|
||||
|
||||
node_v19.loadwallet("w3")
|
||||
wallet = node_v19.get_wallet_rpc("w3")
|
||||
info = wallet.getwalletinfo()
|
||||
assert info['private_keys_enabled']
|
||||
assert info['keypoolsize'] == 0
|
||||
|
||||
# Open the wallets in v0.18
|
||||
node_v18.loadwallet("w1")
|
||||
wallet = node_v18.get_wallet_rpc("w1")
|
||||
info = wallet.getwalletinfo()
|
||||
assert info['private_keys_enabled']
|
||||
assert info['keypoolsize'] > 0
|
||||
txs = wallet.listtransactions()
|
||||
assert_equal(len(txs), 5)
|
||||
assert_equal(txs[1]["txid"], tx1_id)
|
||||
assert_equal(txs[2]["walletconflicts"], [tx1_id])
|
||||
assert_equal(txs[1]["replaced_by_txid"], tx2_id)
|
||||
assert not(txs[1]["abandoned"])
|
||||
assert_equal(txs[1]["confirmations"], -1)
|
||||
assert_equal(txs[2]["blockindex"], 1)
|
||||
assert txs[3]["abandoned"]
|
||||
assert_equal(txs[4]["walletconflicts"], [tx3_id])
|
||||
assert_equal(txs[3]["replaced_by_txid"], tx4_id)
|
||||
assert not(hasattr(txs[3], "blockindex"))
|
||||
|
||||
node_v18.loadwallet("w2")
|
||||
wallet = node_v18.get_wallet_rpc("w2")
|
||||
info = wallet.getwalletinfo()
|
||||
assert info['private_keys_enabled'] == False
|
||||
assert info['keypoolsize'] == 0
|
||||
|
||||
node_v18.loadwallet("w3")
|
||||
wallet = node_v18.get_wallet_rpc("w3")
|
||||
info = wallet.getwalletinfo()
|
||||
assert info['private_keys_enabled']
|
||||
assert info['keypoolsize'] == 0
|
||||
|
||||
# Open the wallets in v0.17
|
||||
node_v17.loadwallet("w1_v18")
|
||||
wallet = node_v17.get_wallet_rpc("w1_v18")
|
||||
info = wallet.getwalletinfo()
|
||||
assert info['private_keys_enabled']
|
||||
assert info['keypoolsize'] > 0
|
||||
|
||||
node_v17.loadwallet("w1")
|
||||
wallet = node_v17.get_wallet_rpc("w1")
|
||||
info = wallet.getwalletinfo()
|
||||
assert info['private_keys_enabled']
|
||||
assert info['keypoolsize'] > 0
|
||||
|
||||
node_v17.loadwallet("w2_v18")
|
||||
wallet = node_v17.get_wallet_rpc("w2_v18")
|
||||
info = wallet.getwalletinfo()
|
||||
assert info['private_keys_enabled'] == False
|
||||
assert info['keypoolsize'] == 0
|
||||
|
||||
node_v17.loadwallet("w2")
|
||||
wallet = node_v17.get_wallet_rpc("w2")
|
||||
info = wallet.getwalletinfo()
|
||||
assert info['private_keys_enabled'] == False
|
||||
assert info['keypoolsize'] == 0
|
||||
|
||||
# RPC loadwallet failure causes bitcoind to exit, in addition to the RPC
|
||||
# call failure, so the following test won't work:
|
||||
# assert_raises_rpc_error(-4, "Wallet loading failed.", node_v17.loadwallet, 'w3_v18')
|
||||
|
||||
# Instead, we stop node and try to launch it with the wallet:
|
||||
self.stop_node(self.num_nodes - 1)
|
||||
node_v17.assert_start_raises_init_error(["-wallet=w3_v18"], "Error: Error loading w3_v18: Wallet requires newer version of Bitcoin Core")
|
||||
node_v17.assert_start_raises_init_error(["-wallet=w3"], "Error: Error loading w3: Wallet requires newer version of Bitcoin Core")
|
||||
self.start_node(self.num_nodes - 1)
|
||||
|
||||
self.log.info("Test wallet upgrade path...")
|
||||
# u1: regular wallet, created with v0.17
|
||||
node_v17.createwallet(wallet_name="u1_v17")
|
||||
wallet = node_v17.get_wallet_rpc("u1_v17")
|
||||
address = wallet.getnewaddress("bech32")
|
||||
info = wallet.getaddressinfo(address)
|
||||
hdkeypath = info["hdkeypath"]
|
||||
pubkey = info["pubkey"]
|
||||
|
||||
# Copy the wallet to the last Bitcoin Core version and open it:
|
||||
node_v17.unloadwallet("u1_v17")
|
||||
shutil.copytree(
|
||||
os.path.join(node_v17_wallets_dir, "u1_v17"),
|
||||
os.path.join(node_master_wallets_dir, "u1_v17")
|
||||
)
|
||||
node_master.loadwallet("u1_v17")
|
||||
wallet = node_master.get_wallet_rpc("u1_v17")
|
||||
info = wallet.getaddressinfo(address)
|
||||
descriptor = "wpkh([" + info["hdmasterfingerprint"] + hdkeypath[1:] + "]" + pubkey + ")"
|
||||
assert_equal(info["desc"], descsum_create(descriptor))
|
||||
|
||||
if __name__ == '__main__':
|
||||
BackwardsCompatibilityTest().main()
|
||||
|
|
@ -369,7 +369,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
|
|||
|
||||
# Public helper methods. These can be accessed by the subclass test scripts.
|
||||
|
||||
def add_nodes(self, num_nodes, extra_args=None, *, rpchost=None, chain=None, binary=None, chain_in_args=None):
|
||||
def add_nodes(self, num_nodes, extra_args=None, *, rpchost=None, chain=None, binary=None, binary_cli=None, versions=None, chain_in_args=None):
|
||||
"""Instantiate TestNode objects.
|
||||
|
||||
Should only be called once after the nodes have been specified in
|
||||
|
|
@ -380,15 +380,21 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
|
|||
extra_confs = [[]] * num_nodes
|
||||
if extra_args is None:
|
||||
extra_args = [[]] * num_nodes
|
||||
if versions is None:
|
||||
versions = [None] * num_nodes
|
||||
if binary is None:
|
||||
binary = [self.options.bitcoind] * num_nodes
|
||||
if binary_cli is None:
|
||||
binary_cli = [self.options.bitcoincli] * num_nodes
|
||||
if chain is None:
|
||||
chain = [self.chain] * num_nodes
|
||||
if chain_in_args is None:
|
||||
chain_in_args = [True] * num_nodes
|
||||
assert_equal(len(extra_confs), num_nodes)
|
||||
assert_equal(len(extra_args), num_nodes)
|
||||
assert_equal(len(versions), num_nodes)
|
||||
assert_equal(len(binary), num_nodes)
|
||||
assert_equal(len(binary_cli), num_nodes)
|
||||
assert_equal(len(chain), num_nodes)
|
||||
for i in range(num_nodes):
|
||||
numnode = len(self.nodes)
|
||||
|
|
@ -399,7 +405,8 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
|
|||
rpchost=rpchost,
|
||||
timewait=self.rpc_timeout,
|
||||
bitcoind=binary[i],
|
||||
bitcoin_cli=self.options.bitcoincli,
|
||||
bitcoin_cli=binary_cli[i],
|
||||
version=versions[i],
|
||||
coverage_dir=self.options.coveragedir,
|
||||
cwd=self.options.tmpdir,
|
||||
extra_conf=extra_confs[i],
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ class TestNode():
|
|||
To make things easier for the test writer, any unrecognised messages will
|
||||
be dispatched to the RPC connection."""
|
||||
|
||||
def __init__(self, i, datadir, chain, *, rpchost, timewait, bitcoind, bitcoin_cli, coverage_dir, cwd, extra_conf=None, extra_args=None, use_cli=False, start_perf=False, chain_in_args=True, use_valgrind=False):
|
||||
def __init__(self, i, datadir, *, chain, rpchost, timewait, bitcoind, bitcoin_cli, coverage_dir, cwd, extra_conf=None, extra_args=None, use_cli=False, start_perf=False, use_valgrind=False, version=None, chain_in_args=True):
|
||||
"""
|
||||
Kwargs:
|
||||
start_perf (bool): If True, begin profiling the node with `perf` as soon as
|
||||
|
|
@ -84,6 +84,7 @@ class TestNode():
|
|||
# For those callers that need more flexibility, they can just set the args property directly.
|
||||
# Note that common args are set in the config file (see initialize_datadir)
|
||||
self.extra_args = extra_args
|
||||
self.version = version
|
||||
# Configuration for logging is set as command-line args rather than in the bitcoin.conf file.
|
||||
# This means that starting a bitcoind using the temp dir to debug a failed test won't
|
||||
# spam debug.log.
|
||||
|
|
@ -91,7 +92,6 @@ class TestNode():
|
|||
self.binary,
|
||||
"-datadir=" + self.datadir,
|
||||
"-logtimemicros",
|
||||
"-logthreadnames",
|
||||
"-debug",
|
||||
"-debugexclude=libevent",
|
||||
"-debugexclude=leveldb",
|
||||
|
|
@ -110,6 +110,9 @@ class TestNode():
|
|||
"--gen-suppressions=all", "--exit-on-first-error=yes",
|
||||
"--error-exitcode=1", "--quiet"] + self.args
|
||||
|
||||
if self.version is None or self.version >= 190000:
|
||||
self.args.append("-logthreadnames")
|
||||
|
||||
self.cli = TestNodeCLI(bitcoin_cli, self.datadir, self.chain)
|
||||
self.use_cli = use_cli
|
||||
self.start_perf = start_perf
|
||||
|
|
@ -270,7 +273,11 @@ class TestNode():
|
|||
return
|
||||
self.log.debug("Stopping node")
|
||||
try:
|
||||
self.stop(wait=wait)
|
||||
# Do not use wait argument when testing older nodes, e.g. in feature_backwards_compatibility.py
|
||||
if self.version is None or self.version >= 180000:
|
||||
self.stop(wait=wait)
|
||||
else:
|
||||
self.stop()
|
||||
except http.client.CannotSendRequest:
|
||||
self.log.exception("Unable to stop node.")
|
||||
|
||||
|
|
|
|||
|
|
@ -181,6 +181,7 @@ BASE_SCRIPTS = [
|
|||
'feature_assumevalid.py',
|
||||
'example_test.py',
|
||||
'wallet_txn_doublespend.py',
|
||||
'feature_backwards_compatibility.py',
|
||||
'wallet_txn_clone.py --mineblock',
|
||||
# ELEMENTS: needs to be fixed
|
||||
#'feature_notifications.py',
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue