aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rwxr-xr-xtest/functional/feature_asmap.py14
-rwxr-xr-xtest/functional/feature_backwards_compatibility.py4
-rwxr-xr-xtest/functional/feature_blocksdir.py4
-rwxr-xr-xtest/functional/feature_cltv.py5
-rwxr-xr-xtest/functional/feature_config_args.py26
-rwxr-xr-xtest/functional/feature_csv_activation.py2
-rwxr-xr-xtest/functional/feature_dbcrash.py32
-rwxr-xr-xtest/functional/feature_dersig.py4
-rwxr-xr-xtest/functional/feature_fee_estimation.py11
-rwxr-xr-xtest/functional/feature_filelock.py8
-rwxr-xr-xtest/functional/feature_help.py6
-rwxr-xr-xtest/functional/feature_loadblock.py24
-rwxr-xr-xtest/functional/feature_logging.py12
-rwxr-xr-xtest/functional/feature_minchainwork.py10
-rwxr-xr-xtest/functional/feature_notifications.py12
-rwxr-xr-xtest/functional/feature_proxy.py28
-rwxr-xr-xtest/functional/feature_pruning.py45
-rwxr-xr-xtest/functional/feature_segwit.py2
-rwxr-xr-xtest/functional/feature_settings.py2
-rwxr-xr-xtest/functional/feature_versionbits_warning.py4
-rwxr-xr-xtest/functional/interface_bitcoin_cli.py16
-rwxr-xr-xtest/functional/interface_http.py20
-rwxr-xr-xtest/functional/interface_rest.py62
-rwxr-xr-xtest/functional/interface_rpc.py2
-rwxr-xr-xtest/functional/interface_zmq.py8
-rwxr-xr-xtest/functional/mining_basic.py4
-rwxr-xr-xtest/functional/p2p_addr_relay.py22
-rwxr-xr-xtest/functional/p2p_addrfetch.py33
-rwxr-xr-xtest/functional/rpc_fundrawtransaction.py57
-rwxr-xr-xtest/functional/wallet_backup.py45
30 files changed, 314 insertions, 210 deletions
diff --git a/test/functional/feature_asmap.py b/test/functional/feature_asmap.py
index 5fcecb4882..704dd6126b 100755
--- a/test/functional/feature_asmap.py
+++ b/test/functional/feature_asmap.py
@@ -31,8 +31,8 @@ ASMAP = '../../src/test/data/asmap.raw' # path to unit test skeleton asmap
VERSION = 'fec61fa21a9f46f3b17bdcd660d7f4cd90b966aad3aec593c99b35f0aca15853'
def expected_messages(filename):
- return ['Opened asmap file "{}" (59 bytes) from disk'.format(filename),
- 'Using asmap version {} for IP bucketing'.format(VERSION)]
+ return [f'Opened asmap file "{filename}" (59 bytes) from disk',
+ f'Using asmap version {VERSION} for IP bucketing']
class AsmapTest(BitcoinTestFramework):
def set_test_params(self):
@@ -50,7 +50,7 @@ class AsmapTest(BitcoinTestFramework):
filename = os.path.join(self.datadir, 'my-map-file.map')
shutil.copyfile(self.asmap_raw, filename)
with self.node.assert_debug_log(expected_messages(filename)):
- self.start_node(0, ['-asmap={}'.format(filename)])
+ self.start_node(0, [f'-asmap={filename}'])
os.remove(filename)
def test_asmap_with_relative_path(self):
@@ -60,13 +60,13 @@ class AsmapTest(BitcoinTestFramework):
filename = os.path.join(self.datadir, name)
shutil.copyfile(self.asmap_raw, filename)
with self.node.assert_debug_log(expected_messages(filename)):
- self.start_node(0, ['-asmap={}'.format(name)])
+ self.start_node(0, [f'-asmap={name}'])
os.remove(filename)
def test_default_asmap(self):
shutil.copyfile(self.asmap_raw, self.default_asmap)
for arg in ['-asmap', '-asmap=']:
- self.log.info('Test bitcoind {} (using default map file)'.format(arg))
+ self.log.info(f'Test bitcoind {arg} (using default map file)')
self.stop_node(0)
with self.node.assert_debug_log(expected_messages(self.default_asmap)):
self.start_node(0, [arg])
@@ -75,7 +75,7 @@ class AsmapTest(BitcoinTestFramework):
def test_default_asmap_with_missing_file(self):
self.log.info('Test bitcoind -asmap with missing default map file')
self.stop_node(0)
- msg = "Error: Could not find asmap file \"{}\"".format(self.default_asmap)
+ msg = f"Error: Could not find asmap file \"{self.default_asmap}\""
self.node.assert_start_raises_init_error(extra_args=['-asmap'], expected_msg=msg)
def test_empty_asmap(self):
@@ -83,7 +83,7 @@ class AsmapTest(BitcoinTestFramework):
self.stop_node(0)
with open(self.default_asmap, "w", encoding="utf-8") as f:
f.write("")
- msg = "Error: Could not parse asmap file \"{}\"".format(self.default_asmap)
+ msg = f"Error: Could not parse asmap file \"{self.default_asmap}\""
self.node.assert_start_raises_init_error(extra_args=['-asmap'], expected_msg=msg)
os.remove(self.default_asmap)
diff --git a/test/functional/feature_backwards_compatibility.py b/test/functional/feature_backwards_compatibility.py
index e0ba835f99..978080703e 100755
--- a/test/functional/feature_backwards_compatibility.py
+++ b/test/functional/feature_backwards_compatibility.py
@@ -366,7 +366,7 @@ class BackwardsCompatibilityTest(BitcoinTestFramework):
assert_equal(load_res['warning'], '')
wallet = node_master.get_wallet_rpc("u1_v16")
info = wallet.getaddressinfo(v16_addr)
- descriptor = "wpkh([" + info["hdmasterfingerprint"] + hdkeypath[1:] + "]" + v16_pubkey + ")"
+ descriptor = f"wpkh([{info['hdmasterfingerprint']}{hdkeypath[1:]}]{v16_pubkey})"
assert_equal(info["desc"], descsum_create(descriptor))
# Now copy that same wallet back to 0.16 to make sure no automatic upgrade breaks it
@@ -389,7 +389,7 @@ class BackwardsCompatibilityTest(BitcoinTestFramework):
node_master.loadwallet("u1_v17")
wallet = node_master.get_wallet_rpc("u1_v17")
info = wallet.getaddressinfo(address)
- descriptor = "wpkh([" + info["hdmasterfingerprint"] + hdkeypath[1:] + "]" + pubkey + ")"
+ descriptor = f"wpkh([{info['hdmasterfingerprint']}{hdkeypath[1:]}]{pubkey})"
assert_equal(info["desc"], descsum_create(descriptor))
# Now copy that same wallet back to 0.17 to make sure no automatic upgrade breaks it
diff --git a/test/functional/feature_blocksdir.py b/test/functional/feature_blocksdir.py
index 7bfad52c24..d3276e64ee 100755
--- a/test/functional/feature_blocksdir.py
+++ b/test/functional/feature_blocksdir.py
@@ -24,10 +24,10 @@ class BlocksdirTest(BitcoinTestFramework):
initialize_datadir(self.options.tmpdir, 0, self.chain)
self.log.info("Starting with nonexistent blocksdir ...")
blocksdir_path = os.path.join(self.options.tmpdir, 'blocksdir')
- self.nodes[0].assert_start_raises_init_error(["-blocksdir=" + blocksdir_path], 'Error: Specified blocks directory "{}" does not exist.'.format(blocksdir_path))
+ self.nodes[0].assert_start_raises_init_error([f"-blocksdir={blocksdir_path}"], f'Error: Specified blocks directory "{blocksdir_path}" does not exist.')
os.mkdir(blocksdir_path)
self.log.info("Starting with existing blocksdir ...")
- self.start_node(0, ["-blocksdir=" + blocksdir_path])
+ self.start_node(0, [f"-blocksdir={blocksdir_path}"])
self.log.info("mining blocks..")
self.nodes[0].generatetoaddress(10, self.nodes[0].get_deterministic_priv_key().address)
assert os.path.isfile(os.path.join(blocksdir_path, self.chain, "blocks", "blk00000.dat"))
diff --git a/test/functional/feature_cltv.py b/test/functional/feature_cltv.py
index 7c14f5d5a6..dc5bffe33e 100755
--- a/test/functional/feature_cltv.py
+++ b/test/functional/feature_cltv.py
@@ -135,7 +135,7 @@ class BIP65Test(BitcoinTestFramework):
block.nVersion = 3
block.solve()
- with self.nodes[0].assert_debug_log(expected_msgs=['{}, bad-version(0x00000003)'.format(block.hash)]):
+ with self.nodes[0].assert_debug_log(expected_msgs=[f'{block.hash}, bad-version(0x00000003)']):
peer.send_and_ping(msg_block(block))
assert_equal(int(self.nodes[0].getbestblockhash(), 16), tip)
peer.sync_with_ping()
@@ -173,8 +173,7 @@ class BIP65Test(BitcoinTestFramework):
block.hashMerkleRoot = block.calc_merkle_root()
block.solve()
- with self.nodes[0].assert_debug_log(expected_msgs=['CheckInputScripts on {} failed with {}'.format(
- block.vtx[-1].hash, expected_cltv_reject_reason)]):
+ with self.nodes[0].assert_debug_log(expected_msgs=[f'CheckInputScripts on {block.vtx[-1].hash} failed with {expected_cltv_reject_reason}']):
peer.send_and_ping(msg_block(block))
assert_equal(int(self.nodes[0].getbestblockhash(), 16), tip)
peer.sync_with_ping()
diff --git a/test/functional/feature_config_args.py b/test/functional/feature_config_args.py
index 24c8a8987a..d5f0ae480b 100755
--- a/test/functional/feature_config_args.py
+++ b/test/functional/feature_config_args.py
@@ -24,7 +24,7 @@ class ConfArgsTest(BitcoinTestFramework):
inc_conf_file_path = os.path.join(self.nodes[0].datadir, 'include.conf')
with open(os.path.join(self.nodes[0].datadir, 'bitcoin.conf'), 'a', encoding='utf-8') as conf:
- conf.write('includeconf={}\n'.format(inc_conf_file_path))
+ conf.write(f'includeconf={inc_conf_file_path}\n')
self.nodes[0].assert_start_raises_init_error(
expected_msg='Error: Error parsing command line arguments: Invalid parameter -dash_cli=1',
@@ -43,13 +43,13 @@ class ConfArgsTest(BitcoinTestFramework):
if self.is_wallet_compiled():
with open(inc_conf_file_path, 'w', encoding='utf8') as conf:
conf.write("wallet=foo\n")
- self.nodes[0].assert_start_raises_init_error(expected_msg='Error: Config setting for -wallet only applied on %s network when in [%s] section.' % (self.chain, self.chain))
+ self.nodes[0].assert_start_raises_init_error(expected_msg=f'Error: Config setting for -wallet only applied on {self.chain} network when in [{self.chain}] section.')
main_conf_file_path = os.path.join(self.options.tmpdir, 'node0', 'bitcoin_main.conf')
- util.write_config(main_conf_file_path, n=0, chain='', extra_config='includeconf={}\n'.format(inc_conf_file_path))
+ util.write_config(main_conf_file_path, n=0, chain='', extra_config=f'includeconf={inc_conf_file_path}\n')
with open(inc_conf_file_path, 'w', encoding='utf-8') as conf:
conf.write('acceptnonstdtxn=1\n')
- self.nodes[0].assert_start_raises_init_error(extra_args=["-conf={}".format(main_conf_file_path)], expected_msg='Error: acceptnonstdtxn is not currently supported for main chain')
+ self.nodes[0].assert_start_raises_init_error(extra_args=[f"-conf={main_conf_file_path}"], expected_msg='Error: acceptnonstdtxn is not currently supported for main chain')
with open(inc_conf_file_path, 'w', encoding='utf-8') as conf:
conf.write('nono\n')
@@ -69,14 +69,14 @@ class ConfArgsTest(BitcoinTestFramework):
inc_conf_file2_path = os.path.join(self.nodes[0].datadir, 'include2.conf')
with open(os.path.join(self.nodes[0].datadir, 'bitcoin.conf'), 'a', encoding='utf-8') as conf:
- conf.write('includeconf={}\n'.format(inc_conf_file2_path))
+ conf.write(f'includeconf={inc_conf_file2_path}\n')
with open(inc_conf_file_path, 'w', encoding='utf-8') as conf:
conf.write('testnot.datadir=1\n')
with open(inc_conf_file2_path, 'w', encoding='utf-8') as conf:
conf.write('[testnet]\n')
self.restart_node(0)
- self.nodes[0].stop_node(expected_stderr='Warning: ' + inc_conf_file_path + ':1 Section [testnot] is not recognized.' + os.linesep + inc_conf_file2_path + ':1 Section [testnet] is not recognized.')
+ self.nodes[0].stop_node(expected_stderr=f'Warning: {inc_conf_file_path}:1 Section [testnot] is not recognized.{os.linesep}{inc_conf_file2_path}:1 Section [testnet] is not recognized.')
with open(inc_conf_file_path, 'w', encoding='utf-8') as conf:
conf.write('') # clear
@@ -105,8 +105,8 @@ class ConfArgsTest(BitcoinTestFramework):
'Command-line arg: rpcpassword=****',
'Command-line arg: rpcuser=****',
'Command-line arg: torpassword=****',
- 'Config file arg: %s="1"' % self.chain,
- 'Config file arg: [%s] server="1"' % self.chain,
+ f'Config file arg: {self.chain}="1"',
+ f'Config file arg: [{self.chain}] server="1"',
],
unexpected_msgs=[
'alice:f7efda5c189b999524f151318c0c86$d5b51b3beffbc0',
@@ -235,7 +235,7 @@ class ConfArgsTest(BitcoinTestFramework):
# Check that using -datadir argument on non-existent directory fails
self.nodes[0].datadir = new_data_dir
- self.nodes[0].assert_start_raises_init_error(['-datadir=' + new_data_dir], 'Error: Specified data directory "' + new_data_dir + '" does not exist.')
+ self.nodes[0].assert_start_raises_init_error([f'-datadir={new_data_dir}'], f'Error: Specified data directory "{new_data_dir}" does not exist.')
# Check that using non-existent datadir in conf file fails
conf_file = os.path.join(default_data_dir, "bitcoin.conf")
@@ -243,21 +243,21 @@ class ConfArgsTest(BitcoinTestFramework):
# datadir needs to be set before [chain] section
conf_file_contents = open(conf_file, encoding='utf8').read()
with open(conf_file, 'w', encoding='utf8') as f:
- f.write("datadir=" + new_data_dir + "\n")
+ f.write(f"datadir={new_data_dir}\n")
f.write(conf_file_contents)
- self.nodes[0].assert_start_raises_init_error(['-conf=' + conf_file], 'Error: Error reading configuration file: specified data directory "' + new_data_dir + '" does not exist.')
+ self.nodes[0].assert_start_raises_init_error([f'-conf={conf_file}'], f'Error: Error reading configuration file: specified data directory "{new_data_dir}" does not exist.')
# Create the directory and ensure the config file now works
os.mkdir(new_data_dir)
- self.start_node(0, ['-conf='+conf_file])
+ self.start_node(0, [f'-conf={conf_file}'])
self.stop_node(0)
assert os.path.exists(os.path.join(new_data_dir, self.chain, 'blocks'))
# Ensure command line argument overrides datadir in conf
os.mkdir(new_data_dir_2)
self.nodes[0].datadir = new_data_dir_2
- self.start_node(0, ['-datadir='+new_data_dir_2, '-conf='+conf_file])
+ self.start_node(0, [f'-datadir={new_data_dir_2}', f'-conf={conf_file}'])
assert os.path.exists(os.path.join(new_data_dir_2, self.chain, 'blocks'))
diff --git a/test/functional/feature_csv_activation.py b/test/functional/feature_csv_activation.py
index 1ac1a0563f..bc0050d47a 100755
--- a/test/functional/feature_csv_activation.py
+++ b/test/functional/feature_csv_activation.py
@@ -247,7 +247,7 @@ class BIP68_112_113Test(BitcoinTestFramework):
self.send_blocks(test_blocks)
assert_equal(self.tipheight, CSV_ACTIVATION_HEIGHT - 2)
- self.log.info("Height = {}, CSV not yet active (will activate for block {}, not {})".format(self.tipheight, CSV_ACTIVATION_HEIGHT, CSV_ACTIVATION_HEIGHT - 1))
+ self.log.info(f"Height = {self.tipheight}, CSV not yet active (will activate for block {CSV_ACTIVATION_HEIGHT}, not {CSV_ACTIVATION_HEIGHT - 1})")
assert not softfork_active(self.nodes[0], 'csv')
# Test both version 1 and version 2 transactions for all tests
diff --git a/test/functional/feature_dbcrash.py b/test/functional/feature_dbcrash.py
index 6d8e5430f8..5bbcd20016 100755
--- a/test/functional/feature_dbcrash.py
+++ b/test/functional/feature_dbcrash.py
@@ -102,7 +102,7 @@ class ChainstateWriteCrashTest(BitcoinTestFramework):
# perhaps we generated a test case that blew up our cache?
# TODO: If this happens a lot, we should try to restart without -dbcrashratio
# and make sure that recovery happens.
- raise AssertionError("Unable to successfully restart node %d in allotted time", node_index)
+ raise AssertionError(f"Unable to successfully restart node {node_index} in allotted time")
def submit_block_catch_error(self, node_index, block):
"""Try submitting a block to the given node.
@@ -114,10 +114,10 @@ class ChainstateWriteCrashTest(BitcoinTestFramework):
self.nodes[node_index].submitblock(block)
return True
except (http.client.CannotSendRequest, http.client.RemoteDisconnected) as e:
- self.log.debug("node %d submitblock raised exception: %s", node_index, e)
+ self.log.debug(f"node {node_index} submitblock raised exception: {e}")
return False
except OSError as e:
- self.log.debug("node %d submitblock raised OSError exception: errno=%s", node_index, e.errno)
+ self.log.debug(f"node {node_index} submitblock raised OSError exception: errno={e.errno}")
if e.errno in [errno.EPIPE, errno.ECONNREFUSED, errno.ECONNRESET]:
# The node has likely crashed
return False
@@ -142,15 +142,15 @@ class ChainstateWriteCrashTest(BitcoinTestFramework):
# Deliver each block to each other node
for i in range(3):
nodei_utxo_hash = None
- self.log.debug("Syncing blocks to node %d", i)
+ self.log.debug(f"Syncing blocks to node {i}")
for (block_hash, block) in blocks:
# Get the block from node3, and submit to node_i
- self.log.debug("submitting block %s", block_hash)
+ self.log.debug(f"submitting block {block_hash}")
if not self.submit_block_catch_error(i, block):
# TODO: more carefully check that the crash is due to -dbcrashratio
# (change the exit code perhaps, and check that here?)
self.wait_for_node_exit(i, timeout=30)
- self.log.debug("Restarting node %d after block hash %s", i, block_hash)
+ self.log.debug(f"Restarting node {i} after block hash {block_hash}")
nodei_utxo_hash = self.restart_node(i, block_hash)
assert nodei_utxo_hash is not None
self.restart_counts[i] += 1
@@ -167,7 +167,7 @@ class ChainstateWriteCrashTest(BitcoinTestFramework):
# - we only update the utxo cache after a node restart, since flushing
# the cache is a no-op at that point
if nodei_utxo_hash is not None:
- self.log.debug("Checking txoutsetinfo matches for node %d", i)
+ self.log.debug(f"Checking txoutsetinfo matches for node {i}")
assert_equal(nodei_utxo_hash, node3_utxo_hash)
def verify_utxo_hash(self):
@@ -218,14 +218,14 @@ class ChainstateWriteCrashTest(BitcoinTestFramework):
# Start by creating a lot of utxos on node3
initial_height = self.nodes[3].getblockcount()
utxo_list = create_confirmed_utxos(self.nodes[3].getnetworkinfo()['relayfee'], self.nodes[3], 5000)
- self.log.info("Prepped %d utxo entries", len(utxo_list))
+ self.log.info(f"Prepped {len(utxo_list)} utxo entries")
# Sync these blocks with the other nodes
block_hashes_to_sync = []
for height in range(initial_height + 1, self.nodes[3].getblockcount() + 1):
block_hashes_to_sync.append(self.nodes[3].getblockhash(height))
- self.log.debug("Syncing %d blocks with other nodes", len(block_hashes_to_sync))
+ self.log.debug(f"Syncing {len(block_hashes_to_sync)} blocks with other nodes")
# Syncing the blocks could cause nodes to crash, so the test begins here.
self.sync_node3blocks(block_hashes_to_sync)
@@ -235,18 +235,18 @@ class ChainstateWriteCrashTest(BitcoinTestFramework):
# each time through the loop, generate a bunch of transactions,
# and then either mine a single new block on the tip, or some-sized reorg.
for i in range(40):
- self.log.info("Iteration %d, generating 2500 transactions %s", i, self.restart_counts)
+ self.log.info(f"Iteration {i}, generating 2500 transactions {self.restart_counts}")
# Generate a bunch of small-ish transactions
self.generate_small_transactions(self.nodes[3], 2500, utxo_list)
# Pick a random block between current tip, and starting tip
current_height = self.nodes[3].getblockcount()
random_height = random.randint(starting_tip_height, current_height)
- self.log.debug("At height %d, considering height %d", current_height, random_height)
+ self.log.debug(f"At height {current_height}, considering height {random_height}")
if random_height > starting_tip_height:
# Randomly reorg from this point with some probability (1/4 for
# tip, 1/5 for tip-1, ...)
if random.random() < 1.0 / (current_height + 4 - random_height):
- self.log.debug("Invalidating block at height %d", random_height)
+ self.log.debug(f"Invalidating block at height {random_height}")
self.nodes[3].invalidateblock(self.nodes[3].getblockhash(random_height))
# Now generate new blocks until we pass the old tip height
@@ -258,10 +258,10 @@ class ChainstateWriteCrashTest(BitcoinTestFramework):
# new address to avoid mining a block that has just been invalidated
address=self.nodes[3].getnewaddress(),
))
- self.log.debug("Syncing %d new blocks...", len(block_hashes))
+ self.log.debug(f"Syncing {len(block_hashes)} new blocks...")
self.sync_node3blocks(block_hashes)
utxo_list = self.nodes[3].listunspent()
- self.log.debug("Node3 utxo count: %d", len(utxo_list))
+ self.log.debug(f"Node3 utxo count: {len(utxo_list)}")
# Check that the utxo hashes agree with node3
# Useful side effect: each utxo cache gets flushed here, so that we
@@ -269,7 +269,7 @@ class ChainstateWriteCrashTest(BitcoinTestFramework):
self.verify_utxo_hash()
# Check the test coverage
- self.log.info("Restarted nodes: %s; crashes on restart: %d", self.restart_counts, self.crashed_on_restart)
+ self.log.info(f"Restarted nodes: {self.restart_counts}; crashes on restart: {self.crashed_on_restart}")
# If no nodes were restarted, we didn't test anything.
assert self.restart_counts != [0, 0, 0]
@@ -280,7 +280,7 @@ class ChainstateWriteCrashTest(BitcoinTestFramework):
# Warn if any of the nodes escaped restart.
for i in range(3):
if self.restart_counts[i] == 0:
- self.log.warning("Node %d never crashed during utxo flush!", i)
+ self.log.warning(f"Node {i} never crashed during utxo flush!")
if __name__ == "__main__":
diff --git a/test/functional/feature_dersig.py b/test/functional/feature_dersig.py
index 5dd6cb6cb2..fd46385cd4 100755
--- a/test/functional/feature_dersig.py
+++ b/test/functional/feature_dersig.py
@@ -104,7 +104,7 @@ class BIP66Test(BitcoinTestFramework):
block.rehash()
block.solve()
- with self.nodes[0].assert_debug_log(expected_msgs=['{}, bad-version(0x00000002)'.format(block.hash)]):
+ with self.nodes[0].assert_debug_log(expected_msgs=[f'{block.hash}, bad-version(0x00000002)']):
peer.send_and_ping(msg_block(block))
assert_equal(int(self.nodes[0].getbestblockhash(), 16), tip)
peer.sync_with_ping()
@@ -134,7 +134,7 @@ class BIP66Test(BitcoinTestFramework):
block.rehash()
block.solve()
- with self.nodes[0].assert_debug_log(expected_msgs=['CheckInputScripts on {} failed with non-mandatory-script-verify-flag (Non-canonical DER signature)'.format(block.vtx[-1].hash)]):
+ with self.nodes[0].assert_debug_log(expected_msgs=[f'CheckInputScripts on {block.vtx[-1].hash} failed with non-mandatory-script-verify-flag (Non-canonical DER signature)']):
peer.send_and_ping(msg_block(block))
assert_equal(int(self.nodes[0].getbestblockhash(), 16), tip)
peer.sync_with_ping()
diff --git a/test/functional/feature_fee_estimation.py b/test/functional/feature_fee_estimation.py
index 5322b02414..a8f3e12e07 100755
--- a/test/functional/feature_fee_estimation.py
+++ b/test/functional/feature_fee_estimation.py
@@ -72,7 +72,7 @@ def small_txpuzzle_randfee(from_node, conflist, unconflist, amount, min_fee, fee
total_in += t["amount"]
tx.vin.append(CTxIn(COutPoint(int(t["txid"], 16), t["vout"]), b""))
if total_in <= amount + fee:
- raise RuntimeError("Insufficient funds: need %d, have %d" % (amount + fee, total_in))
+ raise RuntimeError(f"Insufficient funds: need {amount + fee}, have {total_in}")
tx.vout.append(CTxOut(int((total_in - amount - fee) * COIN), P2SH_1))
tx.vout.append(CTxOut(int(amount * COIN), P2SH_2))
# These transactions don't need to be signed, but we still have to insert
@@ -124,8 +124,7 @@ def check_raw_estimates(node, fees_seen):
assert_greater_than(feerate, 0)
if feerate + delta < min(fees_seen) or feerate - delta > max(fees_seen):
- raise AssertionError("Estimated fee (%f) out of range (%f,%f)"
- % (feerate, min(fees_seen), max(fees_seen)))
+ raise AssertionError(f"Estimated fee ({feerate}) out of range ({min(fees_seen)},{max(fees_seen)})")
def check_smart_estimates(node, fees_seen):
"""Call estimatesmartfee and verify that the estimates meet certain invariants."""
@@ -138,11 +137,9 @@ def check_smart_estimates(node, fees_seen):
assert_greater_than(feerate, 0)
if feerate + delta < min(fees_seen) or feerate - delta > max(fees_seen):
- raise AssertionError("Estimated fee (%f) out of range (%f,%f)"
- % (feerate, min(fees_seen), max(fees_seen)))
+ raise AssertionError(f"Estimated fee ({feerate}) out of range ({min(fees_seen)},{max(fees_seen)})")
if feerate - delta > last_feerate:
- raise AssertionError("Estimated fee (%f) larger than last fee (%f) for lower number of confirms"
- % (feerate, last_feerate))
+ raise AssertionError(f"Estimated fee ({feerate}) larger than last fee ({last_feerate}) for lower number of confirms")
last_feerate = feerate
if i == 0:
diff --git a/test/functional/feature_filelock.py b/test/functional/feature_filelock.py
index 2798d11b0a..e09107802b 100755
--- a/test/functional/feature_filelock.py
+++ b/test/functional/feature_filelock.py
@@ -22,11 +22,11 @@ class FilelockTest(BitcoinTestFramework):
def run_test(self):
datadir = os.path.join(self.nodes[0].datadir, self.chain)
- self.log.info("Using datadir {}".format(datadir))
+ self.log.info(f"Using datadir {datadir}")
self.log.info("Check that we can't start a second bitcoind instance using the same datadir")
- expected_msg = "Error: Cannot obtain a lock on data directory {0}. {1} is probably already running.".format(datadir, self.config['environment']['PACKAGE_NAME'])
- self.nodes[1].assert_start_raises_init_error(extra_args=['-datadir={}'.format(self.nodes[0].datadir), '-noserver'], expected_msg=expected_msg)
+ expected_msg = f"Error: Cannot obtain a lock on data directory {datadir}. {self.config['environment']['PACKAGE_NAME']} is probably already running."
+ self.nodes[1].assert_start_raises_init_error(extra_args=[f'-datadir={self.nodes[0].datadir}', '-noserver'], expected_msg=expected_msg)
if self.is_wallet_compiled():
def check_wallet_filelock(descriptors):
@@ -38,7 +38,7 @@ class FilelockTest(BitcoinTestFramework):
expected_msg = "Error: SQLiteDatabase: Unable to obtain an exclusive lock on the database, is it being used by another bitcoind?"
else:
expected_msg = "Error: Error initializing wallet database environment"
- self.nodes[1].assert_start_raises_init_error(extra_args=['-walletdir={}'.format(wallet_dir), '-wallet=' + wallet_name, '-noserver'], expected_msg=expected_msg, match=ErrorMatch.PARTIAL_REGEX)
+ self.nodes[1].assert_start_raises_init_error(extra_args=[f'-walletdir={wallet_dir}', f'-wallet={wallet_name}', '-noserver'], expected_msg=expected_msg, match=ErrorMatch.PARTIAL_REGEX)
if self.is_bdb_compiled():
check_wallet_filelock(False)
diff --git a/test/functional/feature_help.py b/test/functional/feature_help.py
index babe9bfc80..837e95c128 100755
--- a/test/functional/feature_help.py
+++ b/test/functional/feature_help.py
@@ -40,14 +40,14 @@ class HelpTest(BitcoinTestFramework):
# Node should exit immediately and output help to stdout.
output, _ = self.get_node_output(ret_code_expected=0)
assert b'Options' in output
- self.log.info("Help text received: {} (...)".format(output[0:60]))
+ self.log.info(f"Help text received: {output[0:60]} (...)")
self.log.info("Start bitcoin with -version for version information")
self.nodes[0].start(extra_args=['-version'])
# Node should exit immediately and output version to stdout.
output, _ = self.get_node_output(ret_code_expected=0)
assert b'version' in output
- self.log.info("Version text received: {} (...)".format(output[0:60]))
+ self.log.info(f"Version text received: {output[0:60]} (...)")
# Test that arguments not in the help results in an error
self.log.info("Start bitcoind with -fakearg to make sure it does not start")
@@ -55,7 +55,7 @@ class HelpTest(BitcoinTestFramework):
# Node should exit immediately and output an error to stderr
_, output = self.get_node_output(ret_code_expected=1)
assert b'Error parsing command line arguments' in output
- self.log.info("Error message received: {} (...)".format(output[0:60]))
+ self.log.info(f"Error message received: {output[0:60]} (...)")
if __name__ == '__main__':
diff --git a/test/functional/feature_loadblock.py b/test/functional/feature_loadblock.py
index 14f64d63a2..e5db6de085 100755
--- a/test/functional/feature_loadblock.py
+++ b/test/functional/feature_loadblock.py
@@ -45,17 +45,17 @@ class LoadblockTest(BitcoinTestFramework):
self.log.info("Create linearization config file")
with open(cfg_file, "a", encoding="utf-8") as cfg:
- cfg.write("datadir={}\n".format(data_dir))
- cfg.write("rpcuser={}\n".format(node_url.username))
- cfg.write("rpcpassword={}\n".format(node_url.password))
- cfg.write("port={}\n".format(node_url.port))
- cfg.write("host={}\n".format(node_url.hostname))
- cfg.write("output_file={}\n".format(bootstrap_file))
- cfg.write("max_height=100\n")
- cfg.write("netmagic=fabfb5da\n")
- cfg.write("input={}\n".format(blocks_dir))
- cfg.write("genesis={}\n".format(genesis_block))
- cfg.write("hashlist={}\n".format(hash_list.name))
+ cfg.write(f"datadir={data_dir}\n")
+ cfg.write(f"rpcuser={node_url.username}\n")
+ cfg.write(f"rpcpassword={node_url.password}\n")
+ cfg.write(f"port={node_url.port}\n")
+ cfg.write(f"host={node_url.hostname}\n")
+ cfg.write(f"output_file={bootstrap_file}\n")
+ cfg.write(f"max_height=100\n")
+ cfg.write(f"netmagic=fabfb5da\n")
+ cfg.write(f"input={blocks_dir}\n")
+ cfg.write(f"genesis={genesis_block}\n")
+ cfg.write(f"hashlist={hash_list.name}\n")
base_dir = self.config["environment"]["SRCDIR"]
linearize_dir = os.path.join(base_dir, "contrib", "linearize")
@@ -72,7 +72,7 @@ class LoadblockTest(BitcoinTestFramework):
check=True)
self.log.info("Restart second, unsynced node with bootstrap file")
- self.restart_node(1, extra_args=["-loadblock=" + bootstrap_file])
+ self.restart_node(1, extra_args=[f"-loadblock={bootstrap_file}"])
assert_equal(self.nodes[1].getblockcount(), 100) # start_node is blocking on all block files being imported
assert_equal(self.nodes[1].getblockchaininfo()['blocks'], 100)
diff --git a/test/functional/feature_logging.py b/test/functional/feature_logging.py
index afcbcf099a..722219518a 100755
--- a/test/functional/feature_logging.py
+++ b/test/functional/feature_logging.py
@@ -29,7 +29,7 @@ class LoggingTest(BitcoinTestFramework):
# test alternative log file name outside datadir
tempname = os.path.join(self.options.tmpdir, "foo.log")
- self.restart_node(0, ["-debuglogfile=%s" % tempname])
+ self.restart_node(0, [f"-debuglogfile={tempname}"])
assert os.path.isfile(tempname)
# check that invalid log (relative) will cause error
@@ -37,26 +37,26 @@ class LoggingTest(BitcoinTestFramework):
invalidname = os.path.join("foo", "foo.log")
self.stop_node(0)
exp_stderr = r"Error: Could not open debug log file \S+$"
- self.nodes[0].assert_start_raises_init_error(["-debuglogfile=%s" % (invalidname)], exp_stderr, match=ErrorMatch.FULL_REGEX)
+ self.nodes[0].assert_start_raises_init_error([f"-debuglogfile={invalidname}"], exp_stderr, match=ErrorMatch.FULL_REGEX)
assert not os.path.isfile(os.path.join(invdir, "foo.log"))
# check that invalid log (relative) works after path exists
self.stop_node(0)
os.mkdir(invdir)
- self.start_node(0, ["-debuglogfile=%s" % (invalidname)])
+ self.start_node(0, [f"-debuglogfile={invalidname}"])
assert os.path.isfile(os.path.join(invdir, "foo.log"))
# check that invalid log (absolute) will cause error
self.stop_node(0)
invdir = os.path.join(self.options.tmpdir, "foo")
invalidname = os.path.join(invdir, "foo.log")
- self.nodes[0].assert_start_raises_init_error(["-debuglogfile=%s" % invalidname], exp_stderr, match=ErrorMatch.FULL_REGEX)
+ self.nodes[0].assert_start_raises_init_error([f"-debuglogfile={invalidname}"], exp_stderr, match=ErrorMatch.FULL_REGEX)
assert not os.path.isfile(os.path.join(invdir, "foo.log"))
# check that invalid log (absolute) works after path exists
self.stop_node(0)
os.mkdir(invdir)
- self.start_node(0, ["-debuglogfile=%s" % (invalidname)])
+ self.start_node(0, [f"-debuglogfile={invalidname}"])
assert os.path.isfile(os.path.join(invdir, "foo.log"))
# check that -nodebuglogfile disables logging
@@ -67,7 +67,7 @@ class LoggingTest(BitcoinTestFramework):
assert not os.path.isfile(default_log_path)
# just sanity check no crash here
- self.restart_node(0, ["-debuglogfile=%s" % os.devnull])
+ self.restart_node(0, [f"-debuglogfile={os.devnull}"])
if __name__ == '__main__':
diff --git a/test/functional/feature_minchainwork.py b/test/functional/feature_minchainwork.py
index 803feb509a..3950690cf0 100755
--- a/test/functional/feature_minchainwork.py
+++ b/test/functional/feature_minchainwork.py
@@ -45,16 +45,16 @@ class MinimumChainWorkTest(BitcoinTestFramework):
# Start building a chain on node0. node2 shouldn't be able to sync until node1's
# minchainwork is exceeded
starting_chain_work = REGTEST_WORK_PER_BLOCK # Genesis block's work
- self.log.info("Testing relay across node %d (minChainWork = %d)", 1, self.node_min_work[1])
+ self.log.info(f"Testing relay across node 1 (minChainWork = {self.node_min_work[1]})")
starting_blockcount = self.nodes[2].getblockcount()
num_blocks_to_generate = int((self.node_min_work[1] - starting_chain_work) / REGTEST_WORK_PER_BLOCK)
- self.log.info("Generating %d blocks on node0", num_blocks_to_generate)
+ self.log.info(f"Generating {num_blocks_to_generate} blocks on node0")
hashes = self.nodes[0].generatetoaddress(num_blocks_to_generate,
self.nodes[0].get_deterministic_priv_key().address)
- self.log.info("Node0 current chain work: %s", self.nodes[0].getblockheader(hashes[-1])['chainwork'])
+ self.log.info(f"Node0 current chain work: {self.nodes[0].getblockheader(hashes[-1])['chainwork']}")
# Sleep a few seconds and verify that node2 didn't get any new blocks
# or headers. We sleep, rather than sync_blocks(node0, node1) because
@@ -63,7 +63,7 @@ class MinimumChainWorkTest(BitcoinTestFramework):
time.sleep(3)
self.log.info("Verifying node 2 has no more blocks than before")
- self.log.info("Blockcounts: %s", [n.getblockcount() for n in self.nodes])
+ self.log.info(f"Blockcounts: {[n.getblockcount() for n in self.nodes]}")
# Node2 shouldn't have any new headers yet, because node1 should not
# have relayed anything.
assert_equal(len(self.nodes[2].getchaintips()), 1)
@@ -84,7 +84,7 @@ class MinimumChainWorkTest(BitcoinTestFramework):
# continue the test.
self.sync_all()
- self.log.info("Blockcounts: %s", [n.getblockcount() for n in self.nodes])
+ self.log.info(f"Blockcounts: {[n.getblockcount() for n in self.nodes]}")
if __name__ == '__main__':
MinimumChainWorkTest().main()
diff --git a/test/functional/feature_notifications.py b/test/functional/feature_notifications.py
index 6fc8773ee3..3f8fe9ccd5 100755
--- a/test/functional/feature_notifications.py
+++ b/test/functional/feature_notifications.py
@@ -20,7 +20,7 @@ FILE_CHARS_DISALLOWED = '/\\?%*:|"<>' if os.name == 'nt' else '/'
UNCONFIRMED_HASH_STRING = 'unconfirmed'
def notify_outputname(walletname, txid):
- return txid if os.name == 'nt' else '{}_{}'.format(walletname, txid)
+ return txid if os.name == 'nt' else f'{walletname}_{txid}'
class NotificationsTest(BitcoinTestFramework):
@@ -39,11 +39,11 @@ class NotificationsTest(BitcoinTestFramework):
# -alertnotify and -blocknotify on node0, walletnotify on node1
self.extra_args = [[
- "-alertnotify=echo > {}".format(os.path.join(self.alertnotify_dir, '%s')),
- "-blocknotify=echo > {}".format(os.path.join(self.blocknotify_dir, '%s')),
+ f"-alertnotify=echo > {os.path.join(self.alertnotify_dir, '%s')}",
+ f"-blocknotify=echo > {os.path.join(self.blocknotify_dir, '%s')}",
], [
"-rescan",
- "-walletnotify=echo %h_%b > {}".format(os.path.join(self.walletnotify_dir, notify_outputname('%w', '%s'))),
+ f"-walletnotify=echo %h_%b > {os.path.join(self.walletnotify_dir, notify_outputname('%w', '%s'))}",
]]
self.wallet_names = [self.default_wallet_name, self.wallet]
super().setup_network()
@@ -54,12 +54,12 @@ class NotificationsTest(BitcoinTestFramework):
seed = "cTdGmKFWpbvpKQ7ejrdzqYT2hhjyb3GPHnLAK7wdi5Em67YLwSm9"
xpriv = "tprv8ZgxMBicQKsPfHCsTwkiM1KT56RXbGGTqvc2hgqzycpwbHqqpcajQeMRZoBD35kW4RtyCemu6j34Ku5DEspmgjKdt2qe4SvRch5Kk8B8A2v"
desc_imports = [{
- "desc": descsum_create("wpkh(" + xpriv + "/0/*)"),
+ "desc": descsum_create(f"wpkh({xpriv}/0/*)"),
"timestamp": 0,
"active": True,
"keypool": True,
},{
- "desc": descsum_create("wpkh(" + xpriv + "/1/*)"),
+ "desc": descsum_create(f"wpkh({xpriv}/1/*)"),
"timestamp": 0,
"active": True,
"keypool": True,
diff --git a/test/functional/feature_proxy.py b/test/functional/feature_proxy.py
index 162814815e..2fb5e328f5 100755
--- a/test/functional/feature_proxy.py
+++ b/test/functional/feature_proxy.py
@@ -97,14 +97,14 @@ class ProxyTest(BitcoinTestFramework):
# Note: proxies are not used to connect to local nodes. This is because the proxy to
# use is based on CService.GetNetwork(), which returns NET_UNROUTABLE for localhost.
args = [
- ['-listen', '-proxy=%s:%i' % (self.conf1.addr),'-proxyrandomize=1'],
- ['-listen', '-proxy=%s:%i' % (self.conf1.addr),'-onion=%s:%i' % (self.conf2.addr),
- '-i2psam=%s:%i' % (self.i2p_sam), '-i2pacceptincoming=0', '-proxyrandomize=0'],
- ['-listen', '-proxy=%s:%i' % (self.conf2.addr),'-proxyrandomize=1'],
+ ['-listen', f'-proxy={self.conf1.addr[0]}:{self.conf1.addr[1]}','-proxyrandomize=1'],
+ ['-listen', f'-proxy={self.conf1.addr[0]}:{self.conf1.addr[1]}',f'-onion={self.conf2.addr[0]}:{self.conf2.addr[1]}',
+ f'-i2psam={self.i2p_sam[0]}:{self.i2p_sam[1]}', '-i2pacceptincoming=0', '-proxyrandomize=0'],
+ ['-listen', f'-proxy={self.conf2.addr[0]}:{self.conf2.addr[1]}','-proxyrandomize=1'],
[]
]
if self.have_ipv6:
- args[3] = ['-listen', '-proxy=[%s]:%i' % (self.conf3.addr),'-proxyrandomize=0', '-noonion']
+ args[3] = ['-listen', f'-proxy=[{self.conf3.addr[0]}]:{self.conf3.addr[1]}','-proxyrandomize=0', '-noonion']
self.add_nodes(self.num_nodes, extra_args=args)
self.start_nodes()
@@ -116,7 +116,7 @@ class ProxyTest(BitcoinTestFramework):
def node_test(self, node, proxies, auth, test_onion=True):
rv = []
addr = "15.61.23.23:1234"
- self.log.debug("Test: outgoing IPv4 connection through node for address {}".format(addr))
+ self.log.debug(f"Test: outgoing IPv4 connection through node for address {addr}")
node.addnode(addr, "onetry")
cmd = proxies[0].queue.get()
assert isinstance(cmd, Socks5Command)
@@ -132,7 +132,7 @@ class ProxyTest(BitcoinTestFramework):
if self.have_ipv6:
addr = "[1233:3432:2434:2343:3234:2345:6546:4534]:5443"
- self.log.debug("Test: outgoing IPv6 connection through node for address {}".format(addr))
+ self.log.debug(f"Test: outgoing IPv6 connection through node for address {addr}")
node.addnode(addr, "onetry")
cmd = proxies[1].queue.get()
assert isinstance(cmd, Socks5Command)
@@ -148,7 +148,7 @@ class ProxyTest(BitcoinTestFramework):
if test_onion:
addr = "pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion:8333"
- self.log.debug("Test: outgoing onion connection through node for address {}".format(addr))
+ self.log.debug(f"Test: outgoing onion connection through node for address {addr}")
node.addnode(addr, "onetry")
cmd = proxies[2].queue.get()
assert isinstance(cmd, Socks5Command)
@@ -162,7 +162,7 @@ class ProxyTest(BitcoinTestFramework):
self.network_test(node, addr, network=NET_ONION)
addr = "node.noumenon:8333"
- self.log.debug("Test: outgoing DNS name connection through node for address {}".format(addr))
+ self.log.debug(f"Test: outgoing DNS name connection through node for address {addr}")
node.addnode(addr, "onetry")
cmd = proxies[3].queue.get()
assert isinstance(cmd, Socks5Command)
@@ -218,12 +218,12 @@ class ProxyTest(BitcoinTestFramework):
n1 = networks_dict(self.nodes[1].getnetworkinfo())
assert_equal(NETWORKS, n1.keys())
for net in ['ipv4', 'ipv6']:
- assert_equal(n1[net]['proxy'], '%s:%i' % (self.conf1.addr))
+ assert_equal(n1[net]['proxy'], f'{self.conf1.addr[0]}:{self.conf1.addr[1]}')
assert_equal(n1[net]['proxy_randomize_credentials'], False)
- assert_equal(n1['onion']['proxy'], '%s:%i' % (self.conf2.addr))
+ assert_equal(n1['onion']['proxy'], f'{self.conf2.addr[0]}:{self.conf2.addr[1]}')
assert_equal(n1['onion']['proxy_randomize_credentials'], False)
assert_equal(n1['onion']['reachable'], True)
- assert_equal(n1['i2p']['proxy'], '%s:%i' % (self.i2p_sam))
+ assert_equal(n1['i2p']['proxy'], f'{self.i2p_sam[0]}:{self.i2p_sam[1]}')
assert_equal(n1['i2p']['proxy_randomize_credentials'], False)
assert_equal(n1['i2p']['reachable'], True)
@@ -234,7 +234,7 @@ class ProxyTest(BitcoinTestFramework):
expected_proxy = ''
expected_randomize = False
else:
- expected_proxy = '%s:%i' % (self.conf2.addr)
+ expected_proxy = f'{self.conf2.addr[0]}:{self.conf2.addr[1]}'
expected_randomize = True
assert_equal(n2[net]['proxy'], expected_proxy)
assert_equal(n2[net]['proxy_randomize_credentials'], expected_randomize)
@@ -248,7 +248,7 @@ class ProxyTest(BitcoinTestFramework):
if net == NET_I2P:
expected_proxy = ''
else:
- expected_proxy = '[%s]:%i' % (self.conf3.addr)
+ expected_proxy = f'[{self.conf3.addr[0]}]:{self.conf3.addr[1]}'
assert_equal(n3[net]['proxy'], expected_proxy)
assert_equal(n3[net]['proxy_randomize_credentials'], False)
assert_equal(n3['onion']['reachable'], False)
diff --git a/test/functional/feature_pruning.py b/test/functional/feature_pruning.py
index cedb7b57ca..2f0868e733 100755
--- a/test/functional/feature_pruning.py
+++ b/test/functional/feature_pruning.py
@@ -127,10 +127,28 @@ class PruneTest(BitcoinTestFramework):
self.sync_blocks(self.nodes[0:5])
+ def test_invalid_command_line_options(self):
+ self.nodes[0].assert_start_raises_init_error(
+ expected_msg='Error: Prune cannot be configured with a negative value.',
+ extra_args=['-prune=-1'],
+ )
+ self.nodes[0].assert_start_raises_init_error(
+ expected_msg='Error: Prune configured below the minimum of 550 MiB. Please use a higher number.',
+ extra_args=['-prune=549'],
+ )
+ self.nodes[0].assert_start_raises_init_error(
+ expected_msg='Error: Prune mode is incompatible with -txindex.',
+ extra_args=['-prune=550', '-txindex'],
+ )
+ self.nodes[0].assert_start_raises_init_error(
+ expected_msg='Error: Prune mode is incompatible with -coinstatsindex.',
+ extra_args=['-prune=550', '-coinstatsindex'],
+ )
+
def test_height_min(self):
assert os.path.isfile(os.path.join(self.prunedir, "blk00000.dat")), "blk00000.dat is missing, pruning too early"
self.log.info("Success")
- self.log.info("Though we're already using more than 550MiB, current usage: %d" % calc_usage(self.prunedir))
+ self.log.info(f"Though we're already using more than 550MiB, current usage: {calc_usage(self.prunedir)}")
self.log.info("Mining 25 more blocks should cause the first block file to be pruned")
# Pruning doesn't run until we're allocating another chunk, 20 full blocks past the height cutoff will ensure this
mine_large_blocks(self.nodes[0], 25)
@@ -140,7 +158,7 @@ class PruneTest(BitcoinTestFramework):
self.log.info("Success")
usage = calc_usage(self.prunedir)
- self.log.info("Usage should be below target: %d" % usage)
+ self.log.info(f"Usage should be below target: {usage}")
assert_greater_than(550, usage)
def create_chain_with_staleblocks(self):
@@ -163,18 +181,18 @@ class PruneTest(BitcoinTestFramework):
self.connect_nodes(0, 2)
self.sync_blocks(self.nodes[0:3])
- self.log.info("Usage can be over target because of high stale rate: %d" % calc_usage(self.prunedir))
+ self.log.info(f"Usage can be over target because of high stale rate: {calc_usage(self.prunedir)}")
def reorg_test(self):
# Node 1 will mine a 300 block chain starting 287 blocks back from Node 0 and Node 2's tip
# This will cause Node 2 to do a reorg requiring 288 blocks of undo data to the reorg_test chain
height = self.nodes[1].getblockcount()
- self.log.info("Current block height: %d" % height)
+ self.log.info(f"Current block height: {height}")
self.forkheight = height - 287
self.forkhash = self.nodes[1].getblockhash(self.forkheight)
- self.log.info("Invalidating block %s at height %d" % (self.forkhash, self.forkheight))
+ self.log.info(f"Invalidating block {self.forkhash} at height {self.forkheight}")
self.nodes[1].invalidateblock(self.forkhash)
# We've now switched to our previously mined-24 block fork on node 1, but that's not what we want
@@ -186,7 +204,7 @@ class PruneTest(BitcoinTestFramework):
curhash = self.nodes[1].getblockhash(self.forkheight - 1)
assert self.nodes[1].getblockcount() == self.forkheight - 1
- self.log.info("New best height: %d" % self.nodes[1].getblockcount())
+ self.log.info(f"New best height: {self.nodes[1].getblockcount()}")
# Disconnect node1 and generate the new chain
self.disconnect_nodes(0, 1)
@@ -200,8 +218,8 @@ class PruneTest(BitcoinTestFramework):
self.connect_nodes(1, 2)
self.sync_blocks(self.nodes[0:3], timeout=120)
- self.log.info("Verify height on node 2: %d" % self.nodes[2].getblockcount())
- self.log.info("Usage possibly still high because of stale blocks in block files: %d" % calc_usage(self.prunedir))
+ self.log.info(f"Verify height on node 2: {self.nodes[2].getblockcount()}")
+ self.log.info(f"Usage possibly still high because of stale blocks in block files: {calc_usage(self.prunedir)}")
self.log.info("Mine 220 more large blocks so we have requisite history")
@@ -209,7 +227,7 @@ class PruneTest(BitcoinTestFramework):
self.sync_blocks(self.nodes[0:3], timeout=120)
usage = calc_usage(self.prunedir)
- self.log.info("Usage should be below target: %d" % usage)
+ self.log.info(f"Usage should be below target: {usage}")
assert_greater_than(550, usage)
def reorg_back(self):
@@ -217,7 +235,7 @@ class PruneTest(BitcoinTestFramework):
assert_raises_rpc_error(-1, "Block not available (pruned data)", self.nodes[2].getblock, self.forkhash)
with self.nodes[2].assert_debug_log(expected_msgs=['block verification stopping at height', '(pruning, no data)']):
self.nodes[2].verifychain(checklevel=4, nblocks=0)
- self.log.info("Will need to redownload block %d" % self.forkheight)
+ self.log.info(f"Will need to redownload block {self.forkheight}")
# Verify that we have enough history to reorg back to the fork point
# Although this is more than 288 blocks, because this chain was written more recently
@@ -241,7 +259,7 @@ class PruneTest(BitcoinTestFramework):
# At this point node 2 is within 288 blocks of the fork point so it will preserve its ability to reorg
if self.nodes[2].getblockcount() < self.mainchainheight:
blocks_to_mine = first_reorg_height + 1 - self.mainchainheight
- self.log.info("Rewind node 0 to prev main chain to mine longer chain to trigger redownload. Blocks needed: %d" % blocks_to_mine)
+ self.log.info(f"Rewind node 0 to prev main chain to mine longer chain to trigger redownload. Blocks needed: {blocks_to_mine}")
self.nodes[0].invalidateblock(curchainhash)
assert_equal(self.nodes[0].getblockcount(), self.mainchainheight)
assert_equal(self.nodes[0].getbestblockhash(), self.mainchainhash2)
@@ -278,7 +296,7 @@ class PruneTest(BitcoinTestFramework):
assert_equal(ret, node.getblockchaininfo()['pruneheight'])
def has_block(index):
- return os.path.isfile(os.path.join(self.nodes[node_number].datadir, self.chain, "blocks", "blk{:05}.dat".format(index)))
+ return os.path.isfile(os.path.join(self.nodes[node_number].datadir, self.chain, "blocks", f"blk{index:05}.dat"))
# should not prune because chain tip of node 3 (995) < PruneAfterHeight (1000)
assert_raises_rpc_error(-1, "Blockchain is too short for pruning", node.pruneblockchain, height(500))
@@ -453,6 +471,9 @@ class PruneTest(BitcoinTestFramework):
self.log.info("Test wallet re-scan")
self.wallet_test()
+ self.log.info("Test invalid pruning command line options")
+ self.test_invalid_command_line_options()
+
self.log.info("Done")
if __name__ == '__main__':
diff --git a/test/functional/feature_segwit.py b/test/functional/feature_segwit.py
index cbd8521499..6f1cecce58 100755
--- a/test/functional/feature_segwit.py
+++ b/test/functional/feature_segwit.py
@@ -65,7 +65,7 @@ def find_spendable_utxo(node, min_value):
if utxo['spendable']:
return utxo
- raise AssertionError("Unspent output equal or higher than %s not found" % min_value)
+ raise AssertionError(f"Unspent output equal or higher than {min_value} not found")
txs_mined = {} # txindex from txid to blockhash
diff --git a/test/functional/feature_settings.py b/test/functional/feature_settings.py
index 5a0236401d..26048d37f6 100755
--- a/test/functional/feature_settings.py
+++ b/test/functional/feature_settings.py
@@ -83,7 +83,7 @@ class SettingsTest(BitcoinTestFramework):
with altsettings.open("w") as fp:
fp.write('{"key": "value"}')
with node.assert_debug_log(expected_msgs=['Setting file arg: key = "value"']):
- self.start_node(0, extra_args=["-settings={}".format(altsettings)])
+ self.start_node(0, extra_args=[f"-settings={altsettings}"])
self.stop_node(0)
diff --git a/test/functional/feature_versionbits_warning.py b/test/functional/feature_versionbits_warning.py
index 1c9e237d78..a7ec5c48e3 100755
--- a/test/functional/feature_versionbits_warning.py
+++ b/test/functional/feature_versionbits_warning.py
@@ -21,7 +21,7 @@ VB_TOP_BITS = 0x20000000
VB_UNKNOWN_BIT = 27 # Choose a bit unassigned to any deployment
VB_UNKNOWN_VERSION = VB_TOP_BITS | (1 << VB_UNKNOWN_BIT)
-WARN_UNKNOWN_RULES_ACTIVE = "Unknown new rules activated (versionbit {})".format(VB_UNKNOWN_BIT)
+WARN_UNKNOWN_RULES_ACTIVE = f"Unknown new rules activated (versionbit {VB_UNKNOWN_BIT})"
VB_PATTERN = re.compile("Unknown new rules activated.*versionbit")
class VersionBitsWarningTest(BitcoinTestFramework):
@@ -34,7 +34,7 @@ class VersionBitsWarningTest(BitcoinTestFramework):
# Open and close to create zero-length file
with open(self.alert_filename, 'w', encoding='utf8'):
pass
- self.extra_args = [["-alertnotify=echo %s >> \"" + self.alert_filename + "\""]]
+ self.extra_args = [[f"-alertnotify=echo %s >> \"{self.alert_filename}\""]]
self.setup_nodes()
def send_blocks_with_version(self, peer, numblocks, version):
diff --git a/test/functional/interface_bitcoin_cli.py b/test/functional/interface_bitcoin_cli.py
index dfa448a1a8..4b5363ec49 100755
--- a/test/functional/interface_bitcoin_cli.py
+++ b/test/functional/interface_bitcoin_cli.py
@@ -87,12 +87,12 @@ class TestBitcoinCli(BitcoinTestFramework):
user, password = get_auth_cookie(self.nodes[0].datadir, self.chain)
self.log.info("Test -stdinrpcpass option")
- assert_equal(BLOCKS, self.nodes[0].cli('-rpcuser={}'.format(user), '-stdinrpcpass', input=password).getblockcount())
- assert_raises_process_error(1, 'Incorrect rpcuser or rpcpassword', self.nodes[0].cli('-rpcuser={}'.format(user), '-stdinrpcpass', input='foo').echo)
+ assert_equal(BLOCKS, self.nodes[0].cli(f'-rpcuser={user}', '-stdinrpcpass', input=password).getblockcount())
+ assert_raises_process_error(1, 'Incorrect rpcuser or rpcpassword', self.nodes[0].cli(f'-rpcuser={user}', '-stdinrpcpass', input='foo').echo)
self.log.info("Test -stdin and -stdinrpcpass")
- assert_equal(['foo', 'bar'], self.nodes[0].cli('-rpcuser={}'.format(user), '-stdin', '-stdinrpcpass', input=password + '\nfoo\nbar').echo())
- assert_raises_process_error(1, 'Incorrect rpcuser or rpcpassword', self.nodes[0].cli('-rpcuser={}'.format(user), '-stdin', '-stdinrpcpass', input='foo').echo)
+ assert_equal(['foo', 'bar'], self.nodes[0].cli(f'-rpcuser={user}', '-stdin', '-stdinrpcpass', input=f'{password}\nfoo\nbar').echo())
+ assert_raises_process_error(1, 'Incorrect rpcuser or rpcpassword', self.nodes[0].cli(f'-rpcuser={user}', '-stdin', '-stdinrpcpass', input='foo').echo)
self.log.info("Test connecting to a non-existing server")
assert_raises_process_error(1, "Could not connect to the server", self.nodes[0].cli('-rpcport=1').echo)
@@ -150,8 +150,8 @@ class TestBitcoinCli(BitcoinTestFramework):
w1 = self.nodes[0].get_wallet_rpc(wallets[0])
w2 = self.nodes[0].get_wallet_rpc(wallets[1])
w3 = self.nodes[0].get_wallet_rpc(wallets[2])
- rpcwallet2 = '-rpcwallet={}'.format(wallets[1])
- rpcwallet3 = '-rpcwallet={}'.format(wallets[2])
+ rpcwallet2 = f'-rpcwallet={wallets[1]}'
+ rpcwallet3 = f'-rpcwallet={wallets[2]}'
w1.walletpassphrase(password, self.rpc_timeout)
w2.encryptwallet(password)
w1.sendtoaddress(w2.getnewaddress(), amounts[1])
@@ -162,7 +162,7 @@ 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_string = self.nodes[0].cli('-getinfo', '-rpcwallet={}'.format(wallets[i])).send_cli()
+ cli_get_info_string = self.nodes[0].cli('-getinfo', f'-rpcwallet={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])
@@ -296,7 +296,7 @@ class TestBitcoinCli(BitcoinTestFramework):
self.log.info("Test -version with node stopped")
self.stop_node(0)
cli_response = self.nodes[0].cli('-version').send_cli()
- assert "{} RPC client version".format(self.config['environment']['PACKAGE_NAME']) in cli_response
+ assert f"{self.config['environment']['PACKAGE_NAME']} RPC client version" in cli_response
self.log.info("Test -rpcwait option successfully waits for RPC connection")
self.nodes[0].start() # start node without RPC connection
diff --git a/test/functional/interface_http.py b/test/functional/interface_http.py
index d007490f80..075224c011 100755
--- a/test/functional/interface_http.py
+++ b/test/functional/interface_http.py
@@ -24,8 +24,8 @@ class HTTPBasicsTest (BitcoinTestFramework):
# lowlevel check for http persistent connection #
#################################################
url = urllib.parse.urlparse(self.nodes[0].url)
- authpair = url.username + ':' + url.password
- headers = {"Authorization": "Basic " + str_to_b64str(authpair)}
+ authpair = f'{url.username}:{url.password}'
+ headers = {"Authorization": f"Basic {str_to_b64str(authpair)}"}
conn = http.client.HTTPConnection(url.hostname, url.port)
conn.connect()
@@ -42,7 +42,7 @@ class HTTPBasicsTest (BitcoinTestFramework):
conn.close()
#same should be if we add keep-alive because this should be the std. behaviour
- headers = {"Authorization": "Basic " + str_to_b64str(authpair), "Connection": "keep-alive"}
+ headers = {"Authorization": f"Basic {str_to_b64str(authpair)}", "Connection": "keep-alive"}
conn = http.client.HTTPConnection(url.hostname, url.port)
conn.connect()
@@ -59,7 +59,7 @@ class HTTPBasicsTest (BitcoinTestFramework):
conn.close()
#now do the same with "Connection: close"
- headers = {"Authorization": "Basic " + str_to_b64str(authpair), "Connection":"close"}
+ headers = {"Authorization": f"Basic {str_to_b64str(authpair)}", "Connection":"close"}
conn = http.client.HTTPConnection(url.hostname, url.port)
conn.connect()
@@ -70,8 +70,8 @@ class HTTPBasicsTest (BitcoinTestFramework):
#node1 (2nd node) is running with disabled keep-alive option
urlNode1 = urllib.parse.urlparse(self.nodes[1].url)
- authpair = urlNode1.username + ':' + urlNode1.password
- headers = {"Authorization": "Basic " + str_to_b64str(authpair)}
+ authpair = f'{urlNode1.username}:{urlNode1.password}'
+ headers = {"Authorization": f"Basic {str_to_b64str(authpair)}"}
conn = http.client.HTTPConnection(urlNode1.hostname, urlNode1.port)
conn.connect()
@@ -81,8 +81,8 @@ class HTTPBasicsTest (BitcoinTestFramework):
#node2 (third node) is running with standard keep-alive parameters which means keep-alive is on
urlNode2 = urllib.parse.urlparse(self.nodes[2].url)
- authpair = urlNode2.username + ':' + urlNode2.password
- headers = {"Authorization": "Basic " + str_to_b64str(authpair)}
+ authpair = f'{urlNode2.username}:{urlNode2.password}'
+ headers = {"Authorization": f"Basic {str_to_b64str(authpair)}"}
conn = http.client.HTTPConnection(urlNode2.hostname, urlNode2.port)
conn.connect()
@@ -94,13 +94,13 @@ class HTTPBasicsTest (BitcoinTestFramework):
# Check excessive request size
conn = http.client.HTTPConnection(urlNode2.hostname, urlNode2.port)
conn.connect()
- conn.request('GET', '/' + ('x'*1000), '', headers)
+ conn.request('GET', f'/{"x"*1000}', '', headers)
out1 = conn.getresponse()
assert_equal(out1.status, http.client.NOT_FOUND)
conn = http.client.HTTPConnection(urlNode2.hostname, urlNode2.port)
conn.connect()
- conn.request('GET', '/' + ('x'*10000), '', headers)
+ conn.request('GET', f'/{"x"*10000}', '', headers)
out1 = conn.getresponse()
assert_equal(out1.status, http.client.BAD_REQUEST)
diff --git a/test/functional/interface_rest.py b/test/functional/interface_rest.py
index d644a420fc..47c95f5673 100755
--- a/test/functional/interface_rest.py
+++ b/test/functional/interface_rest.py
@@ -57,7 +57,7 @@ class RESTTest (BitcoinTestFramework):
rest_uri += '.hex'
conn = http.client.HTTPConnection(self.url.hostname, self.url.port)
- self.log.debug('%s %s %s', http_method, rest_uri, body)
+ self.log.debug(f'{http_method} {rest_uri} {body}')
if http_method == 'GET':
conn.request('GET', rest_uri)
elif http_method == 'POST':
@@ -92,11 +92,11 @@ class RESTTest (BitcoinTestFramework):
self.log.info("Test the /tx URI")
- json_obj = self.test_rest_request("/tx/{}".format(txid))
+ json_obj = self.test_rest_request(f"/tx/{txid}")
assert_equal(json_obj['txid'], txid)
# Check hex format response
- hex_response = self.test_rest_request("/tx/{}".format(txid), req_type=ReqType.HEX, ret_type=RetType.OBJ)
+ hex_response = self.test_rest_request(f"/tx/{txid}", req_type=ReqType.HEX, ret_type=RetType.OBJ)
assert_greater_than_or_equal(int(hex_response.getheader('content-length')),
json_obj['size']*2)
@@ -114,7 +114,7 @@ class RESTTest (BitcoinTestFramework):
assert_equal(self.nodes[1].getbalance(), Decimal("0.1"))
# Check chainTip response
- json_obj = self.test_rest_request("/getutxos/{}-{}".format(*spending))
+ json_obj = self.test_rest_request(f"/getutxos/{spending[0]}-{spending[1]}")
assert_equal(json_obj['chaintipHash'], bb_hash)
# Make sure there is one utxo
@@ -123,7 +123,7 @@ class RESTTest (BitcoinTestFramework):
self.log.info("Query a spent TXO using the /getutxos URI")
- json_obj = self.test_rest_request("/getutxos/{}-{}".format(*spent))
+ json_obj = self.test_rest_request(f"/getutxos/{spent[0]}-{spent[1]}")
# Check chainTip response
assert_equal(json_obj['chaintipHash'], bb_hash)
@@ -136,7 +136,7 @@ class RESTTest (BitcoinTestFramework):
self.log.info("Query two TXOs using the /getutxos URI")
- json_obj = self.test_rest_request("/getutxos/{}-{}/{}-{}".format(*(spending + spent)))
+ json_obj = self.test_rest_request(f"/getutxos/{spending[0]}-{spending[1]}/{spent[0]}-{spent[1]}")
assert_equal(len(json_obj['utxos']), 1)
assert_equal(json_obj['bitmap'], "10")
@@ -163,32 +163,32 @@ class RESTTest (BitcoinTestFramework):
# do a tx and don't sync
txid = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.1)
- json_obj = self.test_rest_request("/tx/{}".format(txid))
+ json_obj = self.test_rest_request(f"/tx/{txid}")
# get the spent output to later check for utxo (should be spent by then)
spent = (json_obj['vin'][0]['txid'], json_obj['vin'][0]['vout'])
# get n of 0.1 outpoint
n, = filter_output_indices_by_value(json_obj['vout'], Decimal('0.1'))
spending = (txid, n)
- json_obj = self.test_rest_request("/getutxos/{}-{}".format(*spending))
+ json_obj = self.test_rest_request(f"/getutxos/{spending[0]}-{spending[1]}")
assert_equal(len(json_obj['utxos']), 0)
- json_obj = self.test_rest_request("/getutxos/checkmempool/{}-{}".format(*spending))
+ json_obj = self.test_rest_request(f"/getutxos/checkmempool/{spending[0]}-{spending[1]}")
assert_equal(len(json_obj['utxos']), 1)
- json_obj = self.test_rest_request("/getutxos/{}-{}".format(*spent))
+ json_obj = self.test_rest_request(f"/getutxos/{spent[0]}-{spent[1]}")
assert_equal(len(json_obj['utxos']), 1)
- json_obj = self.test_rest_request("/getutxos/checkmempool/{}-{}".format(*spent))
+ json_obj = self.test_rest_request(f"/getutxos/checkmempool/{spent[0]}-{spent[1]}")
assert_equal(len(json_obj['utxos']), 0)
self.nodes[0].generate(1)
self.sync_all()
- json_obj = self.test_rest_request("/getutxos/{}-{}".format(*spending))
+ json_obj = self.test_rest_request(f"/getutxos/{spending[0]}-{spending[1]}")
assert_equal(len(json_obj['utxos']), 1)
- json_obj = self.test_rest_request("/getutxos/checkmempool/{}-{}".format(*spending))
+ json_obj = self.test_rest_request(f"/getutxos/checkmempool/{spending[0]}-{spending[1]}")
assert_equal(len(json_obj['utxos']), 1)
# Do some invalid requests
@@ -197,11 +197,11 @@ class RESTTest (BitcoinTestFramework):
self.test_rest_request("/getutxos/checkmempool", http_method='POST', req_type=ReqType.JSON, status=400, ret_type=RetType.OBJ)
# Test limits
- long_uri = '/'.join(["{}-{}".format(txid, n_) for n_ in range(20)])
- self.test_rest_request("/getutxos/checkmempool/{}".format(long_uri), http_method='POST', status=400, ret_type=RetType.OBJ)
+ long_uri = '/'.join([f"{txid}-{n_}" for n_ in range(20)])
+ self.test_rest_request(f"/getutxos/checkmempool/{long_uri}", http_method='POST', status=400, ret_type=RetType.OBJ)
- long_uri = '/'.join(['{}-{}'.format(txid, n_) for n_ in range(15)])
- self.test_rest_request("/getutxos/checkmempool/{}".format(long_uri), http_method='POST', status=200)
+ long_uri = '/'.join([f'{txid}-{n_}' for n_ in range(15)])
+ self.test_rest_request(f"/getutxos/checkmempool/{long_uri}", http_method='POST', status=200)
self.nodes[0].generate(1) # generate block to not affect upcoming tests
self.sync_all()
@@ -215,42 +215,42 @@ class RESTTest (BitcoinTestFramework):
# Check result if block is not in the active chain
self.nodes[0].invalidateblock(bb_hash)
- assert_equal(self.test_rest_request('/headers/1/{}'.format(bb_hash)), [])
- self.test_rest_request('/block/{}'.format(bb_hash))
+ assert_equal(self.test_rest_request(f'/headers/1/{bb_hash}'), [])
+ self.test_rest_request(f'/block/{bb_hash}')
self.nodes[0].reconsiderblock(bb_hash)
# Check binary format
- response = self.test_rest_request("/block/{}".format(bb_hash), req_type=ReqType.BIN, ret_type=RetType.OBJ)
+ response = self.test_rest_request(f"/block/{bb_hash}", req_type=ReqType.BIN, ret_type=RetType.OBJ)
assert_greater_than(int(response.getheader('content-length')), BLOCK_HEADER_SIZE)
response_bytes = response.read()
# Compare with block header
- response_header = self.test_rest_request("/headers/1/{}".format(bb_hash), req_type=ReqType.BIN, ret_type=RetType.OBJ)
+ response_header = self.test_rest_request(f"/headers/1/{bb_hash}", req_type=ReqType.BIN, ret_type=RetType.OBJ)
assert_equal(int(response_header.getheader('content-length')), BLOCK_HEADER_SIZE)
response_header_bytes = response_header.read()
assert_equal(response_bytes[:BLOCK_HEADER_SIZE], response_header_bytes)
# Check block hex format
- response_hex = self.test_rest_request("/block/{}".format(bb_hash), req_type=ReqType.HEX, ret_type=RetType.OBJ)
+ response_hex = self.test_rest_request(f"/block/{bb_hash}", req_type=ReqType.HEX, ret_type=RetType.OBJ)
assert_greater_than(int(response_hex.getheader('content-length')), BLOCK_HEADER_SIZE*2)
response_hex_bytes = response_hex.read().strip(b'\n')
assert_equal(response_bytes.hex().encode(), response_hex_bytes)
# Compare with hex block header
- response_header_hex = self.test_rest_request("/headers/1/{}".format(bb_hash), req_type=ReqType.HEX, ret_type=RetType.OBJ)
+ response_header_hex = self.test_rest_request(f"/headers/1/{bb_hash}", req_type=ReqType.HEX, ret_type=RetType.OBJ)
assert_greater_than(int(response_header_hex.getheader('content-length')), BLOCK_HEADER_SIZE*2)
response_header_hex_bytes = response_header_hex.read(BLOCK_HEADER_SIZE*2)
assert_equal(response_bytes[:BLOCK_HEADER_SIZE].hex().encode(), response_header_hex_bytes)
# Check json format
- block_json_obj = self.test_rest_request("/block/{}".format(bb_hash))
+ block_json_obj = self.test_rest_request(f"/block/{bb_hash}")
assert_equal(block_json_obj['hash'], bb_hash)
- assert_equal(self.test_rest_request("/blockhashbyheight/{}".format(block_json_obj['height']))['blockhash'], bb_hash)
+ assert_equal(self.test_rest_request(f"/blockhashbyheight/{block_json_obj['height']}")['blockhash'], bb_hash)
# Check hex/bin format
- resp_hex = self.test_rest_request("/blockhashbyheight/{}".format(block_json_obj['height']), req_type=ReqType.HEX, ret_type=RetType.OBJ)
+ resp_hex = self.test_rest_request(f"/blockhashbyheight/{block_json_obj['height']}", req_type=ReqType.HEX, ret_type=RetType.OBJ)
assert_equal(resp_hex.read().decode('utf-8').rstrip(), bb_hash)
- resp_bytes = self.test_rest_request("/blockhashbyheight/{}".format(block_json_obj['height']), req_type=ReqType.BIN, ret_type=RetType.BYTES)
+ resp_bytes = self.test_rest_request(f"/blockhashbyheight/{block_json_obj['height']}", req_type=ReqType.BIN, ret_type=RetType.BYTES)
blockhash = resp_bytes[::-1].hex()
assert_equal(blockhash, bb_hash)
@@ -264,7 +264,7 @@ class RESTTest (BitcoinTestFramework):
self.test_rest_request("/blockhashbyheight/", ret_type=RetType.OBJ, status=400)
# Compare with json block header
- json_obj = self.test_rest_request("/headers/1/{}".format(bb_hash))
+ json_obj = self.test_rest_request(f"/headers/1/{bb_hash}")
assert_equal(len(json_obj), 1) # ensure that there is one header in the json response
assert_equal(json_obj[0]['hash'], bb_hash) # request/response hash should be the same
@@ -276,7 +276,7 @@ class RESTTest (BitcoinTestFramework):
# See if we can get 5 headers in one response
self.nodes[1].generate(5)
self.sync_all()
- json_obj = self.test_rest_request("/headers/5/{}".format(bb_hash))
+ json_obj = self.test_rest_request(f"/headers/5/{bb_hash}")
assert_equal(len(json_obj), 5) # now we should have 5 header objects
self.log.info("Test tx inclusion in the /mempool and /block URIs")
@@ -306,13 +306,13 @@ class RESTTest (BitcoinTestFramework):
self.sync_all()
# Check if the 3 tx show up in the new block
- json_obj = self.test_rest_request("/block/{}".format(newblockhash[0]))
+ json_obj = self.test_rest_request(f"/block/{newblockhash[0]}")
non_coinbase_txs = {tx['txid'] for tx in json_obj['tx']
if 'coinbase' not in tx['vin'][0]}
assert_equal(non_coinbase_txs, set(txs))
# Check the same but without tx details
- json_obj = self.test_rest_request("/block/notxdetails/{}".format(newblockhash[0]))
+ json_obj = self.test_rest_request(f"/block/notxdetails/{newblockhash[0]}")
for tx in txs:
assert tx in json_obj['tx']
diff --git a/test/functional/interface_rpc.py b/test/functional/interface_rpc.py
index 4d5666f414..89a7d29b24 100755
--- a/test/functional/interface_rpc.py
+++ b/test/functional/interface_rpc.py
@@ -16,7 +16,7 @@ def expect_http_status(expected_http_status, expected_rpc_code,
fcn, *args):
try:
fcn(*args)
- raise AssertionError("Expected RPC error %d, got none" % expected_rpc_code)
+ raise AssertionError(f"Expected RPC error {expected_rpc_code}, got none")
except JSONRPCException as exc:
assert_equal(exc.error["code"], expected_rpc_code)
assert_equal(exc.http_status, expected_http_status)
diff --git a/test/functional/interface_zmq.py b/test/functional/interface_zmq.py
index 15f352d68c..61b96a8250 100755
--- a/test/functional/interface_zmq.py
+++ b/test/functional/interface_zmq.py
@@ -132,7 +132,7 @@ class ZMQTest (BitcoinTestFramework):
socket = self.ctx.socket(zmq.SUB)
subscribers.append(ZMQSubscriber(socket, topic.encode()))
- self.restart_node(0, ["-zmqpub%s=%s" % (topic, address) for topic, address in services] +
+ self.restart_node(0, [f"-zmqpub{topic}={address}" for topic, address in services] +
self.extra_args[0])
for i, sub in enumerate(subscribers):
@@ -184,7 +184,7 @@ class ZMQTest (BitcoinTestFramework):
rawtx = subs[3]
num_blocks = 5
- self.log.info("Generate %(n)d blocks (and %(n)d coinbase txes)" % {"n": num_blocks})
+ self.log.info(f"Generate {num_blocks} blocks (and {num_blocks} coinbase txes)")
genhashes = self.nodes[0].generatetoaddress(num_blocks, ADDRESS_BCRT1_UNSPENDABLE)
self.sync_all()
@@ -504,7 +504,7 @@ class ZMQTest (BitcoinTestFramework):
if mempool_sequence is not None:
zmq_mem_seq = mempool_sequence
if zmq_mem_seq > get_raw_seq:
- raise Exception("We somehow jumped mempool sequence numbers! zmq_mem_seq: {} > get_raw_seq: {}".format(zmq_mem_seq, get_raw_seq))
+ raise Exception(f"We somehow jumped mempool sequence numbers! zmq_mem_seq: {zmq_mem_seq} > get_raw_seq: {get_raw_seq}")
# 4) Moving forward, we apply the delta to our local view
# remaining txs(5) + 1 rbf(A+R) + 1 block connect + 1 final tx
@@ -520,7 +520,7 @@ class ZMQTest (BitcoinTestFramework):
assert mempool_sequence > expected_sequence
r_gap += mempool_sequence - expected_sequence
else:
- raise Exception("WARNING: txhash has unexpected mempool sequence value: {} vs expected {}".format(mempool_sequence, expected_sequence))
+ raise Exception(f"WARNING: txhash has unexpected mempool sequence value: {mempool_sequence} vs expected {expected_sequence}")
if label == "A":
assert hash_str not in mempool_view
mempool_view.add(hash_str)
diff --git a/test/functional/mining_basic.py b/test/functional/mining_basic.py
index 01fc02f27e..23711646a2 100755
--- a/test/functional/mining_basic.py
+++ b/test/functional/mining_basic.py
@@ -65,10 +65,10 @@ class MiningTest(BitcoinTestFramework):
assert_equal(mining_info['currentblockweight'], 4000)
self.log.info('test blockversion')
- self.restart_node(0, extra_args=['-mocktime={}'.format(t), '-blockversion=1337'])
+ self.restart_node(0, extra_args=[f'-mocktime={t}', '-blockversion=1337'])
self.connect_nodes(0, 1)
assert_equal(1337, self.nodes[0].getblocktemplate(NORMAL_GBT_REQUEST_PARAMS)['version'])
- self.restart_node(0, extra_args=['-mocktime={}'.format(t)])
+ self.restart_node(0, extra_args=[f'-mocktime={t}'])
self.connect_nodes(0, 1)
assert_equal(VERSIONBITS_TOP_BITS + (1 << VERSIONBITS_DEPLOYMENT_TESTDUMMY_BIT), self.nodes[0].getblocktemplate(NORMAL_GBT_REQUEST_PARAMS)['version'])
self.restart_node(0)
diff --git a/test/functional/p2p_addr_relay.py b/test/functional/p2p_addr_relay.py
index 113e1f9492..e93698b08e 100755
--- a/test/functional/p2p_addr_relay.py
+++ b/test/functional/p2p_addr_relay.py
@@ -311,7 +311,7 @@ class AddrTest(BitcoinTestFramework):
self.nodes[0].disconnect_p2ps()
- def send_addrs_and_test_rate_limiting(self, peer, no_relay, new_addrs, total_addrs):
+ 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))
@@ -329,27 +329,26 @@ class AddrTest(BitcoinTestFramework):
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":
+ for conn_type, no_relay in [("outbound-full-relay", False), ("block-relay-only", True), ("inbound", False)]:
+ self.log.info(f'Test rate limiting of addr processing for {conn_type} peers')
+ if conn_type == "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)
+ peer = self.nodes[0].add_outbound_p2p_connection(AddrReceiver(), p2p_idx=0, connection_type=conn_type)
# 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)
+ self.send_addrs_and_test_rate_limiting(peer, no_relay, new_addrs=600, total_addrs=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)
+ self.send_addrs_and_test_rate_limiting(peer, no_relay, new_addrs=600, total_addrs=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)
+ self.send_addrs_and_test_rate_limiting(peer, no_relay, new_addrs=10, total_addrs=1210)
# Advance the time by 100 seconds, permitting the processing of 10 more addresses.
# Send 200 and verify that 10 are processed.
@@ -357,7 +356,7 @@ class AddrTest(BitcoinTestFramework):
self.nodes[0].setmocktime(self.mocktime)
peer.increment_tokens(10)
- self.send_addrs_and_test_rate_limiting(peer, no_relay, 200, 1410)
+ self.send_addrs_and_test_rate_limiting(peer, no_relay, new_addrs=200, total_addrs=1410)
# Advance the time by 1000 seconds, permitting the processing of 100 more addresses.
# Send 200 and verify that 100 are processed.
@@ -365,9 +364,10 @@ class AddrTest(BitcoinTestFramework):
self.nodes[0].setmocktime(self.mocktime)
peer.increment_tokens(100)
- self.send_addrs_and_test_rate_limiting(peer, no_relay, 200, 1610)
+ self.send_addrs_and_test_rate_limiting(peer, no_relay, new_addrs=200, total_addrs=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
index 66ee1544a9..2a0f6432a9 100755
--- a/test/functional/p2p_addrfetch.py
+++ b/test/functional/p2p_addrfetch.py
@@ -21,18 +21,24 @@ ADDR.port = 18444
class P2PAddrFetch(BitcoinTestFramework):
-
def set_test_params(self):
self.setup_clean_chain = True
self.num_nodes = 1
+ def assert_getpeerinfo(self, *, peer_ids):
+ num_peers = len(peer_ids)
+ info = self.nodes[0].getpeerinfo()
+ assert_equal(len(info), num_peers)
+ for n in range(0, num_peers):
+ assert_equal(info[n]['id'], peer_ids[n])
+ assert_equal(info[n]['connection_type'], 'addr-fetch')
+
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')
+ peer_id = 0
+ peer = node.add_outbound_p2p_connection(P2PInterface(), p2p_idx=peer_id, connection_type="addr-fetch")
+ self.assert_getpeerinfo(peer_ids=[peer_id])
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()
@@ -45,7 +51,7 @@ class P2PAddrFetch(BitcoinTestFramework):
msg = msg_addr()
msg.addrs = [ADDR]
peer.send_and_ping(msg)
- assert_equal(len(node.getpeerinfo()), 1)
+ self.assert_getpeerinfo(peer_ids=[peer_id])
self.log.info("Check that answering with larger addr messages leads to disconnect")
msg.addrs = [ADDR] * 2
@@ -53,9 +59,20 @@ class P2PAddrFetch(BitcoinTestFramework):
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_id = 1
+ peer = node.add_outbound_p2p_connection(P2PInterface(), p2p_idx=peer_id, connection_type="addr-fetch")
+
+ time_now = int(time.time())
+ self.assert_getpeerinfo(peer_ids=[peer_id])
+
+ # Expect addr-fetch peer connection to be maintained up to 5 minutes.
+ node.setmocktime(time_now + 295)
+ self.assert_getpeerinfo(peer_ids=[peer_id])
+
+ # Expect addr-fetch peer connection to be disconnected after 5 minutes.
+ node.setmocktime(time_now + 301)
peer.wait_for_disconnect(timeout=5)
+ self.assert_getpeerinfo(peer_ids=[])
if __name__ == '__main__':
diff --git a/test/functional/rpc_fundrawtransaction.py b/test/functional/rpc_fundrawtransaction.py
index e29d0a73f2..2369ad25d5 100755
--- a/test/functional/rpc_fundrawtransaction.py
+++ b/test/functional/rpc_fundrawtransaction.py
@@ -99,6 +99,7 @@ class RawTransactionsTest(BitcoinTestFramework):
self.test_subtract_fee_with_presets()
self.test_transaction_too_large()
self.test_include_unsafe()
+ self.test_22670()
def test_change_position(self):
"""Ensure setting changePosition in fundraw with an exact match is handled properly."""
@@ -969,6 +970,62 @@ class RawTransactionsTest(BitcoinTestFramework):
signedtx = wallet.signrawtransactionwithwallet(fundedtx['hex'])
wallet.sendrawtransaction(signedtx['hex'])
+ def test_22670(self):
+ # In issue #22670, it was observed that ApproximateBestSubset may
+ # choose enough value to cover the target amount but not enough to cover the transaction fees.
+ # This leads to a transaction whose actual transaction feerate is lower than expected.
+ # However at normal feerates, the difference between the effective value and the real value
+ # that this bug is not detected because the transaction fee must be at least 0.01 BTC (the minimum change value).
+ # Otherwise the targeted minimum change value will be enough to cover the transaction fees that were not
+ # being accounted for. So the minimum relay fee is set to 0.1 BTC/kvB in this test.
+ self.log.info("Test issue 22670 ApproximateBestSubset bug")
+ # Make sure the default wallet will not be loaded when restarted with a high minrelaytxfee
+ self.nodes[0].unloadwallet(self.default_wallet_name, False)
+ feerate = Decimal("0.1")
+ self.restart_node(0, [f"-minrelaytxfee={feerate}", "-discardfee=0"]) # Set high minrelayfee, set discardfee to 0 for easier calculation
+
+ self.nodes[0].loadwallet(self.default_wallet_name, True)
+ funds = self.nodes[0].get_wallet_rpc(self.default_wallet_name)
+ self.nodes[0].createwallet(wallet_name="tester")
+ tester = self.nodes[0].get_wallet_rpc("tester")
+
+ # Because this test is specifically for ApproximateBestSubset, the target value must be greater
+ # than any single input available, and require more than 1 input. So we make 3 outputs
+ for i in range(0, 3):
+ funds.sendtoaddress(tester.getnewaddress(address_type="bech32"), 1)
+ self.nodes[0].generate(1)
+
+ # Create transactions in order to calculate fees for the target bounds that can trigger this bug
+ change_tx = tester.fundrawtransaction(tester.createrawtransaction([], [{funds.getnewaddress(): 1.5}]))
+ tx = tester.createrawtransaction([], [{funds.getnewaddress(): 2}])
+ no_change_tx = tester.fundrawtransaction(tx, {"subtractFeeFromOutputs": [0]})
+
+ overhead_fees = feerate * len(tx) / 2 / 1000
+ cost_of_change = change_tx["fee"] - no_change_tx["fee"]
+ fees = no_change_tx["fee"]
+ assert_greater_than(fees, 0.01)
+
+ def do_fund_send(target):
+ create_tx = tester.createrawtransaction([], [{funds.getnewaddress(): target}])
+ funded_tx = tester.fundrawtransaction(create_tx)
+ signed_tx = tester.signrawtransactionwithwallet(funded_tx["hex"])
+ assert signed_tx["complete"]
+ decoded_tx = tester.decoderawtransaction(signed_tx["hex"])
+ assert_equal(len(decoded_tx["vin"]), 3)
+ assert tester.testmempoolaccept([signed_tx["hex"]])[0]["allowed"]
+
+ # We want to choose more value than is available in 2 inputs when considering the fee,
+ # but not enough to need 3 inputs when not considering the fee.
+ # So the target value must be at least 2.00000001 - fee.
+ lower_bound = Decimal("2.00000001") - fees
+ # The target value must be at most 2 - cost_of_change - not_input_fees - min_change (these are all
+ # included in the target before ApproximateBestSubset).
+ upper_bound = Decimal("2.0") - cost_of_change - overhead_fees - Decimal("0.01")
+ assert_greater_than_or_equal(upper_bound, lower_bound)
+ do_fund_send(lower_bound)
+ do_fund_send(upper_bound)
+
+ self.restart_node(0)
if __name__ == '__main__':
RawTransactionsTest().main()
diff --git a/test/functional/wallet_backup.py b/test/functional/wallet_backup.py
index 05a0ef0ea1..c7a983556d 100755
--- a/test/functional/wallet_backup.py
+++ b/test/functional/wallet_backup.py
@@ -111,6 +111,18 @@ class WalletBackupTest(BitcoinTestFramework):
os.remove(os.path.join(self.nodes[1].datadir, self.chain, 'wallets', self.default_wallet_name, self.wallet_data_filename))
os.remove(os.path.join(self.nodes[2].datadir, self.chain, 'wallets', self.default_wallet_name, self.wallet_data_filename))
+ def restore_nonexistent_wallet(self):
+ node = self.nodes[3]
+ nonexistent_wallet_file = os.path.join(self.nodes[0].datadir, 'nonexistent_wallet.bak')
+ wallet_name = "res0"
+ assert_raises_rpc_error(-8, "Backup file does not exist", node.restorewallet, wallet_name, nonexistent_wallet_file)
+
+ def restore_wallet_existent_name(self):
+ node = self.nodes[3]
+ wallet_file = os.path.join(self.nodes[0].datadir, 'wallet.bak')
+ wallet_name = "res0"
+ assert_raises_rpc_error(-8, "Wallet name already exists.", node.restorewallet, wallet_name, wallet_file)
+
def init_three(self):
self.init_wallet(0)
self.init_wallet(1)
@@ -169,26 +181,27 @@ class WalletBackupTest(BitcoinTestFramework):
##
# Test restoring spender wallets from backups
##
- self.log.info("Restoring using wallet.dat")
- self.stop_three()
- self.erase_three()
+ self.log.info("Restoring wallets on node 3 using backup files")
- # Start node2 with no chain
- shutil.rmtree(os.path.join(self.nodes[2].datadir, self.chain, 'blocks'))
- shutil.rmtree(os.path.join(self.nodes[2].datadir, self.chain, 'chainstate'))
+ self.restore_nonexistent_wallet()
- # Restore wallets from backup
- shutil.copyfile(os.path.join(self.nodes[0].datadir, 'wallet.bak'), os.path.join(self.nodes[0].datadir, self.chain, 'wallets', self.default_wallet_name, self.wallet_data_filename))
- shutil.copyfile(os.path.join(self.nodes[1].datadir, 'wallet.bak'), os.path.join(self.nodes[1].datadir, self.chain, 'wallets', self.default_wallet_name, self.wallet_data_filename))
- shutil.copyfile(os.path.join(self.nodes[2].datadir, 'wallet.bak'), os.path.join(self.nodes[2].datadir, self.chain, 'wallets', self.default_wallet_name, self.wallet_data_filename))
+ backup_file_0 = os.path.join(self.nodes[0].datadir, 'wallet.bak')
+ backup_file_1 = os.path.join(self.nodes[1].datadir, 'wallet.bak')
+ backup_file_2 = os.path.join(self.nodes[2].datadir, 'wallet.bak')
- self.log.info("Re-starting nodes")
- self.start_three()
- self.sync_blocks()
+ self.nodes[3].restorewallet("res0", backup_file_0)
+ self.nodes[3].restorewallet("res1", backup_file_1)
+ self.nodes[3].restorewallet("res2", backup_file_2)
+
+ res0_rpc = self.nodes[3].get_wallet_rpc("res0")
+ res1_rpc = self.nodes[3].get_wallet_rpc("res1")
+ res2_rpc = self.nodes[3].get_wallet_rpc("res2")
+
+ assert_equal(res0_rpc.getbalance(), balance0)
+ assert_equal(res1_rpc.getbalance(), balance1)
+ assert_equal(res2_rpc.getbalance(), balance2)
- assert_equal(self.nodes[0].getbalance(), balance0)
- assert_equal(self.nodes[1].getbalance(), balance1)
- assert_equal(self.nodes[2].getbalance(), balance2)
+ self.restore_wallet_existent_name()
if not self.options.descriptors:
self.log.info("Restoring using dumped wallet")