aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rwxr-xr-xtest/functional/feature_cltv.py3
-rwxr-xr-xtest/functional/feature_csv_activation.py2
-rwxr-xr-xtest/functional/feature_presegwit_node_upgrade.py52
-rwxr-xr-xtest/functional/interface_bitcoin_cli.py141
-rwxr-xr-xtest/functional/mempool_accept_wtxid.py17
-rwxr-xr-xtest/functional/mempool_unbroadcast.py6
-rwxr-xr-xtest/functional/mining_basic.py21
-rwxr-xr-xtest/functional/p2p_addr_relay.py99
-rwxr-xr-xtest/functional/p2p_addrfetch.py62
-rwxr-xr-xtest/functional/p2p_addrv2_relay.py5
-rwxr-xr-xtest/functional/p2p_invalid_messages.py1
-rwxr-xr-xtest/functional/p2p_segwit.py80
-rwxr-xr-xtest/functional/rpc_blockchain.py3
-rwxr-xr-xtest/functional/rpc_rawtransaction.py9
-rwxr-xr-xtest/functional/rpc_signrawtransaction.py15
-rw-r--r--test/functional/test_framework/blocktools.py4
-rwxr-xr-xtest/functional/test_framework/test_node.py5
-rw-r--r--test/functional/test_framework/util.py11
-rwxr-xr-xtest/functional/test_runner.py2
-rwxr-xr-xtest/functional/wallet_dump.py9
-rwxr-xr-xtest/functional/wallet_upgradewallet.py10
-rwxr-xr-xtest/get_previous_releases.py6
-rwxr-xr-xtest/lint/lint-spelling.sh2
23 files changed, 422 insertions, 143 deletions
diff --git a/test/functional/feature_cltv.py b/test/functional/feature_cltv.py
index 10d2072dba..7c14f5d5a6 100755
--- a/test/functional/feature_cltv.py
+++ b/test/functional/feature_cltv.py
@@ -9,6 +9,7 @@ Test that the CHECKLOCKTIMEVERIFY soft-fork activates at (regtest) block height
"""
from test_framework.blocktools import (
+ CLTV_HEIGHT,
create_block,
create_coinbase,
)
@@ -31,8 +32,6 @@ from test_framework.wallet import (
MiniWalletMode,
)
-CLTV_HEIGHT = 1351
-
# Helper function to modify a transaction by
# 1) prepending a given script to the scriptSig of vin 0 and
diff --git a/test/functional/feature_csv_activation.py b/test/functional/feature_csv_activation.py
index 5081867319..1ac1a0563f 100755
--- a/test/functional/feature_csv_activation.py
+++ b/test/functional/feature_csv_activation.py
@@ -41,6 +41,7 @@ from itertools import product
import time
from test_framework.blocktools import (
+ CSV_ACTIVATION_HEIGHT,
create_block,
create_coinbase,
)
@@ -63,7 +64,6 @@ from test_framework.wallet import (
TESTING_TX_COUNT = 83 # Number of testing transactions: 1 BIP113 tx, 16 BIP68 txs, 66 BIP112 txs (see comments above)
COINBASE_BLOCK_COUNT = TESTING_TX_COUNT # Number of coinbase blocks we need to generate as inputs for our txs
BASE_RELATIVE_LOCKTIME = 10
-CSV_ACTIVATION_HEIGHT = 432
SEQ_DISABLE_FLAG = 1 << 31
SEQ_RANDOM_HIGH_BIT = 1 << 25
SEQ_TYPE_FLAG = 1 << 22
diff --git a/test/functional/feature_presegwit_node_upgrade.py b/test/functional/feature_presegwit_node_upgrade.py
new file mode 100755
index 0000000000..0428588da3
--- /dev/null
+++ b/test/functional/feature_presegwit_node_upgrade.py
@@ -0,0 +1,52 @@
+#!/usr/bin/env python3
+# Copyright (c) 2017-2020 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+"""Test a pre-segwit node upgrading to segwit consensus"""
+
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import (
+ assert_equal,
+ softfork_active,
+)
+
+class SegwitUpgradeTest(BitcoinTestFramework):
+ def set_test_params(self):
+ self.setup_clean_chain = True
+ self.num_nodes = 1
+ self.extra_args = [["-segwitheight=10"]]
+
+ def run_test(self):
+ """A pre-segwit node with insufficiently validated blocks needs to redownload blocks"""
+
+ self.log.info("Testing upgrade behaviour for pre-segwit node to segwit rules")
+ node = self.nodes[0]
+
+ # Node hasn't been used or connected yet
+ assert_equal(node.getblockcount(), 0)
+
+ assert not softfork_active(node, "segwit")
+
+ # Generate 8 blocks without witness data
+ node.generate(8)
+ assert_equal(node.getblockcount(), 8)
+
+ self.stop_node(0)
+ # Restarting the node (with segwit activation height set to 5) should result in a shutdown
+ # because the blockchain consists of 3 insufficiently validated blocks per segwit consensus rules.
+ node.assert_start_raises_init_error(
+ extra_args=["-segwitheight=5"],
+ expected_msg=": Witness data for blocks after height 5 requires validation. Please restart with -reindex..\nPlease restart with -reindex or -reindex-chainstate to recover.")
+
+ # As directed, the user restarts the node with -reindex
+ self.start_node(0, extra_args=["-reindex", "-segwitheight=5"])
+
+ # With the segwit consensus rules, the node is able to validate only up to block 4
+ assert_equal(node.getblockcount(), 4)
+
+ # The upgraded node should now have segwit activated
+ assert softfork_active(node, "segwit")
+
+
+if __name__ == '__main__':
+ SegwitUpgradeTest().main()
diff --git a/test/functional/interface_bitcoin_cli.py b/test/functional/interface_bitcoin_cli.py
index 22eec59600..dfa448a1a8 100755
--- a/test/functional/interface_bitcoin_cli.py
+++ b/test/functional/interface_bitcoin_cli.py
@@ -5,6 +5,7 @@
"""Test bitcoin-cli"""
from decimal import Decimal
+import re
from test_framework.blocktools import COINBASE_MATURITY
from test_framework.test_framework import BitcoinTestFramework
@@ -29,6 +30,41 @@ TOO_MANY_ARGS = 'error: too many arguments (maximum 2 for nblocks and maxtries)'
WALLET_NOT_LOADED = 'Requested wallet does not exist or is not loaded'
WALLET_NOT_SPECIFIED = 'Wallet file not specified'
+
+def cli_get_info_string_to_dict(cli_get_info_string):
+ """Helper method to convert human-readable -getinfo into a dictionary"""
+ cli_get_info = {}
+ lines = cli_get_info_string.splitlines()
+ line_idx = 0
+ ansi_escape = re.compile(r'(\x9B|\x1B\[)[0-?]*[ -\/]*[@-~]')
+ while line_idx < len(lines):
+ # Remove ansi colour code
+ line = ansi_escape.sub('', lines[line_idx])
+ if "Balances" in line:
+ # When "Balances" appears in a line, all of the following lines contain "balance: wallet" until an empty line
+ cli_get_info["Balances"] = {}
+ while line_idx < len(lines) and not (lines[line_idx + 1] == ''):
+ line_idx += 1
+ balance, wallet = lines[line_idx].strip().split(" ")
+ # Remove right justification padding
+ wallet = wallet.strip()
+ if wallet == '""':
+ # Set default wallet("") to empty string
+ wallet = ''
+ cli_get_info["Balances"][wallet] = balance.strip()
+ elif ": " in line:
+ key, value = line.split(": ")
+ if key == 'Wallet' and value == '""':
+ # Set default wallet("") to empty string
+ value = ''
+ if key == "Proxy" and value == "N/A":
+ # Set N/A to empty string to represent no proxy
+ value = ''
+ cli_get_info[key.strip()] = value.strip()
+ line_idx += 1
+ return cli_get_info
+
+
class TestBitcoinCli(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
@@ -67,37 +103,43 @@ class TestBitcoinCli(BitcoinTestFramework):
self.log.info("Test -getinfo with arguments fails")
assert_raises_process_error(1, "-getinfo takes no arguments", self.nodes[0].cli('-getinfo').help)
+ self.log.info("Test -getinfo with -color=never does not return ANSI escape codes")
+ assert "\u001b[0m" not in self.nodes[0].cli('-getinfo', '-color=never').send_cli()
+
+ self.log.info("Test -getinfo with -color=always returns ANSI escape codes")
+ assert "\u001b[0m" in self.nodes[0].cli('-getinfo', '-color=always').send_cli()
+
+ self.log.info("Test -getinfo with invalid value for -color option")
+ assert_raises_process_error(1, "Invalid value for -color option. Valid values: always, auto, never.", self.nodes[0].cli('-getinfo', '-color=foo').send_cli)
+
self.log.info("Test -getinfo returns expected network and blockchain info")
if self.is_wallet_compiled():
self.nodes[0].encryptwallet(password)
- cli_get_info = self.nodes[0].cli('-getinfo').send_cli()
+ cli_get_info_string = self.nodes[0].cli('-getinfo').send_cli()
+ cli_get_info = cli_get_info_string_to_dict(cli_get_info_string)
+
network_info = self.nodes[0].getnetworkinfo()
blockchain_info = self.nodes[0].getblockchaininfo()
- assert_equal(cli_get_info['version'], network_info['version'])
- assert_equal(cli_get_info['blocks'], blockchain_info['blocks'])
- assert_equal(cli_get_info['headers'], blockchain_info['headers'])
- assert_equal(cli_get_info['timeoffset'], network_info['timeoffset'])
- assert_equal(
- cli_get_info['connections'],
- {
- 'in': network_info['connections_in'],
- 'out': network_info['connections_out'],
- 'total': network_info['connections']
- }
- )
- assert_equal(cli_get_info['proxy'], network_info['networks'][0]['proxy'])
- assert_equal(cli_get_info['difficulty'], blockchain_info['difficulty'])
- assert_equal(cli_get_info['chain'], blockchain_info['chain'])
+ assert_equal(int(cli_get_info['Version']), network_info['version'])
+ assert_equal(cli_get_info['Verification progress'], "%.4f%%" % (blockchain_info['verificationprogress'] * 100))
+ assert_equal(int(cli_get_info['Blocks']), blockchain_info['blocks'])
+ assert_equal(int(cli_get_info['Headers']), blockchain_info['headers'])
+ assert_equal(int(cli_get_info['Time offset (s)']), network_info['timeoffset'])
+ expected_network_info = f"in {network_info['connections_in']}, out {network_info['connections_out']}, total {network_info['connections']}"
+ assert_equal(cli_get_info["Network"], expected_network_info)
+ assert_equal(cli_get_info['Proxy'], network_info['networks'][0]['proxy'])
+ assert_equal(Decimal(cli_get_info['Difficulty']), blockchain_info['difficulty'])
+ assert_equal(cli_get_info['Chain'], blockchain_info['chain'])
if self.is_wallet_compiled():
self.log.info("Test -getinfo and bitcoin-cli getwalletinfo return expected wallet info")
- assert_equal(cli_get_info['balance'], BALANCE)
- assert 'balances' not in cli_get_info.keys()
+ assert_equal(Decimal(cli_get_info['Balance']), BALANCE)
+ assert 'Balances' not in cli_get_info_string
wallet_info = self.nodes[0].getwalletinfo()
- assert_equal(cli_get_info['keypoolsize'], wallet_info['keypoolsize'])
- assert_equal(cli_get_info['unlocked_until'], wallet_info['unlocked_until'])
- assert_equal(cli_get_info['paytxfee'], wallet_info['paytxfee'])
- assert_equal(cli_get_info['relayfee'], network_info['relayfee'])
+ assert_equal(int(cli_get_info['Keypool size']), wallet_info['keypoolsize'])
+ assert_equal(int(cli_get_info['Unlocked until']), wallet_info['unlocked_until'])
+ assert_equal(Decimal(cli_get_info['Transaction fee rate (-paytxfee) (BTC/kvB)']), wallet_info['paytxfee'])
+ assert_equal(Decimal(cli_get_info['Min tx relay fee rate (BTC/kvB)']), network_info['relayfee'])
assert_equal(self.nodes[0].cli.getwalletinfo(), wallet_info)
# Setup to test -getinfo, -generate, and -rpcwallet= with multiple wallets.
@@ -120,44 +162,57 @@ class TestBitcoinCli(BitcoinTestFramework):
self.log.info("Test -getinfo with multiple wallets and -rpcwallet returns specified wallet balance")
for i in range(len(wallets)):
- cli_get_info = self.nodes[0].cli('-getinfo', '-rpcwallet={}'.format(wallets[i])).send_cli()
- assert 'balances' not in cli_get_info.keys()
- assert_equal(cli_get_info['balance'], amounts[i])
+ cli_get_info_string = self.nodes[0].cli('-getinfo', '-rpcwallet={}'.format(wallets[i])).send_cli()
+ cli_get_info = cli_get_info_string_to_dict(cli_get_info_string)
+ assert 'Balances' not in cli_get_info_string
+ assert_equal(cli_get_info["Wallet"], wallets[i])
+ assert_equal(Decimal(cli_get_info['Balance']), amounts[i])
self.log.info("Test -getinfo with multiple wallets and -rpcwallet=non-existing-wallet returns no balances")
- cli_get_info_keys = self.nodes[0].cli('-getinfo', '-rpcwallet=does-not-exist').send_cli().keys()
- assert 'balance' not in cli_get_info_keys
- assert 'balances' not in cli_get_info_keys
+ cli_get_info_string = self.nodes[0].cli('-getinfo', '-rpcwallet=does-not-exist').send_cli()
+ assert 'Balance' not in cli_get_info_string
+ assert 'Balances' not in cli_get_info_string
self.log.info("Test -getinfo with multiple wallets returns all loaded wallet names and balances")
assert_equal(set(self.nodes[0].listwallets()), set(wallets))
- cli_get_info = self.nodes[0].cli('-getinfo').send_cli()
- assert 'balance' not in cli_get_info.keys()
- assert_equal(cli_get_info['balances'], {k: v for k, v in zip(wallets, amounts)})
+ cli_get_info_string = self.nodes[0].cli('-getinfo').send_cli()
+ cli_get_info = cli_get_info_string_to_dict(cli_get_info_string)
+ assert 'Balance' not in cli_get_info
+ for k, v in zip(wallets, amounts):
+ assert_equal(Decimal(cli_get_info['Balances'][k]), v)
# Unload the default wallet and re-verify.
self.nodes[0].unloadwallet(wallets[0])
assert wallets[0] not in self.nodes[0].listwallets()
- cli_get_info = self.nodes[0].cli('-getinfo').send_cli()
- assert 'balance' not in cli_get_info.keys()
- assert_equal(cli_get_info['balances'], {k: v for k, v in zip(wallets[1:], amounts[1:])})
+ cli_get_info_string = self.nodes[0].cli('-getinfo').send_cli()
+ cli_get_info = cli_get_info_string_to_dict(cli_get_info_string)
+ assert 'Balance' not in cli_get_info
+ assert 'Balances' in cli_get_info_string
+ for k, v in zip(wallets[1:], amounts[1:]):
+ assert_equal(Decimal(cli_get_info['Balances'][k]), v)
+ assert wallets[0] not in cli_get_info
self.log.info("Test -getinfo after unloading all wallets except a non-default one returns its balance")
self.nodes[0].unloadwallet(wallets[2])
assert_equal(self.nodes[0].listwallets(), [wallets[1]])
- cli_get_info = self.nodes[0].cli('-getinfo').send_cli()
- assert 'balances' not in cli_get_info.keys()
- assert_equal(cli_get_info['balance'], amounts[1])
+ cli_get_info_string = self.nodes[0].cli('-getinfo').send_cli()
+ cli_get_info = cli_get_info_string_to_dict(cli_get_info_string)
+ assert 'Balances' not in cli_get_info_string
+ assert_equal(cli_get_info['Wallet'], wallets[1])
+ assert_equal(Decimal(cli_get_info['Balance']), amounts[1])
self.log.info("Test -getinfo with -rpcwallet=remaining-non-default-wallet returns only its balance")
- cli_get_info = self.nodes[0].cli('-getinfo', rpcwallet2).send_cli()
- assert 'balances' not in cli_get_info.keys()
- assert_equal(cli_get_info['balance'], amounts[1])
+ cli_get_info_string = self.nodes[0].cli('-getinfo', rpcwallet2).send_cli()
+ cli_get_info = cli_get_info_string_to_dict(cli_get_info_string)
+ assert 'Balances' not in cli_get_info_string
+ assert_equal(cli_get_info['Wallet'], wallets[1])
+ assert_equal(Decimal(cli_get_info['Balance']), amounts[1])
self.log.info("Test -getinfo with -rpcwallet=unloaded wallet returns no balances")
- cli_get_info_keys = self.nodes[0].cli('-getinfo', rpcwallet3).send_cli().keys()
- assert 'balance' not in cli_get_info_keys
- assert 'balances' not in cli_get_info_keys
+ cli_get_info_string = self.nodes[0].cli('-getinfo', rpcwallet3).send_cli()
+ cli_get_info_keys = cli_get_info_string_to_dict(cli_get_info_string)
+ assert 'Balance' not in cli_get_info_keys
+ assert 'Balances' not in cli_get_info_string
# Test bitcoin-cli -generate.
n1 = 3
diff --git a/test/functional/mempool_accept_wtxid.py b/test/functional/mempool_accept_wtxid.py
index dd1f8997ad..63ecc8ee2a 100755
--- a/test/functional/mempool_accept_wtxid.py
+++ b/test/functional/mempool_accept_wtxid.py
@@ -16,6 +16,7 @@ from test_framework.messages import (
CTxOut,
sha256,
)
+from test_framework.p2p import P2PTxInvStore
from test_framework.script import (
CScript,
OP_0,
@@ -62,6 +63,8 @@ class MempoolWtxidTest(BitcoinTestFramework):
parent_txid = node.sendrawtransaction(hexstring=raw_parent, maxfeerate=0)
node.generate(1)
+ peer_wtxid_relay = node.add_p2p_connection(P2PTxInvStore())
+
# Create a new transaction with witness solving first branch
child_witness_script = CScript([OP_TRUE])
child_witness_program = sha256(child_witness_script)
@@ -87,10 +90,13 @@ class MempoolWtxidTest(BitcoinTestFramework):
assert_equal(child_one_txid, child_two_txid)
assert child_one_wtxid != child_two_wtxid
- self.log.info("Submit one child to the mempool")
+ self.log.info("Submit child_one to the mempool")
txid_submitted = node.sendrawtransaction(child_one.serialize().hex())
assert_equal(node.getrawmempool(True)[txid_submitted]['wtxid'], child_one_wtxid)
+ peer_wtxid_relay.wait_for_broadcast([child_one_wtxid])
+ assert_equal(node.getmempoolinfo()["unbroadcastcount"], 0)
+
# testmempoolaccept reports the "already in mempool" error
assert_equal(node.testmempoolaccept([child_one.serialize().hex()]), [{
"txid": child_one_txid,
@@ -108,9 +114,18 @@ class MempoolWtxidTest(BitcoinTestFramework):
# sendrawtransaction will not throw but quits early when the exact same transaction is already in mempool
node.sendrawtransaction(child_one.serialize().hex())
+
+ self.log.info("Connect another peer that hasn't seen child_one before")
+ peer_wtxid_relay_2 = node.add_p2p_connection(P2PTxInvStore())
+
+ self.log.info("Submit child_two to the mempool")
# sendrawtransaction will not throw but quits early when a transaction with the same non-witness data is already in mempool
node.sendrawtransaction(child_two.serialize().hex())
+ # The node should rebroadcast the transaction using the wtxid of the correct transaction
+ # (child_one, which is in its mempool).
+ peer_wtxid_relay_2.wait_for_broadcast([child_one_wtxid])
+ assert_equal(node.getmempoolinfo()["unbroadcastcount"], 0)
if __name__ == '__main__':
MempoolWtxidTest().main()
diff --git a/test/functional/mempool_unbroadcast.py b/test/functional/mempool_unbroadcast.py
index b475b65e68..7d9e6c306d 100755
--- a/test/functional/mempool_unbroadcast.py
+++ b/test/functional/mempool_unbroadcast.py
@@ -92,6 +92,12 @@ class MempoolUnbroadcastTest(BitcoinTestFramework):
self.disconnect_nodes(0, 1)
node.disconnect_p2ps()
+ self.log.info("Rebroadcast transaction and ensure it is not added to unbroadcast set when already in mempool")
+ rpc_tx_hsh = node.sendrawtransaction(txFS["hex"])
+ mempool = node.getrawmempool(True)
+ assert rpc_tx_hsh in mempool
+ assert not mempool[rpc_tx_hsh]['unbroadcast']
+
def test_txn_removal(self):
self.log.info("Test that transactions removed from mempool are removed from unbroadcast set")
node = self.nodes[0]
diff --git a/test/functional/mining_basic.py b/test/functional/mining_basic.py
index ba467c1517..01fc02f27e 100755
--- a/test/functional/mining_basic.py
+++ b/test/functional/mining_basic.py
@@ -13,6 +13,7 @@ from decimal import Decimal
from test_framework.blocktools import (
create_coinbase,
+ get_witness_script,
NORMAL_GBT_REQUEST_PARAMS,
TIME_GENESIS_BLOCK,
)
@@ -20,6 +21,7 @@ from test_framework.messages import (
CBlock,
CBlockHeader,
BLOCK_HEADER_SIZE,
+ ser_uint256,
)
from test_framework.p2p import P2PDataStore
from test_framework.test_framework import BitcoinTestFramework
@@ -49,6 +51,9 @@ class MiningTest(BitcoinTestFramework):
self.setup_clean_chain = True
self.supports_cli = False
+ def skip_test_if_missing_module(self):
+ self.skip_if_no_wallet()
+
def mine_chain(self):
self.log.info('Create some old blocks')
for t in range(TIME_GENESIS_BLOCK, TIME_GENESIS_BLOCK + 200 * 600, 600):
@@ -89,7 +94,21 @@ class MiningTest(BitcoinTestFramework):
assert_equal(mining_info['networkhashps'], Decimal('0.003333333333333334'))
assert_equal(mining_info['pooledtx'], 0)
- # Mine a block to leave initial block download
+ self.log.info("getblocktemplate: Test default witness commitment")
+ txid = int(node.sendtoaddress(node.getnewaddress(), 1), 16)
+ tmpl = node.getblocktemplate(NORMAL_GBT_REQUEST_PARAMS)
+
+ # Check that default_witness_commitment is present.
+ assert 'default_witness_commitment' in tmpl
+ witness_commitment = tmpl['default_witness_commitment']
+
+ # Check that default_witness_commitment is correct.
+ witness_root = CBlock.get_merkle_root([ser_uint256(0),
+ ser_uint256(txid)])
+ script = get_witness_script(witness_root, 0)
+ assert_equal(witness_commitment, script.hex())
+
+ # Mine a block to leave initial block download and clear the mempool
node.generatetoaddress(1, node.get_deterministic_priv_key().address)
tmpl = node.getblocktemplate(NORMAL_GBT_REQUEST_PARAMS)
self.log.info("getblocktemplate: Test capability advertised")
diff --git a/test/functional/p2p_addr_relay.py b/test/functional/p2p_addr_relay.py
index 1a414959b9..ff1d85a9be 100755
--- a/test/functional/p2p_addr_relay.py
+++ b/test/functional/p2p_addr_relay.py
@@ -13,17 +13,20 @@ from test_framework.messages import (
msg_addr,
msg_getaddr
)
-from test_framework.p2p import P2PInterface
-from test_framework.test_framework import BitcoinTestFramework
-from test_framework.util import (
- assert_equal,
+from test_framework.p2p import (
+ P2PInterface,
+ p2p_lock,
)
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import assert_equal
+import random
import time
class AddrReceiver(P2PInterface):
num_ipv4_received = 0
test_addr_contents = False
+ _tokens = 1
def __init__(self, test_addr_contents=False):
super().__init__()
@@ -40,6 +43,20 @@ class AddrReceiver(P2PInterface):
raise AssertionError("Invalid addr.port of {} (8333-8342 expected)".format(addr.port))
assert addr.ip.startswith('123.123.123.')
+ def on_getaddr(self, message):
+ # When the node sends us a getaddr, it increments the addr relay tokens for the connection by 1000
+ self._tokens += 1000
+
+ @property
+ def tokens(self):
+ with p2p_lock:
+ return self._tokens
+
+ def increment_tokens(self, n):
+ # When we move mocktime forward, the node increments the addr relay tokens for its peers
+ with p2p_lock:
+ self._tokens += n
+
def addr_received(self):
return self.num_ipv4_received != 0
@@ -53,12 +70,14 @@ class AddrTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 1
+ self.extra_args = [["-whitelist=addr@127.0.0.1"]]
def run_test(self):
self.oversized_addr_test()
self.relay_tests()
self.getaddr_tests()
self.blocksonly_mode_tests()
+ self.rate_limit_tests()
def setup_addr_msg(self, num):
addrs = []
@@ -75,6 +94,19 @@ class AddrTest(BitcoinTestFramework):
msg.addrs = addrs
return msg
+ def setup_rand_addr_msg(self, num):
+ addrs = []
+ for i in range(num):
+ addr = CAddress()
+ addr.time = self.mocktime + i
+ addr.nServices = NODE_NETWORK | NODE_WITNESS
+ addr.ip = f"{random.randrange(128,169)}.{random.randrange(1,255)}.{random.randrange(1,255)}.{random.randrange(1,255)}"
+ addr.port = 8333
+ addrs.append(addr)
+ msg = msg_addr()
+ msg.addrs = addrs
+ return msg
+
def send_addr_msg(self, source, msg, receivers):
source.send_and_ping(msg)
# pop m_next_addr_send timer
@@ -191,7 +223,7 @@ class AddrTest(BitcoinTestFramework):
def blocksonly_mode_tests(self):
self.log.info('Test addr relay in -blocksonly mode')
- self.restart_node(0, ["-blocksonly"])
+ self.restart_node(0, ["-blocksonly", "-whitelist=addr@127.0.0.1"])
self.mocktime = int(time.time())
self.log.info('Check that we send getaddr messages')
@@ -207,6 +239,63 @@ class AddrTest(BitcoinTestFramework):
self.nodes[0].disconnect_p2ps()
+ def send_addrs_and_test_rate_limiting(self, peer, no_relay, new_addrs, total_addrs):
+ """Send an addr message and check that the number of addresses processed and rate-limited is as expected"""
+
+ peer.send_and_ping(self.setup_rand_addr_msg(new_addrs))
+
+ peerinfo = self.nodes[0].getpeerinfo()[0]
+ addrs_processed = peerinfo['addr_processed']
+ addrs_rate_limited = peerinfo['addr_rate_limited']
+ self.log.debug(f"addrs_processed = {addrs_processed}, addrs_rate_limited = {addrs_rate_limited}")
+
+ if no_relay:
+ assert_equal(addrs_processed, 0)
+ assert_equal(addrs_rate_limited, 0)
+ else:
+ assert_equal(addrs_processed, min(total_addrs, peer.tokens))
+ assert_equal(addrs_rate_limited, max(0, total_addrs - peer.tokens))
+
+ def rate_limit_tests(self):
+
+ self.mocktime = int(time.time())
+ self.restart_node(0, [])
+ self.nodes[0].setmocktime(self.mocktime)
+
+ for contype, no_relay in [("outbound-full-relay", False), ("block-relay-only", True), ("inbound", False)]:
+ self.log.info(f'Test rate limiting of addr processing for {contype} peers')
+ if contype == "inbound":
+ peer = self.nodes[0].add_p2p_connection(AddrReceiver())
+ else:
+ peer = self.nodes[0].add_outbound_p2p_connection(AddrReceiver(), p2p_idx=0, connection_type=contype)
+
+ # Send 600 addresses. For all but the block-relay-only peer this should result in addresses being processed.
+ self.send_addrs_and_test_rate_limiting(peer, no_relay, 600, 600)
+
+ # Send 600 more addresses. For the outbound-full-relay peer (which we send a GETADDR, and thus will
+ # process up to 1001 incoming addresses), this means more addresses will be processed.
+ self.send_addrs_and_test_rate_limiting(peer, no_relay, 600, 1200)
+
+ # Send 10 more. As we reached the processing limit for all nodes, no more addresses should be procesesd.
+ self.send_addrs_and_test_rate_limiting(peer, no_relay, 10, 1210)
+
+ # Advance the time by 100 seconds, permitting the processing of 10 more addresses.
+ # Send 200 and verify that 10 are processed.
+ self.mocktime += 100
+ self.nodes[0].setmocktime(self.mocktime)
+ peer.increment_tokens(10)
+
+ self.send_addrs_and_test_rate_limiting(peer, no_relay, 200, 1410)
+
+ # Advance the time by 1000 seconds, permitting the processing of 100 more addresses.
+ # Send 200 and verify that 100 are processed.
+ self.mocktime += 1000
+ self.nodes[0].setmocktime(self.mocktime)
+ peer.increment_tokens(100)
+
+ self.send_addrs_and_test_rate_limiting(peer, no_relay, 200, 1610)
+
+ self.nodes[0].disconnect_p2ps()
if __name__ == '__main__':
AddrTest().main()
diff --git a/test/functional/p2p_addrfetch.py b/test/functional/p2p_addrfetch.py
new file mode 100755
index 0000000000..66ee1544a9
--- /dev/null
+++ b/test/functional/p2p_addrfetch.py
@@ -0,0 +1,62 @@
+#!/usr/bin/env python3
+# Copyright (c) 2021 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+"""
+Test p2p addr-fetch connections
+"""
+
+import time
+
+from test_framework.messages import msg_addr, CAddress, NODE_NETWORK, NODE_WITNESS
+from test_framework.p2p import P2PInterface, p2p_lock
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import assert_equal
+
+ADDR = CAddress()
+ADDR.time = int(time.time())
+ADDR.nServices = NODE_NETWORK | NODE_WITNESS
+ADDR.ip = "192.0.0.8"
+ADDR.port = 18444
+
+
+class P2PAddrFetch(BitcoinTestFramework):
+
+ def set_test_params(self):
+ self.setup_clean_chain = True
+ self.num_nodes = 1
+
+ def run_test(self):
+ node = self.nodes[0]
+ self.log.info("Connect to an addr-fetch peer")
+ peer = node.add_outbound_p2p_connection(P2PInterface(), p2p_idx=0, connection_type="addr-fetch")
+ info = node.getpeerinfo()
+ assert_equal(len(info), 1)
+ assert_equal(info[0]['connection_type'], 'addr-fetch')
+
+ self.log.info("Check that we send getaddr but don't try to sync headers with the addr-fetch peer")
+ peer.sync_send_with_ping()
+ with p2p_lock:
+ assert peer.message_count['getaddr'] == 1
+ assert peer.message_count['getheaders'] == 0
+
+ self.log.info("Check that answering the getaddr with a single address does not lead to disconnect")
+ # This prevents disconnecting on self-announcements
+ msg = msg_addr()
+ msg.addrs = [ADDR]
+ peer.send_and_ping(msg)
+ assert_equal(len(node.getpeerinfo()), 1)
+
+ self.log.info("Check that answering with larger addr messages leads to disconnect")
+ msg.addrs = [ADDR] * 2
+ peer.send_message(msg)
+ peer.wait_for_disconnect(timeout=5)
+
+ self.log.info("Check timeout for addr-fetch peer that does not send addrs")
+ peer = node.add_outbound_p2p_connection(P2PInterface(), p2p_idx=1, connection_type="addr-fetch")
+ node.setmocktime(int(time.time()) + 301) # Timeout: 5 minutes
+ peer.wait_for_disconnect(timeout=5)
+
+
+if __name__ == '__main__':
+ P2PAddrFetch().main()
diff --git a/test/functional/p2p_addrv2_relay.py b/test/functional/p2p_addrv2_relay.py
index c006a6c24f..32c1d42b1c 100755
--- a/test/functional/p2p_addrv2_relay.py
+++ b/test/functional/p2p_addrv2_relay.py
@@ -42,7 +42,9 @@ class AddrReceiver(P2PInterface):
super().__init__(support_addrv2 = True)
def on_addrv2(self, message):
- if ADDRS == message.addrs:
+ expected_set = set((addr.ip, addr.port) for addr in ADDRS)
+ received_set = set((addr.ip, addr.port) for addr in message.addrs)
+ if expected_set == received_set:
self.addrv2_received_and_checked = True
def wait_for_addrv2(self):
@@ -53,6 +55,7 @@ class AddrTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
self.num_nodes = 1
+ self.extra_args = [["-whitelist=addr@127.0.0.1"]]
def run_test(self):
self.log.info('Create connection that sends addrv2 messages')
diff --git a/test/functional/p2p_invalid_messages.py b/test/functional/p2p_invalid_messages.py
index 788a81d4af..9c34506320 100755
--- a/test/functional/p2p_invalid_messages.py
+++ b/test/functional/p2p_invalid_messages.py
@@ -58,6 +58,7 @@ class InvalidMessagesTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 1
self.setup_clean_chain = True
+ self.extra_args = [["-whitelist=addr@127.0.0.1"]]
def run_test(self):
self.test_buffer()
diff --git a/test/functional/p2p_segwit.py b/test/functional/p2p_segwit.py
index ead9d852fe..db96e6bdcf 100755
--- a/test/functional/p2p_segwit.py
+++ b/test/functional/p2p_segwit.py
@@ -9,11 +9,10 @@ import random
import struct
import time
-from test_framework.blocktools import create_block, create_coinbase, add_witness_commitment, get_witness_script, WITNESS_COMMITMENT_HEADER
+from test_framework.blocktools import create_block, create_coinbase, add_witness_commitment, WITNESS_COMMITMENT_HEADER
from test_framework.key import ECKey
from test_framework.messages import (
BIP125_SEQUENCE_NUMBER,
- CBlock,
CBlockHeader,
CInv,
COutPoint,
@@ -206,24 +205,17 @@ class TestP2PConn(P2PInterface):
class SegWitTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
- self.num_nodes = 3
+ self.num_nodes = 2
# This test tests SegWit both pre and post-activation, so use the normal BIP9 activation.
self.extra_args = [
["-acceptnonstdtxn=1", "-segwitheight={}".format(SEGWIT_HEIGHT), "-whitelist=noban@127.0.0.1"],
["-acceptnonstdtxn=0", "-segwitheight={}".format(SEGWIT_HEIGHT)],
- ["-acceptnonstdtxn=1", "-segwitheight=-1"],
]
self.supports_cli = False
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
- def setup_network(self):
- self.setup_nodes()
- self.connect_nodes(0, 1)
- self.connect_nodes(0, 2)
- self.sync_all()
-
# Helper functions
def build_next_block(self, version=4):
@@ -264,7 +256,6 @@ class SegWitTest(BitcoinTestFramework):
self.test_non_witness_transaction()
self.test_v0_outputs_arent_spendable()
self.test_block_relay()
- self.test_getblocktemplate_before_lockin()
self.test_unnecessary_witness_before_segwit_activation()
self.test_witness_tx_relay_before_segwit_activation()
self.test_standardness_v0()
@@ -292,7 +283,6 @@ class SegWitTest(BitcoinTestFramework):
self.test_signature_version_1()
self.test_non_standard_witness_blinding()
self.test_non_standard_witness()
- self.test_upgrade_after_activation()
self.test_witness_sigops()
self.test_superfluous_witness()
self.test_wtxid_relay()
@@ -482,11 +472,6 @@ class SegWitTest(BitcoinTestFramework):
witness, and so can't be spent before segwit activation (the point at which
blocks are permitted to contain witnesses)."""
- # node2 doesn't need to be connected for this test.
- # (If it's connected, node0 may propagate an invalid block to it over
- # compact blocks and the nodes would have inconsistent tips.)
- self.disconnect_nodes(0, 2)
-
# Create two outputs, a p2wsh and p2sh-p2wsh
witness_program = CScript([OP_TRUE])
script_pubkey = script_to_p2wsh_script(witness_program)
@@ -544,38 +529,10 @@ class SegWitTest(BitcoinTestFramework):
# TODO: support multiple acceptable reject reasons.
test_witness_block(self.nodes[0], self.test_node, block, accepted=False, with_witness=False)
- self.connect_nodes(0, 2)
-
self.utxo.pop(0)
self.utxo.append(UTXO(txid, 2, value))
@subtest # type: ignore
- def test_getblocktemplate_before_lockin(self):
- txid = int(self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1), 16)
-
- for node in [self.nodes[0], self.nodes[2]]:
- gbt_results = node.getblocktemplate({"rules": ["segwit"]})
- if node == self.nodes[2]:
- # If this is a non-segwit node, we should not get a witness
- # commitment.
- assert 'default_witness_commitment' not in gbt_results
- else:
- # For segwit-aware nodes, check the witness
- # commitment is correct.
- assert 'default_witness_commitment' in gbt_results
- witness_commitment = gbt_results['default_witness_commitment']
-
- # Check that default_witness_commitment is present.
- witness_root = CBlock.get_merkle_root([ser_uint256(0),
- ser_uint256(txid)])
- script = get_witness_script(witness_root, 0)
- assert_equal(witness_commitment, script.hex())
-
- # Clear out the mempool
- self.nodes[0].generate(1)
- self.sync_blocks()
-
- @subtest # type: ignore
def test_witness_tx_relay_before_segwit_activation(self):
# Generate a transaction that doesn't require a witness, but send it
@@ -1928,39 +1885,6 @@ class SegWitTest(BitcoinTestFramework):
self.utxo.pop(0)
@subtest # type: ignore
- def test_upgrade_after_activation(self):
- """Test the behavior of starting up a segwit-aware node after the softfork has activated."""
-
- # All nodes are caught up and node 2 is a pre-segwit node that will soon upgrade.
- for n in range(2):
- assert_equal(self.nodes[n].getblockcount(), self.nodes[2].getblockcount())
- assert softfork_active(self.nodes[n], "segwit")
- assert SEGWIT_HEIGHT < self.nodes[2].getblockcount()
- assert 'segwit' not in self.nodes[2].getblockchaininfo()['softforks']
-
- # Restarting node 2 should result in a shutdown because the blockchain consists of
- # insufficiently validated blocks per segwit consensus rules.
- self.stop_node(2)
- self.nodes[2].assert_start_raises_init_error(
- extra_args=[f"-segwitheight={SEGWIT_HEIGHT}"],
- expected_msg=f": Witness data for blocks after height {SEGWIT_HEIGHT} requires validation. Please restart with -reindex..\nPlease restart with -reindex or -reindex-chainstate to recover.",
- )
-
- # As directed, the user restarts the node with -reindex
- self.start_node(2, extra_args=["-reindex", f"-segwitheight={SEGWIT_HEIGHT}"])
-
- # With the segwit consensus rules, the node is able to validate only up to SEGWIT_HEIGHT - 1
- assert_equal(self.nodes[2].getblockcount(), SEGWIT_HEIGHT - 1)
- self.connect_nodes(0, 2)
-
- # We reconnect more than 100 blocks, give it plenty of time
- # sync_blocks() also verifies the best block hash is the same for all nodes
- self.sync_blocks(timeout=240)
-
- # The upgraded node should now have segwit activated
- assert softfork_active(self.nodes[2], "segwit")
-
- @subtest # type: ignore
def test_witness_sigops(self):
"""Test sigop counting is correct inside witnesses."""
diff --git a/test/functional/rpc_blockchain.py b/test/functional/rpc_blockchain.py
index 90715cae26..f7290ff229 100755
--- a/test/functional/rpc_blockchain.py
+++ b/test/functional/rpc_blockchain.py
@@ -93,11 +93,14 @@ class BlockchainTest(BitcoinTestFramework):
'pruned',
'size_on_disk',
'softforks',
+ 'time',
'verificationprogress',
'warnings',
]
res = self.nodes[0].getblockchaininfo()
+ assert isinstance(res['time'], int)
+
# result should have these additional pruning keys if manual pruning is enabled
assert_equal(sorted(res.keys()), sorted(['pruneheight', 'automatic_pruning'] + keys))
diff --git a/test/functional/rpc_rawtransaction.py b/test/functional/rpc_rawtransaction.py
index 3ff74dc5a4..9d4a5525d1 100755
--- a/test/functional/rpc_rawtransaction.py
+++ b/test/functional/rpc_rawtransaction.py
@@ -515,6 +515,15 @@ class RawTransactionsTest(BitcoinTestFramework):
assert_equal(testres['allowed'], True)
self.nodes[2].sendrawtransaction(hexstring=rawTxSigned['hex'], maxfeerate='0.20000000')
+ self.log.info('sendrawtransaction/testmempoolaccept with tx that is already in the chain')
+ self.nodes[2].generate(1)
+ self.sync_blocks()
+ for node in self.nodes:
+ testres = node.testmempoolaccept([rawTxSigned['hex']])[0]
+ assert_equal(testres['allowed'], False)
+ assert_equal(testres['reject-reason'], 'txn-already-known')
+ assert_raises_rpc_error(-27, 'Transaction already in block chain', node.sendrawtransaction, rawTxSigned['hex'])
+
if __name__ == '__main__':
RawTransactionsTest().main()
diff --git a/test/functional/rpc_signrawtransaction.py b/test/functional/rpc_signrawtransaction.py
index f3627d1e37..571029155e 100755
--- a/test/functional/rpc_signrawtransaction.py
+++ b/test/functional/rpc_signrawtransaction.py
@@ -4,7 +4,11 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test transaction signing using the signrawtransaction* RPCs."""
-from test_framework.blocktools import COINBASE_MATURITY
+from test_framework.blocktools import (
+ CLTV_HEIGHT,
+ COINBASE_MATURITY,
+ CSV_ACTIVATION_HEIGHT,
+)
from test_framework.address import (
script_to_p2sh,
script_to_p2wsh,
@@ -15,6 +19,7 @@ from test_framework.util import (
assert_equal,
assert_raises_rpc_error,
find_vout_for_address,
+ generate_to_height,
hex_str_to_bytes,
)
from test_framework.messages import (
@@ -270,7 +275,8 @@ class SignRawTransactionsTest(BitcoinTestFramework):
getcontext().prec = 8
# Make sure CSV is active
- self.nodes[0].generate(500)
+ generate_to_height(self.nodes[0], CSV_ACTIVATION_HEIGHT)
+ assert self.nodes[0].getblockchaininfo()['softforks']['csv']['active']
# Create a P2WSH script with CSV
script = CScript([1, OP_CHECKSEQUENCEVERIFY, OP_DROP])
@@ -304,8 +310,9 @@ class SignRawTransactionsTest(BitcoinTestFramework):
self.nodes[0].walletpassphrase("password", 9999)
getcontext().prec = 8
- # Make sure CSV is active
- self.nodes[0].generate(1500)
+ # Make sure CLTV is active
+ generate_to_height(self.nodes[0], CLTV_HEIGHT)
+ assert self.nodes[0].getblockchaininfo()['softforks']['bip65']['active']
# Create a P2WSH script with CLTV
script = CScript([1000, OP_CHECKLOCKTIMEVERIFY, OP_DROP])
diff --git a/test/functional/test_framework/blocktools.py b/test/functional/test_framework/blocktools.py
index 833a215993..2ab720aafb 100644
--- a/test/functional/test_framework/blocktools.py
+++ b/test/functional/test_framework/blocktools.py
@@ -55,6 +55,10 @@ TIME_GENESIS_BLOCK = 1296688602
# Coinbase transaction outputs can only be spent after this number of new blocks (network rule)
COINBASE_MATURITY = 100
+# Soft-fork activation heights
+CLTV_HEIGHT = 1351
+CSV_ACTIVATION_HEIGHT = 432
+
# From BIP141
WITNESS_COMMITMENT_HEADER = b"\xaa\x21\xa9\xed"
diff --git a/test/functional/test_framework/test_node.py b/test/functional/test_framework/test_node.py
index ba52abc7dd..afa904c8d7 100755
--- a/test/functional/test_framework/test_node.py
+++ b/test/functional/test_framework/test_node.py
@@ -557,9 +557,8 @@ class TestNode():
return p2p_conn
def add_outbound_p2p_connection(self, p2p_conn, *, p2p_idx, connection_type="outbound-full-relay", **kwargs):
- """Add an outbound p2p connection from node. Either
- full-relay("outbound-full-relay") or
- block-relay-only("block-relay-only") connection.
+ """Add an outbound p2p connection from node. Must be an
+ "outbound-full-relay", "block-relay-only" or "addr-fetch" connection.
This method adds the p2p connection to the self.p2ps list and returns
the connection to the caller.
diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py
index 35dbfbba8d..fcaf3b2c29 100644
--- a/test/functional/test_framework/util.py
+++ b/test/functional/test_framework/util.py
@@ -559,6 +559,17 @@ def mine_large_block(node, utxos=None):
node.generate(1)
+def generate_to_height(node, target_height):
+ """Generates blocks until a given target block height has been reached.
+ To prevent timeouts, only up to 200 blocks are generated per RPC call.
+ Can be used to activate certain soft-forks (e.g. CSV, CLTV)."""
+ current_height = node.getblockcount()
+ while current_height < target_height:
+ nblocks = min(200, target_height - current_height)
+ current_height += len(node.generate(nblocks))
+ assert_equal(node.getblockcount(), target_height)
+
+
def find_vout_for_address(node, txid, addr):
"""
Locate the vout index of the given transaction sending to the
diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py
index cbd773b704..0a73891f2a 100755
--- a/test/functional/test_runner.py
+++ b/test/functional/test_runner.py
@@ -186,6 +186,7 @@ BASE_SCRIPTS = [
'p2p_addr_relay.py',
'p2p_getaddr_caching.py',
'p2p_getdata.py',
+ 'p2p_addrfetch.py',
'rpc_net.py',
'wallet_keypool.py --legacy-wallet',
'wallet_keypool.py --descriptors',
@@ -296,6 +297,7 @@ BASE_SCRIPTS = [
'wallet_startup.py',
'p2p_i2p_ports.py',
'feature_config_args.py',
+ 'feature_presegwit_node_upgrade.py',
'feature_settings.py',
'rpc_getdescriptorinfo.py',
'rpc_addresses_deprecation.py',
diff --git a/test/functional/wallet_dump.py b/test/functional/wallet_dump.py
index eb54da99f5..91d6121679 100755
--- a/test/functional/wallet_dump.py
+++ b/test/functional/wallet_dump.py
@@ -209,6 +209,15 @@ class WalletDumpTest(BitcoinTestFramework):
with self.nodes[0].assert_debug_log(['Flushing wallet.dat'], timeout=20):
self.nodes[0].getnewaddress()
+ # Make sure that dumpwallet doesn't have a lock order issue when there is an unconfirmed tx and it is reloaded
+ # See https://github.com/bitcoin/bitcoin/issues/22489
+ self.nodes[0].createwallet("w3")
+ w3 = self.nodes[0].get_wallet_rpc("w3")
+ w3.importprivkey(privkey=self.nodes[0].get_deterministic_priv_key().key, label="coinbase_import")
+ w3.sendtoaddress(w3.getnewaddress(), 10)
+ w3.unloadwallet()
+ self.nodes[0].loadwallet("w3")
+ w3.dumpwallet(os.path.join(self.nodes[0].datadir, "w3.dump"))
if __name__ == '__main__':
WalletDumpTest().main()
diff --git a/test/functional/wallet_upgradewallet.py b/test/functional/wallet_upgradewallet.py
index ad11f4b244..4d34670ea9 100755
--- a/test/functional/wallet_upgradewallet.py
+++ b/test/functional/wallet_upgradewallet.py
@@ -94,10 +94,11 @@ class UpgradeWalletTest(BitcoinTestFramework):
def test_upgradewallet(self, wallet, previous_version, requested_version=None, expected_version=None):
unchanged = expected_version == previous_version
new_version = previous_version if unchanged else expected_version if expected_version else requested_version
- assert_equal(wallet.getwalletinfo()["walletversion"], previous_version)
+ old_wallet_info = wallet.getwalletinfo()
+ assert_equal(old_wallet_info["walletversion"], previous_version)
assert_equal(wallet.upgradewallet(requested_version),
{
- "wallet_name": "",
+ "wallet_name": old_wallet_info["walletname"],
"previous_version": previous_version,
"current_version": new_version,
"result": "Already at latest version. Wallet version unchanged." if unchanged else "Wallet upgraded successfully from version {} to version {}.".format(previous_version, new_version),
@@ -352,6 +353,11 @@ class UpgradeWalletTest(BitcoinTestFramework):
v16_3_kvs = dump_bdb_kv(v16_3_wallet)
assert b'\x0adefaultkey' not in v16_3_kvs
+ if self.is_sqlite_compiled():
+ self.log.info("Checking that descriptor wallets do nothing, successfully")
+ self.nodes[0].createwallet(wallet_name="desc_upgrade", descriptors=True)
+ desc_wallet = self.nodes[0].get_wallet_rpc("desc_upgrade")
+ self.test_upgradewallet(desc_wallet, previous_version=169900, expected_version=169900)
if __name__ == '__main__':
UpgradeWalletTest().main()
diff --git a/test/get_previous_releases.py b/test/get_previous_releases.py
index 01e4ef47a7..e92bb402b5 100755
--- a/test/get_previous_releases.py
+++ b/test/get_previous_releases.py
@@ -112,7 +112,11 @@ def download_binary(tag, args) -> int:
tarballHash = hasher.hexdigest()
if tarballHash not in SHA256_SUMS or SHA256_SUMS[tarballHash] != tarball:
- print("Checksum did not match")
+ if tarball in SHA256_SUMS.values():
+ print("Checksum did not match")
+ return 1
+
+ print("Checksum for given version doesn't exist")
return 1
print("Checksum matched")
diff --git a/test/lint/lint-spelling.sh b/test/lint/lint-spelling.sh
index 238fa63c45..111091b7f8 100755
--- a/test/lint/lint-spelling.sh
+++ b/test/lint/lint-spelling.sh
@@ -15,6 +15,6 @@ if ! command -v codespell > /dev/null; then
fi
IGNORE_WORDS_FILE=test/lint/lint-spelling.ignore-words.txt
-if ! codespell --check-filenames --disable-colors --quiet-level=7 --ignore-words=${IGNORE_WORDS_FILE} $(git ls-files -- ":(exclude)build-aux/m4/" ":(exclude)contrib/seeds/*.txt" ":(exclude)depends/" ":(exclude)doc/release-notes/" ":(exclude)src/leveldb/" ":(exclude)src/crc32c/" ":(exclude)src/qt/locale/" ":(exclude)src/qt/*.qrc" ":(exclude)src/secp256k1/" ":(exclude)src/univalue/" ":(exclude)contrib/gitian-keys/keys.txt" ":(exclude)contrib/guix/patches"); then
+if ! codespell --check-filenames --disable-colors --quiet-level=7 --ignore-words=${IGNORE_WORDS_FILE} $(git ls-files -- ":(exclude)build-aux/m4/" ":(exclude)contrib/seeds/*.txt" ":(exclude)depends/" ":(exclude)doc/release-notes/" ":(exclude)src/leveldb/" ":(exclude)src/crc32c/" ":(exclude)src/qt/locale/" ":(exclude)src/qt/*.qrc" ":(exclude)src/secp256k1/" ":(exclude)src/univalue/" ":(exclude)contrib/builder-keys/keys.txt" ":(exclude)contrib/guix/patches"); then
echo "^ Warning: codespell identified likely spelling errors. Any false positives? Add them to the list of ignored words in ${IGNORE_WORDS_FILE}"
fi