mirror of
https://github.com/dashpay/dash.git
synced 2024-12-26 12:32:48 +01:00
65226da849
68faa87881f5334b2528db4adc72ec19d94316a3 test: use f-strings in mining_*.py tests (fanquake) c2a5d560df2824df5731100c2584e8ad7a3d7bc2 test: use f-strings in interface_*.py tests (fanquake) 86d958262dff43002820d58ccb8958e2dbfb9d5b test: use f-strings in feature_proxy.py (fanquake) 31bdb33dcb8345df1bb94b28e811252a918d7dcb test: use f-strings in feature_segwit.py (fanquake) b166d54c3cbb0c028210cee977b3dcde5ac5474f test: use f-strings in feature_versionbits_warning.py (fanquake) cf6d66bf941d946600047d712c7cd15d7605322e test: use f-strings in feature_settings.py (fanquake) 6651d77f22862716f5bd7d0b31cfbd3937ab7b1d test: use f-strings in feature_pruning.py (fanquake) 961f5813ba65b6a601081912c4ece96c2679794d test: use f-strings in feature_notifications.py (fanquake) 1a546e6f6ca95772f0d7dbc2792477becbb8ea63 test: use f-strings in feature_minchainwork.py (fanquake) 6679eceacc915a8ea7cd7063f103ffc5eb9da884 test: use f-strings in feature_logging.py (fanquake) fb633933ab570e945d2a366f37eeff39f516c613 test: use f-strings in feature_loadblock.py (fanquake) e9ca8b254d4b9567831c0e113ce1c0a2b4795a95 test: use f-strings in feature_help.py (fanquake) ff7e3309995a8960ac371741b2b00c6da40f7490 test: use f-strings in feature_filelock.py (fanquake) d5a6adc5e478fa5c6e562377eea873dc38e66578 test: use f-strings in feature_fee_estimation.py (fanquake) a2de33cbdc79202bccddb4beadfde88266ac979f test: use f-strings in feature_dersig.py (fanquake) a2502cc63fd308be8af840962da9c53339433fa6 test: use f-strings in feature_dbcrash.py (fanquake) 3e2f84e7a96cb4b97b609ac853f78edd0ed43f82 test: use f-strings in feature_csv_activation.py (fanquake) e2f1fd8ee92fa421b6d293169044d6ddd5a9b8df test: use f-strings in feature_config_args.py (fanquake) 36d33d32b1b498b61f56d552f6e2c1d064f978c3 test: use f-strings in feature_cltv.py (fanquake) dca173cc044270b30782b1e3355e9dcb8c534295 test: use f-strings in feature_blocksdir.py (fanquake) 5453e8706278918ac51a725e81599cfa18c8cdbc test: use f-strings in feature_backwards_compatibility.py (fanquake) 6f3d5ad67ac8e7b50abae1a2949898d858e38106 test: use f-strings in feature_asmap.py (fanquake) Pull request description: Rather than using 3 different ways to build/format strings (sometimes all in the same test, i.e [`feature_config_args.py`](https://github.com/bitcoin/bitcoin/blob/master/test/functional/feature_config_args.py)), consolidate to using [f-strings (3.6+)](https://docs.python.org/3/reference/lexical_analysis.html#f-strings), which are generally more concise / readable, as well as more performant than existing methods. This deals with the `feature_*.py`, `interface_*.py` and `mining_*.py` tests. See also: [PEP 498](https://www.python.org/dev/peps/pep-0498/) ACKs for top commit: mjdietzx: reACK 68faa87881f5334b2528db4adc72ec19d94316a3 Zero-1729: crACK 68faa87881f5334b2528db4adc72ec19d94316a3 Tree-SHA512: d4e1a42e07d96d2c552387a46da1534223c4ce408703d7568ad2ef580797dd68d9695b8d19666b567af37f44de6e430e8be5db5d5404ba8fcecf9f5b026a6efb
403 lines
17 KiB
Python
Executable File
403 lines
17 KiB
Python
Executable File
#!/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. Requires previous releases binaries,
|
|
see test/README.md.
|
|
|
|
v0.15.0.0 is not required by this test, but it is used in wallet_upgradewallet.py.
|
|
Due to a hardfork in regtest, it can't be used to sync nodes.
|
|
|
|
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
|
|
|
|
from test_framework.util import (
|
|
assert_equal,
|
|
assert_raises_rpc_error,
|
|
)
|
|
|
|
|
|
class BackwardsCompatibilityTest(BitcoinTestFramework):
|
|
def set_test_params(self):
|
|
self.setup_clean_chain = True
|
|
self.num_nodes = 7
|
|
# Add new version after each release:
|
|
self.extra_args = [
|
|
[], # Pre-release: use to mine blocks
|
|
["-nowallet"], # Pre-release: use to receive coins, swap wallets, etc
|
|
["-nowallet"], # v20.0.1
|
|
["-nowallet"], # v19.3.0
|
|
["-nowallet"], # v18.2.2
|
|
["-nowallet"], # v0.17.0.3
|
|
["-nowallet"], # v0.16.1.1
|
|
]
|
|
self.wallet_names = [self.default_wallet_name]
|
|
|
|
def skip_test_if_missing_module(self):
|
|
self.skip_if_no_wallet()
|
|
self.skip_if_no_previous_releases()
|
|
|
|
def setup_nodes(self):
|
|
self.add_nodes(self.num_nodes, extra_args=self.extra_args, versions=[
|
|
None,
|
|
None,
|
|
19030000,
|
|
19030000,
|
|
18020200,
|
|
170003,
|
|
160101,
|
|
])
|
|
|
|
self.start_nodes()
|
|
self.import_deterministic_coinbase_privkeys()
|
|
|
|
def run_test(self):
|
|
self.generatetoaddress(self.nodes[0], 101, self.nodes[0].getnewaddress())
|
|
|
|
self.sync_blocks()
|
|
|
|
# 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 - 6]
|
|
node_v20 = self.nodes[self.num_nodes - 5]
|
|
node_v19 = self.nodes[self.num_nodes - 4]
|
|
node_v18 = self.nodes[self.num_nodes - 3]
|
|
node_v17 = self.nodes[self.num_nodes - 2]
|
|
node_v16 = 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, 1)
|
|
self.sync_mempools()
|
|
self.generate(self.nodes[0], 1)
|
|
self.sync_blocks()
|
|
|
|
# w1_v19: regular wallet, created with v0.19
|
|
node_v19.rpc.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
|
|
# Use addmultisigaddress (see #18075)
|
|
address_18075 = wallet.addmultisigaddress(1, ["0296b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52", "037211a824f55b505228e4c3d5194c1fcfaa15a456abdf37f9b9d97a4040afc073"], "")["address"]
|
|
assert wallet.getaddressinfo(address_18075)["solvable"]
|
|
|
|
# w1_v18: regular wallet, created with v0.18
|
|
node_v18.rpc.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
|
|
|
|
# w1_v20: regular wallet, created with v20.0
|
|
node_v20.rpc.createwallet(wallet_name="w1_v20")
|
|
wallet = node_v20.get_wallet_rpc("w1_v20")
|
|
info = wallet.getwalletinfo()
|
|
assert info['private_keys_enabled']
|
|
assert info['keypoolsize'] > 0
|
|
|
|
# w2_v19: wallet with private keys disabled, created with v0.19
|
|
node_v19.rpc.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.rpc.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.rpc.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.rpc.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_v20_wallets_dir = os.path.join(node_v20.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_v16_wallets_dir = os.path.join(node_v16.datadir, "regtest")
|
|
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.16
|
|
for wallet in os.listdir(node_master_wallets_dir):
|
|
shutil.copytree(
|
|
os.path.join(node_master_wallets_dir, wallet),
|
|
os.path.join(node_v16_wallets_dir, wallet)
|
|
)
|
|
|
|
# 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)
|
|
)
|
|
|
|
# Copy wallets to v0.20
|
|
for wallet in os.listdir(node_master_wallets_dir):
|
|
shutil.copytree(
|
|
os.path.join(node_master_wallets_dir, wallet),
|
|
os.path.join(node_v20_wallets_dir, wallet)
|
|
)
|
|
|
|
if not self.options.descriptors:
|
|
# Descriptor wallets break compatibility, only run this test for legacy wallet
|
|
# Open the wallets in v0.20
|
|
node_v20.loadwallet("w1")
|
|
wallet = node_v20.get_wallet_rpc("w1")
|
|
info = wallet.getwalletinfo()
|
|
assert info['private_keys_enabled']
|
|
assert info['keypoolsize'] > 0
|
|
txs = wallet.listtransactions()
|
|
assert_equal(len(txs), 1)
|
|
|
|
node_v20.loadwallet("w2")
|
|
wallet = node_v20.get_wallet_rpc("w2")
|
|
info = wallet.getwalletinfo()
|
|
assert info['private_keys_enabled'] == False
|
|
assert info['keypoolsize'] == 0
|
|
|
|
node_v20.loadwallet("w3")
|
|
wallet = node_v20.get_wallet_rpc("w3")
|
|
info = wallet.getwalletinfo()
|
|
assert info['private_keys_enabled']
|
|
assert info['keypoolsize'] == 0
|
|
|
|
# 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), 1)
|
|
|
|
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), 1)
|
|
|
|
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
|
|
|
|
node_v17.loadwallet("w1")
|
|
wallet = node_v17.get_wallet_rpc("w1")
|
|
info = wallet.getwalletinfo()
|
|
# doesn't have private_keys_enabled in v17
|
|
#assert info['private_keys_enabled']
|
|
assert info['keypoolsize'] > 0
|
|
|
|
node_v17.loadwallet("w2")
|
|
wallet = node_v17.get_wallet_rpc("w2")
|
|
info = wallet.getwalletinfo()
|
|
# doesn't have private_keys_enabled in v17
|
|
# TODO enable back when HD wallets are created by default
|
|
# assert info['private_keys_enabled'] == False
|
|
# assert info['keypoolsize'] == 0
|
|
else:
|
|
# Descriptor wallets appear to be corrupted wallets to old software
|
|
assert_raises_rpc_error(-4, "Wallet requires newer version of Dash Core", node_v19.loadwallet, "w1")
|
|
assert_raises_rpc_error(-4, "Wallet requires newer version of Dash Core", node_v19.loadwallet, "w2")
|
|
assert_raises_rpc_error(-4, "Wallet requires newer version of Dash Core", node_v19.loadwallet, "w3")
|
|
assert_raises_rpc_error(-18, "Data is not in recognized format", node_v18.loadwallet, "w1")
|
|
assert_raises_rpc_error(-18, "Data is not in recognized format", node_v18.loadwallet, "w2")
|
|
assert_raises_rpc_error(-18, "Data is not in recognized format", node_v18.loadwallet, "w3")
|
|
|
|
# Open the wallets in v0.17
|
|
node_v17.loadwallet("w1_v18")
|
|
wallet = node_v17.get_wallet_rpc("w1_v18")
|
|
info = wallet.getwalletinfo()
|
|
# doesn't have private_keys_enabled in v17
|
|
# 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()
|
|
# doesn't have private_keys_enabled in v17
|
|
# TODO enable back when HD wallets are created by default
|
|
#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(5)
|
|
# it expected to fail with error 'DBErrors::TOO_NEW' but Dash Core can open v18 by version 17
|
|
# can be implemented in future if there's any incompatible versions
|
|
#node_v17.assert_start_raises_init_error(["-wallet=w3_v18"], "Error: Error loading w3_v18: Wallet requires newer version of Dash Core")
|
|
#node_v17.assert_start_raises_init_error(["-wallet=w3"], "Error: Error loading w3: Wallet requires newer version of Dash Core")
|
|
self.start_node(5)
|
|
|
|
# Open most recent wallet in v0.16 (no loadwallet RPC)
|
|
self.restart_node(6, extra_args=["-wallet=w2"])
|
|
wallet = node_v16.get_wallet_rpc("w2")
|
|
info = wallet.getwalletinfo()
|
|
assert info['keypoolsize'] == 1
|
|
|
|
self.log.info("Test wallet upgrade path...")
|
|
# u1: regular wallet, created with v0.17
|
|
node_v17.rpc.createwallet(wallet_name="u1_v17")
|
|
wallet = node_v17.get_wallet_rpc("u1_v17")
|
|
address = wallet.getnewaddress()
|
|
v17_info = wallet.getaddressinfo(address)
|
|
# TODO enable back when HD wallets are created by default
|
|
#v17_hdkeypath = v17_info["hdkeypath"]
|
|
v17_pubkey = v17_info["pubkey"]
|
|
|
|
if self.is_bdb_compiled():
|
|
# Old wallets are BDB and will only work if BDB is compiled
|
|
# Copy the 0.16 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)
|
|
# TODO enable back when HD wallets are created by default
|
|
#descriptor = f"pkh([{info["hdmasterfingerprint"]}{hdkeypath[1:]}]{v17_pubkey})"
|
|
#assert_equal(info["desc"], descsum_create(descriptor))
|
|
assert_equal(info["pubkey"], v17_pubkey)
|
|
|
|
# Now copy that same wallet back to 0.17 to make sure no automatic upgrade breaks it
|
|
node_master.unloadwallet("u1_v17")
|
|
shutil.rmtree(os.path.join(node_v17_wallets_dir, "u1_v17"))
|
|
shutil.copytree(
|
|
os.path.join(node_master_wallets_dir, "u1_v17"),
|
|
os.path.join(node_v17_wallets_dir, "u1_v17")
|
|
)
|
|
node_v17.loadwallet("u1_v17")
|
|
wallet = node_v17.get_wallet_rpc("u1_v17")
|
|
info = wallet.getaddressinfo(address)
|
|
assert_equal(info, v17_info)
|
|
|
|
# Copy the 0.19 wallet to the last Bitcoin Core version and open it:
|
|
shutil.copytree(
|
|
os.path.join(node_v19_wallets_dir, "w1_v19"),
|
|
os.path.join(node_master_wallets_dir, "w1_v19")
|
|
)
|
|
node_master.loadwallet("w1_v19")
|
|
wallet = node_master.get_wallet_rpc("w1_v19")
|
|
assert wallet.getaddressinfo(address_18075)["solvable"]
|
|
|
|
# Now copy that same wallet back to 0.19 to make sure no automatic upgrade breaks it
|
|
node_master.unloadwallet("w1_v19")
|
|
shutil.rmtree(os.path.join(node_v19_wallets_dir, "w1_v19"))
|
|
shutil.copytree(
|
|
os.path.join(node_master_wallets_dir, "w1_v19"),
|
|
os.path.join(node_v19_wallets_dir, "w1_v19")
|
|
)
|
|
node_v19.loadwallet("w1_v19")
|
|
wallet = node_v19.get_wallet_rpc("w1_v19")
|
|
assert wallet.getaddressinfo(address_18075)["solvable"]
|
|
|
|
if __name__ == '__main__':
|
|
BackwardsCompatibilityTest().main()
|