diff --git a/.arclint b/.arclint
index 78e8d0869..f68f4c7f0 100644
--- a/.arclint
+++ b/.arclint
@@ -1,323 +1,323 @@
 {
     "linters": {
         "generated": {
             "type": "generated"
         },
         "clang-format": {
             "type": "clang-format",
             "version": ">=12.0",
             "bin": ["clang-format-12", "clang-format"],
             "include": "(^(src|chronik)/.*\\.(h|c|cpp|mm)$)",
             "exclude": [
                 "(^src/(secp256k1|univalue|leveldb)/)",
                 "(^src/bench/nanobench.h$)"
             ]
         },
         "autopep8": {
             "type": "autopep8",
             "version": ">=1.3.4",
             "include": "(\\.py$)",
             "exclude": [
                 "(^contrib/gitian-builder/)",
                 "(^contrib/apple-sdk-tools/)"
             ],
             "flags": [
                 "--aggressive",
                 "--ignore=W503,W504",
                 "--max-line-length=88"
             ]
         },
         "flake8": {
             "type": "flake8",
             "version": ">=5.0",
             "include": "(\\.py$)",
             "exclude": [
                 "(^contrib/gitian-builder/)",
                 "(^contrib/apple-sdk-tools/)"
             ],
             "flags": [
-                "--ignore=A001,A003,E303,E305,E501,E704,W503,W504",
+                "--ignore=A003,E303,E305,E501,E704,W503,W504",
                 "--require-plugins=flake8-comprehensions,flake8-builtins"
             ]
         },
         "lint-format-strings": {
             "type": "lint-format-strings",
             "include": "(^(src|chronik)/.*\\.(h|c|cpp)$)",
             "exclude": [
                 "(^src/(secp256k1|univalue|leveldb)/)",
                 "(^src/bench/nanobench.h$)",
                 "(^src/test/fuzz/strprintf.cpp$)"
             ]
         },
         "check-doc": {
             "type": "check-doc",
             "include": "(^(src|chronik)/.*\\.(h|c|cpp)$)"
         },
         "lint-tests": {
             "type": "lint-tests",
             "include": "(^src/(seeder/|rpc/|wallet/)?test/.*\\.(cpp)$)"
         },
         "phpcs": {
             "type": "phpcs",
             "include": "(\\.php$)",
             "exclude": [
                 "(^arcanist/__phutil_library_.+\\.php$)"
             ],
             "phpcs.standard": "arcanist/phpcs.xml"
         },
         "lint-locale-dependence": {
             "type": "lint-locale-dependence",
             "include": "(^(src|chronik)/.*\\.(h|cpp)$)",
             "exclude": [
                 "(^src/(crypto/ctaes/|leveldb/|secp256k1/|tinyformat.h|univalue/))",
                 "(^src/bench/nanobench.h$)"
             ]
         },
         "lint-cheader": {
             "type": "lint-cheader",
             "include": "(^(src|chronik)/.*\\.(h|cpp)$)",
             "exclude": [
                 "(^src/(crypto/ctaes|secp256k1|univalue|leveldb)/)",
                 "(^src/bench/nanobench.h$)"
             ]
         },
         "spelling": {
             "type": "spelling",
             "exclude": [
                 "(^build-aux/m4/)",
                 "(^depends/)",
                 "(^doc/release-notes/)",
                 "(^contrib/gitian-builder/)",
                 "(^src/(qt/locale|secp256k1|univalue|leveldb)/)",
                 "(^test/lint/dictionary/)",
                 "(package-lock.json)"
             ],
             "spelling.dictionaries": [
                 "test/lint/dictionary/english.json"
             ]
         },
         "lint-assert-with-side-effects": {
             "type": "lint-assert-with-side-effects",
             "include": "(^(src|chronik)/.*\\.(h|cpp)$)",
             "exclude": [
                 "(^src/(secp256k1|univalue|leveldb)/)",
                 "(^src/bench/nanobench.h$)"
             ]
         },
         "lint-include-quotes": {
             "type": "lint-include-quotes",
             "include": "(^(src|chronik)/.*\\.(h|cpp)$)",
             "exclude": [
                 "(^src/(secp256k1|univalue|leveldb)/)",
                 "(^src/bench/nanobench.h$)"
             ]
         },
         "lint-include-guard": {
             "type": "lint-include-guard",
             "include": "(^(src|chronik)/.*\\.h$)",
             "exclude": [
                 "(^src/(crypto/ctaes|secp256k1|univalue|leveldb)/)",
                 "(^src/bench/nanobench.h$)",
                 "(^src/tinyformat.h$)"
             ]
         },
         "lint-include-source": {
             "type": "lint-include-source",
             "include": "(^(src|chronik)/.*\\.(h|c|cpp)$)",
             "exclude": [
                 "(^src/(secp256k1|univalue|leveldb)/)",
                 "(^src/bench/nanobench.h$)"
             ]
         },
         "lint-std-chrono": {
             "type": "lint-std-chrono",
             "include": "(^(src|chronik)/.*\\.(h|cpp)$)"
         },
         "lint-stdint": {
             "type": "lint-stdint",
             "include": "(^(src|chronik)/.*\\.(h|c|cpp)$)",
             "exclude": [
                 "(^src/(secp256k1|univalue|leveldb)/)",
                 "(^src/bench/nanobench.h$)",
                 "(^src/compat/assumptions.h$)"
             ]
         },
         "lint-source-filename": {
             "type": "lint-source-filename",
             "include": "(^(src|chronik)/.*\\.(h|c|cpp)$)",
             "exclude": [
                 "(^src/(secp256k1|univalue|leveldb)/)",
                 "(^src/bench/nanobench.h$)"
             ]
         },
         "lint-boost-dependencies": {
             "type": "lint-boost-dependencies",
             "include": "(^(src|chronik)/.*\\.(h|cpp)$)"
         },
         "lint-python-encoding": {
             "type": "lint-python-encoding",
             "include": "(\\.py$)",
             "exclude": [
                 "(^contrib/gitian-builder/)",
                 "(^contrib/apple-sdk-tools/)"
             ]
         },
         "lint-python-shebang": {
             "type": "lint-python-shebang",
             "include": "(\\.py$)",
             "exclude": [
                 "(__init__\\.py$)",
                 "(^contrib/gitian-builder/)",
                 "(^contrib/apple-sdk-tools/)"
             ]
         },
         "lint-bash-shebang": {
             "type": "lint-bash-shebang",
             "include": "(\\.sh$)",
             "exclude": [
                 "(^contrib/gitian-builder/)"
             ]
         },
         "shellcheck": {
             "type": "shellcheck",
             "version": ">=0.7.0",
             "flags": [
                 "--external-sources",
                 "--source-path=SCRIPTDIR"
             ],
             "include": "(\\.sh$)",
             "exclude": [
                 "(^contrib/gitian-builder/)",
                 "(^src/(secp256k1|univalue)/)"
             ]
         },
         "lint-shell-locale": {
             "type": "lint-shell-locale",
             "include": "(\\.sh$)",
             "exclude": [
                 "(^contrib/gitian-builder/)",
                 "(^src/(secp256k1|univalue)/)",
                 "(^cmake/utils/log-and-print-on-failure.sh)"
             ]
         },
         "lint-cpp-void-parameters": {
             "type": "lint-cpp-void-parameters",
             "include": "(^(src|chronik)/.*\\.(h|cpp)$)",
             "exclude": [
                 "(^src/(crypto/ctaes|secp256k1|univalue|leveldb)/)",
                 "(^src/bench/nanobench.h$)",
                 "(^src/compat/glibc_compat.cpp$)"
             ]
         },
         "lint-logs": {
             "type": "lint-logs",
             "include": "(^(src|chronik)/.*\\.(h|cpp|rs)$)"
         },
         "lint-qt": {
             "type": "lint-qt",
             "include": "(^src/qt/.*\\.(h|cpp)$)",
             "exclude": [
                 "(^src/qt/(locale|forms|res)/)"
             ]
         },
         "lint-doxygen": {
             "type": "lint-doxygen",
             "include": "(^(src|chronik)/.*\\.(h|c|cpp)$)",
             "exclude": [
                 "(^src/(crypto/ctaes|secp256k1|univalue|leveldb)/)",
                 "(^src/bench/nanobench.h$)"
             ]
         },
         "lint-whitespace": {
             "type": "lint-whitespace",
             "include": "(\\.(ac|am|cmake|conf|in|include|json|m4|md|openrc|php|pl|rs|sh|txt|yml)$)",
             "exclude": [
                 "(^contrib/gitian-builder/)",
                 "(^src/(secp256k1|univalue|leveldb)/)",
                 "(^src/bench/nanobench.h$)"
             ]
         },
         "yamllint": {
             "type": "yamllint",
             "include": "(\\.(yml|yaml)$)",
             "exclude": "(^src/(secp256k1|univalue|leveldb)/)"
         },
         "lint-check-nonfatal": {
             "type": "lint-check-nonfatal",
             "include": [
                 "(^src/rpc/.*\\.(h|c|cpp)$)",
                 "(^src/wallet/rpc*.*\\.(h|c|cpp)$)"
             ],
             "exclude": "(^src/rpc/server.cpp)"
         },
         "lint-markdown": {
             "type": "lint-markdown",
             "include": [
                 "(\\.md$)"
             ],
             "exclude": "(^contrib/gitian-builder/)"
         },
         "lint-python-mypy": {
             "type": "lint-python-mypy",
             "version": ">=0.910",
             "include": "(\\.py$)",
             "exclude": [
                 "(^contrib/gitian-builder/)",
                 "(^contrib/apple-sdk-tools/)",
                 "(^contrib/macdeploy/)"
             ],
             "flags": [
                 "--ignore-missing-imports",
                 "--install-types",
                 "--non-interactive"
             ]
         },
         "lint-python-mutable-default": {
             "type": "lint-python-mutable-default",
             "include": "(\\.py$)",
             "exclude": [
                 "(^contrib/gitian-builder/)",
                 "(^contrib/apple-sdk-tools/)"
             ]
         },
         "prettier": {
             "type": "prettier",
             "version":">=2.4.1",
             "include": "(^web/.*\\.(css|html|js|json|jsx|md|scss|ts|tsx)$)",
             "exclude": "(^web/.*/translations/.*\\.json$)"
         },
         "lint-python-isort": {
             "type": "lint-python-isort",
             "version": ">=5.6.4",
             "include": "(\\.py$)",
             "exclude": [
                 "(^contrib/gitian-builder/)",
                 "(^contrib/apple-sdk-tools/)"
             ]
         },
         "rustfmt": {
             "type": "rustfmt",
             "version": ">=1.5.1",
             "include": "(\\.rs$)"
         },
         "eslint": {
             "type": "eslint",
             "version": ">=8.0.0",
             "include": [
                 "(cashtab/.*\\.js$)", 
                 "(apps/alias-server/.*\\.js$)", 
                 "(modules/ecashaddrjs/.*\\.js$)", 
                 "(apps/ecash-herald/.*\\.js$)"
             ]
         },
         "lint-python-flynt": {
             "type": "lint-python-flynt",
             "version": ">=0.78",
             "include": "(\\.py$)",
             "exclude": [
                 "(^contrib/gitian-builder/)",
                 "(^contrib/apple-sdk-tools/)"
             ]
         }
     }
 }
diff --git a/test/functional/abc_rpc_isfinal.py b/test/functional/abc_rpc_isfinal.py
index b3d6afebb..4e9fe63bf 100755
--- a/test/functional/abc_rpc_isfinal.py
+++ b/test/functional/abc_rpc_isfinal.py
@@ -1,200 +1,200 @@
 #!/usr/bin/env python3
 # Copyright (c) 2022 The Bitcoin developers
 # Distributed under the MIT software license, see the accompanying
 # file COPYING or http://www.opensource.org/licenses/mit-license.php.
 """Test the isfinalxxx RPCS."""
 import random
 
 from test_framework.address import ADDRESS_ECREG_UNSPENDABLE
 from test_framework.authproxy import JSONRPCException
 from test_framework.avatools import AvaP2PInterface, can_find_inv_in_poll
 from test_framework.blocktools import create_block, create_coinbase
 from test_framework.messages import CBlockHeader, msg_headers
 from test_framework.test_framework import BitcoinTestFramework
 from test_framework.util import assert_equal, assert_raises_rpc_error, uint256_hex
 
 QUORUM_NODE_COUNT = 16
 
 
 class AvalancheIsFinalTest(BitcoinTestFramework):
     def set_test_params(self):
         self.setup_clean_chain = True
         self.num_nodes = 1
         self.extra_args = [
             [
                 '-avaproofstakeutxodustthreshold=1000000',
                 '-avaproofstakeutxoconfirmations=1',
                 '-avacooldown=0',
                 '-avaminquorumstake=0',
                 '-avaminavaproofsnodecount=0',
             ]
         ]
 
     def run_test(self):
         node = self.nodes[0]
 
         tip = node.getbestblockhash()
 
         assert_raises_rpc_error(
             -1,
             "Avalanche is not ready to poll yet.",
             self.nodes[0].isfinalblock,
             tip,
         )
         assert_raises_rpc_error(
             -1,
             "Avalanche is not ready to poll yet.",
             self.nodes[0].isfinaltransaction,
             node.getblock(tip)['tx'][0],
             tip,
         )
 
         # Build a fake quorum of nodes.
         def get_quorum():
             return [node.add_p2p_connection(AvaP2PInterface(self, node))
                     for _ in range(0, QUORUM_NODE_COUNT)]
 
         # Pick one node from the quorum for polling.
         quorum = get_quorum()
 
         def is_quorum_established():
             return node.getavalancheinfo()['ready_to_poll'] is True
         self.wait_until(is_quorum_established)
 
         blockhash = self.generate(node, 1, sync_fun=self.no_op)[0]
         cb_txid = node.getblock(blockhash)['tx'][0]
         assert not node.isfinalblock(blockhash)
         assert not node.isfinaltransaction(cb_txid, blockhash)
 
         def is_finalblock(blockhash):
             can_find_inv_in_poll(quorum, int(blockhash, 16))
             return node.isfinalblock(blockhash)
 
         with node.assert_debug_log([f"Avalanche finalized block {blockhash}"]):
             self.wait_until(lambda: is_finalblock(blockhash))
         assert node.isfinaltransaction(cb_txid, blockhash)
 
         self.log.info("Check block ancestors are finalized as well")
         tip_height = node.getblockheader(blockhash)['height']
         for height in range(0, tip_height):
-            hash = node.getblockhash(height)
-            assert node.isfinalblock(hash)
-            txid = node.getblock(hash)['tx'][0]
-            assert node.isfinaltransaction(txid, hash)
+            blockhash = node.getblockhash(height)
+            assert node.isfinalblock(blockhash)
+            txid = node.getblock(blockhash)['tx'][0]
+            assert node.isfinaltransaction(txid, blockhash)
 
         if self.is_wallet_compiled():
             self.log.info("Check mempool transactions are not finalized")
             # Mature some utxos
             tip = self.generate(node, 100, sync_fun=self.no_op)[-1]
             wallet_txid = node.sendtoaddress(
                 ADDRESS_ECREG_UNSPENDABLE, 1_000_000)
             assert wallet_txid in node.getrawmempool()
             assert_raises_rpc_error(
                 -5,
                 "No such transaction found in the provided block.",
                 node.isfinaltransaction,
                 wallet_txid,
                 tip,
             )
 
             self.log.info(
                 "A transaction is only finalized if the containing block is finalized")
             tip = self.generate(node, 1, sync_fun=self.no_op)[0]
             assert wallet_txid not in node.getrawmempool()
             assert not node.isfinaltransaction(wallet_txid, tip)
             self.wait_until(lambda: is_finalblock(tip))
             assert node.isfinaltransaction(wallet_txid, tip)
 
             # Needs -txindex
             assert_raises_rpc_error(
                 -5,
                 "No such transaction. Use -txindex or provide a block hash to enable blockchain transaction queries.",
                 node.isfinaltransaction,
                 wallet_txid,
             )
 
             self.log.info(
                 "Repeat with -txindex so we don't need the blockhash")
             self.restart_node(0, self.extra_args[0] + ['-txindex'])
             quorum = get_quorum()
             self.wait_until(is_quorum_established)
 
             # Try to raise a -txindex not synced yet error. This is not
             # guaranteed because syncing is fast!
             try:
                 node.isfinaltransaction(
                     uint256_hex(random.randint(0, 2**256 - 1)),
                 )
             except JSONRPCException as e:
                 assert_equal(e.error['code'], -5)
 
                 if e.error['message'] == "No such mempool or blockchain transaction.":
                     # If we got a regular  "not found" error, the txindex should
                     # have synced.
                     assert node.getindexinfo()['txindex']['synced'] is True
                 else:
                     # Otherwise we might have successfully raised before the
                     # indexer completed. Checking the status now is useless as
                     # the indexer might have completed the synchronization in
                     # the meantime and the status is no longer relevant.
                     assert e.error['message'] == "No such transaction. Blockchain transactions are still in the process of being indexed."
             else:
                 assert False, "The isfinaltransaction RPC call did not throw as expected."
 
             self.wait_until(lambda: node.getindexinfo()[
                             'txindex']['synced'] is True)
 
             self.wait_until(lambda: is_finalblock(tip))
             assert node.isfinaltransaction(wallet_txid)
 
             wallet_txid = node.sendtoaddress(
                 ADDRESS_ECREG_UNSPENDABLE, 1_000_000)
             assert wallet_txid in node.getrawmempool()
             assert not node.isfinaltransaction(wallet_txid)
 
             assert_raises_rpc_error(
                 -5,
                 "No such mempool or blockchain transaction.",
                 node.isfinaltransaction,
                 uint256_hex(random.randint(0, 2**256 - 1)),
             )
 
         self.log.info("Check unknown item")
         for _ in range(10):
             assert_raises_rpc_error(
                 -8,
                 "Block not found",
                 node.isfinalblock,
                 uint256_hex(random.randint(0, 2**256 - 1)),
             )
             assert_raises_rpc_error(
                 -8,
                 "Block not found",
                 node.isfinaltransaction,
                 uint256_hex(random.randint(0, 2**256 - 1)),
                 uint256_hex(random.randint(0, 2**256 - 1)),
             )
 
         tip = node.getbestblockhash()
         height = node.getblockcount() + 1
         time = node.getblock(tip)['time'] + 1
         block = create_block(int(tip, 16), create_coinbase(height), time)
         block.solve()
 
         peer = node.add_p2p_connection(AvaP2PInterface())
         msg = msg_headers()
         msg.headers = [CBlockHeader(block)]
         peer.send_message(msg)
 
         self.wait_until(lambda: node.getchaintips()[0]['height'] == height)
         assert_raises_rpc_error(
             -1,
             "Block data not downloaded yet.",
             node.isfinaltransaction,
             uint256_hex(random.randint(0, 2**256 - 1)),
             uint256_hex(block.sha256),
         )
 
 
 if __name__ == '__main__':
     AvalancheIsFinalTest().main()
diff --git a/test/functional/p2p_add_connections.py b/test/functional/p2p_add_connections.py
index 49cb87678..3da8951bc 100755
--- a/test/functional/p2p_add_connections.py
+++ b/test/functional/p2p_add_connections.py
@@ -1,224 +1,224 @@
 #!/usr/bin/env python3
 # Copyright (c) 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 add_outbound_p2p_connection test framework functionality"""
 
 import random
 
 from test_framework.messages import NODE_AVALANCHE, NODE_NETWORK
 from test_framework.p2p import P2PInterface
 from test_framework.test_framework import BitcoinTestFramework
 from test_framework.util import assert_equal, check_node_connections
 
 # From net.h
 MAX_OUTBOUND_FULL_RELAY_CONNECTIONS = 16
 MAX_BLOCK_RELAY_ONLY_CONNECTIONS = 2
 
 # Override DEFAULT_MAX_AVALANCHE_OUTBOUND_CONNECTIONS with
 # -maxavalancheoutbound
 MAX_AVALANCHE_OUTBOUND_CONNECTIONS = 12
 
 
 class P2PFeelerReceiver(P2PInterface):
     def on_version(self, message):
         # The bitcoind node closes feeler connections as soon as a version
         # message is received from the test framework. Don't send any responses
         # to the node's version message since the connection will already be
         # closed.
         pass
 
 
 class P2PAddConnections(BitcoinTestFramework):
     def set_test_params(self):
         self.num_nodes = 2
         self.extra_args = [
             [
                 "-avaproofstakeutxoconfirmations=1",
                 f"-maxavalancheoutbound={MAX_AVALANCHE_OUTBOUND_CONNECTIONS}"
             ],
             []
         ]
 
     def setup_network(self):
         self.setup_nodes()
         # Don't connect the nodes
 
     def add_outbounds(self, node, quantity, conn_type):
         services = NODE_NETWORK
         if conn_type == "avalanche":
             services |= NODE_AVALANCHE
 
         for _ in range(quantity):
             self.log.debug(
                 f"Node {node.index}, {conn_type}: {self.p2p_idx[node.index]}")
             node.add_outbound_p2p_connection(
                 P2PInterface(),
                 p2p_idx=self.p2p_idx[node.index],
                 connection_type=conn_type,
                 services=services,
             )
             self.p2p_idx[node.index] += 1
 
     def simple_test(self):
         self.log.info(
             "Connect to various outbound peers in a predetermined way")
         self.p2p_idx = [0] * self.num_nodes
 
         self.log.info(
             f"Add {MAX_OUTBOUND_FULL_RELAY_CONNECTIONS} outbounds to node 0")
         self.add_outbounds(
             self.nodes[0],
             MAX_OUTBOUND_FULL_RELAY_CONNECTIONS,
             "outbound-full-relay")
 
         self.log.info(
             f"Add {MAX_BLOCK_RELAY_ONLY_CONNECTIONS} block-relay-only connections to node 0")
         self.add_outbounds(
             self.nodes[0],
             MAX_BLOCK_RELAY_ONLY_CONNECTIONS,
             "block-relay-only")
 
         self.log.info(
             f"Add {MAX_BLOCK_RELAY_ONLY_CONNECTIONS} block-relay-only connections to node 1")
         self.add_outbounds(
             self.nodes[1],
             MAX_BLOCK_RELAY_ONLY_CONNECTIONS,
             "block-relay-only")
 
         self.log.info("Add 5 inbound connections to node 1")
         for i in range(5):
             self.log.info(f"inbound: {i}")
             self.nodes[1].add_p2p_connection(P2PInterface())
 
         self.log.info("Add 4 outbounds to node 1")
         self.add_outbounds(self.nodes[1], 4, "outbound-full-relay")
 
         self.log.info("Check the connections opened as expected")
         check_node_connections(
             node=self.nodes[0],
             num_in=0,
             num_out=MAX_OUTBOUND_FULL_RELAY_CONNECTIONS + MAX_BLOCK_RELAY_ONLY_CONNECTIONS)
         check_node_connections(
             node=self.nodes[1],
             num_in=5,
             num_out=4 + MAX_BLOCK_RELAY_ONLY_CONNECTIONS)
 
         self.log.info("Disconnect p2p connections & try to re-open")
         self.nodes[0].disconnect_p2ps()
         self.p2p_idx[0] = 0
         check_node_connections(node=self.nodes[0], num_in=0, num_out=0)
 
         self.log.info(
             f"Add {MAX_OUTBOUND_FULL_RELAY_CONNECTIONS} outbounds to node 0")
         self.add_outbounds(
             self.nodes[0],
             MAX_OUTBOUND_FULL_RELAY_CONNECTIONS,
             "outbound-full-relay")
         check_node_connections(
             node=self.nodes[0],
             num_in=0,
             num_out=MAX_OUTBOUND_FULL_RELAY_CONNECTIONS)
 
         self.log.info(
             f"Add {MAX_BLOCK_RELAY_ONLY_CONNECTIONS} block-relay-only connections to node 0")
         self.add_outbounds(
             self.nodes[0],
             MAX_BLOCK_RELAY_ONLY_CONNECTIONS,
             "block-relay-only")
         check_node_connections(
             node=self.nodes[0],
             num_in=0,
             num_out=MAX_OUTBOUND_FULL_RELAY_CONNECTIONS + MAX_BLOCK_RELAY_ONLY_CONNECTIONS)
 
         self.log.info("Restart node 0 and try to reconnect to p2ps")
         self.restart_node(0)
         self.p2p_idx[0] = 0
 
         self.log.info(
             f"Add {MAX_OUTBOUND_FULL_RELAY_CONNECTIONS} outbounds to node 0")
         self.add_outbounds(
             self.nodes[0],
             MAX_OUTBOUND_FULL_RELAY_CONNECTIONS,
             "outbound-full-relay")
         check_node_connections(
             node=self.nodes[0],
             num_in=0,
             num_out=MAX_OUTBOUND_FULL_RELAY_CONNECTIONS)
 
         self.log.info(
             f"Add {MAX_BLOCK_RELAY_ONLY_CONNECTIONS} block-relay-only connections to node 0")
         self.add_outbounds(
             self.nodes[0],
             MAX_BLOCK_RELAY_ONLY_CONNECTIONS,
             "block-relay-only")
         check_node_connections(
             node=self.nodes[0],
             num_in=0,
             num_out=MAX_OUTBOUND_FULL_RELAY_CONNECTIONS + MAX_BLOCK_RELAY_ONLY_CONNECTIONS)
 
         check_node_connections(
             node=self.nodes[1],
             num_in=5,
             num_out=4 + MAX_BLOCK_RELAY_ONLY_CONNECTIONS)
 
         self.log.info("Add 1 feeler connection to node 0")
         feeler_conn = self.nodes[0].add_outbound_p2p_connection(
             P2PFeelerReceiver(), p2p_idx=self.p2p_idx[0], connection_type="feeler")
 
         # Feeler connection is closed
         assert not feeler_conn.is_connected
 
         # Verify version message received
         assert_equal(feeler_conn.message_count["version"], 1)
         # Feeler connections do not request tx relay
         assert_equal(feeler_conn.last_message["version"].relay, 0)
 
         self.log.info("Connecting avalanche outbounds")
         self.add_outbounds(
             self.nodes[0],
             MAX_AVALANCHE_OUTBOUND_CONNECTIONS,
             "avalanche")
         check_node_connections(
             node=self.nodes[0],
             num_in=0,
             num_out=MAX_OUTBOUND_FULL_RELAY_CONNECTIONS +
             MAX_BLOCK_RELAY_ONLY_CONNECTIONS +
             MAX_AVALANCHE_OUTBOUND_CONNECTIONS)
 
     def random_test(self):
         for node in self.nodes:
             node.disconnect_p2ps()
         self.p2p_idx = [0] * self.num_nodes
 
         remaining_outbounds = {
             "outbound-full-relay": MAX_OUTBOUND_FULL_RELAY_CONNECTIONS,
             "block-relay-only": MAX_BLOCK_RELAY_ONLY_CONNECTIONS,
             "avalanche": MAX_AVALANCHE_OUTBOUND_CONNECTIONS,
         }
         max_outbounds = sum(remaining_outbounds.values())
 
         iterations = random.randint(1, 5 * max_outbounds)
         self.log.info(
             f"Randomly insert outbounds of various types {iterations} times")
 
         for _ in range(iterations):
-            type = random.choice(list(remaining_outbounds))
-            if remaining_outbounds[type] <= 0:
+            conn_type = random.choice(list(remaining_outbounds))
+            if remaining_outbounds[conn_type] <= 0:
                 continue
 
-            self.add_outbounds(self.nodes[0], 1, type)
-            remaining_outbounds[type] -= 1
+            self.add_outbounds(self.nodes[0], 1, conn_type)
+            remaining_outbounds[conn_type] -= 1
 
         check_node_connections(
             node=self.nodes[0],
             num_in=0,
             num_out=max_outbounds - sum(remaining_outbounds.values()))
 
     def run_test(self):
         self.simple_test()
         self.random_test()
 
 
 if __name__ == '__main__':
     P2PAddConnections().main()
diff --git a/test/functional/rpc_rawtransaction.py b/test/functional/rpc_rawtransaction.py
index 3875eeb58..332f192b1 100755
--- a/test/functional/rpc_rawtransaction.py
+++ b/test/functional/rpc_rawtransaction.py
@@ -1,726 +1,726 @@
 #!/usr/bin/env python3
 # Copyright (c) 2014-2019 The Bitcoin Core developers
 # Distributed under the MIT software license, see the accompanying
 # file COPYING or http://www.opensource.org/licenses/mit-license.php.
 """Test the rawtranscation RPCs.
 
 Test the following RPCs:
    - createrawtransaction
    - signrawtransactionwithwallet
    - sendrawtransaction
    - decoderawtransaction
    - getrawtransaction
 """
 
 from collections import OrderedDict
 from decimal import Decimal
 from io import BytesIO
 
 from test_framework.messages import COutPoint, CTransaction, CTxIn, CTxOut, ToHex
 from test_framework.script import CScript
 from test_framework.test_framework import BitcoinTestFramework
 from test_framework.txtools import pad_raw_tx
 from test_framework.util import (
     assert_equal,
     assert_greater_than,
     assert_raises_rpc_error,
     find_vout_for_address,
 )
 
 
 class multidict(dict):
     """Dictionary that allows duplicate keys.
     Constructed with a list of (key, value) tuples. When dumped by the json module,
     will output invalid json with repeated keys, eg:
     >>> json.dumps(multidict([(1,2),(1,2)])
     '{"1": 2, "1": 2}'
     Used to test calls to rpc methods with repeated keys in the json object."""
 
     def __init__(self, x):
         dict.__init__(self, x)
         self.x = x
 
     def items(self):
         return self.x
 
 
 # Create one-input, one-output, no-fee transaction:
 class RawTransactionsTest(BitcoinTestFramework):
     def set_test_params(self):
         self.setup_clean_chain = True
         self.num_nodes = 3
         self.extra_args = [["-txindex"], ["-txindex"], ["-txindex"]]
         # whitelist all peers to speed up tx relay / mempool sync
         for args in self.extra_args:
             args.append("-whitelist=noban@127.0.0.1")
 
         self.supports_cli = False
 
     def skip_test_if_missing_module(self):
         self.skip_if_no_wallet()
 
     def setup_network(self):
         super().setup_network()
         self.connect_nodes(0, 2)
 
     def run_test(self):
         self.log.info(
             'prepare some coins for multiple *rawtransaction commands')
         self.generate(self.nodes[2], 1)
         self.generate(self.nodes[0], 101)
         self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 1500000)
         self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 1000000)
         self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 5000000)
         self.sync_all()
         self.generate(self.nodes[0], 5)
 
         self.log.info(
             'Test getrawtransaction on genesis block coinbase returns an error')
         block = self.nodes[0].getblock(self.nodes[0].getblockhash(0))
         assert_raises_rpc_error(-5, "The genesis block coinbase is not considered an ordinary transaction",
                                 self.nodes[0].getrawtransaction, block['merkleroot'])
 
         self.log.info(
             'Check parameter types and required parameters of createrawtransaction')
         # Test `createrawtransaction` required parameters
         assert_raises_rpc_error(-1, "createrawtransaction",
                                 self.nodes[0].createrawtransaction)
         assert_raises_rpc_error(-1, "createrawtransaction",
                                 self.nodes[0].createrawtransaction, [])
 
         # Test `createrawtransaction` invalid extra parameters
         assert_raises_rpc_error(-1, "createrawtransaction",
                                 self.nodes[0].createrawtransaction, [], {}, 0, 'foo')
 
         # Test `createrawtransaction` invalid `inputs`
         txid = '1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000'
         assert_raises_rpc_error(-3, "Expected type array",
                                 self.nodes[0].createrawtransaction, 'foo', {})
         assert_raises_rpc_error(-1, "JSON value is not an object as expected",
                                 self.nodes[0].createrawtransaction, ['foo'], {})
         assert_raises_rpc_error(-1,
                                 "JSON value is not a string as expected",
                                 self.nodes[0].createrawtransaction,
                                 [{}],
                                 {})
         assert_raises_rpc_error(-8,
                                 "txid must be of length 64 (not 3, for 'foo')",
                                 self.nodes[0].createrawtransaction,
                                 [{'txid': 'foo'}],
                                 {})
         assert_raises_rpc_error(-8,
                                 "txid must be hexadecimal string (not 'ZZZ7bb8b1697ea987f3b223ba7819250cae33efacb068d23dc24859824a77844')",
                                 self.nodes[0].createrawtransaction,
                                 [{'txid': 'ZZZ7bb8b1697ea987f3b223ba7819250cae33efacb068d23dc24859824a77844'}],
                                 {})
         assert_raises_rpc_error(-8, "Invalid parameter, missing vout key",
                                 self.nodes[0].createrawtransaction, [{'txid': txid}], {})
         assert_raises_rpc_error(-8, "Invalid parameter, vout must be a number",
                                 self.nodes[0].createrawtransaction, [{'txid': txid, 'vout': 'foo'}], {})
         assert_raises_rpc_error(-8, "Invalid parameter, vout cannot be negative",
                                 self.nodes[0].createrawtransaction, [{'txid': txid, 'vout': -1}], {})
         assert_raises_rpc_error(-8, "Invalid parameter, sequence number is out of range",
                                 self.nodes[0].createrawtransaction, [{'txid': txid, 'vout': 0, 'sequence': -1}], {})
 
         # Test `createrawtransaction` invalid `outputs`
         address = self.nodes[0].getnewaddress()
         address2 = self.nodes[0].getnewaddress()
         assert_raises_rpc_error(-1, "JSON value is not an array as expected",
                                 self.nodes[0].createrawtransaction, [], 'foo')
         # Should not throw for backwards compatibility
         self.nodes[0].createrawtransaction(inputs=[], outputs={})
         self.nodes[0].createrawtransaction(inputs=[], outputs=[])
         assert_raises_rpc_error(-8, "Data must be hexadecimal string",
                                 self.nodes[0].createrawtransaction, [], {'data': 'foo'})
         assert_raises_rpc_error(-5, "Invalid Bitcoin address",
                                 self.nodes[0].createrawtransaction, [], {'foo': 0})
         assert_raises_rpc_error(-3, "Invalid amount",
                                 self.nodes[0].createrawtransaction, [], {address: 'foo'})
         assert_raises_rpc_error(-3, "Amount out of range",
                                 self.nodes[0].createrawtransaction, [], {address: -1})
         assert_raises_rpc_error(-8, f"Invalid parameter, duplicated address: {address}",
                                 self.nodes[0].createrawtransaction, [],
                                 multidict([(address, 1), (address, 1)]))
         assert_raises_rpc_error(-8, f"Invalid parameter, duplicated address: {address}",
                                 self.nodes[0].createrawtransaction, [],
                                 [{address: 1}, {address: 1}])
         assert_raises_rpc_error(-8,
                                 "Invalid parameter, duplicate key: data",
                                 self.nodes[0].createrawtransaction,
                                 [],
                                 [{"data": 'aa'},
                                     {"data": "bb"}])
         assert_raises_rpc_error(-8,
                                 "Invalid parameter, duplicate key: data",
                                 self.nodes[0].createrawtransaction,
                                 [],
                                 multidict([("data",
                                             'aa'),
                                            ("data",
                                             "bb")]))
         assert_raises_rpc_error(-8, "Invalid parameter, key-value pair must contain exactly one key",
                                 self.nodes[0].createrawtransaction, [], [{'a': 1, 'b': 2}])
         assert_raises_rpc_error(-8, "Invalid parameter, key-value pair not an object as expected",
                                 self.nodes[0].createrawtransaction, [], [['key-value pair1'], ['2']])
 
         # Test `createrawtransaction` invalid `locktime`
         assert_raises_rpc_error(-3, "Expected type number",
                                 self.nodes[0].createrawtransaction, [], {}, 'foo')
         assert_raises_rpc_error(-8, "Invalid parameter, locktime out of range",
                                 self.nodes[0].createrawtransaction, [], {}, -1)
         assert_raises_rpc_error(-8, "Invalid parameter, locktime out of range",
                                 self.nodes[0].createrawtransaction, [], {}, 4294967296)
 
         self.log.info(
             'Check that createrawtransaction accepts an array and object as outputs')
         tx = CTransaction()
         # One output
         tx.deserialize(BytesIO(bytes.fromhex(self.nodes[2].createrawtransaction(
             inputs=[{'txid': txid, 'vout': 9}], outputs={address: 99}))))
         assert_equal(len(tx.vout), 1)
         assert_equal(
             tx.serialize().hex(),
             self.nodes[2].createrawtransaction(
                 inputs=[{'txid': txid, 'vout': 9}], outputs=[{address: 99}]),
         )
         # Two outputs
         tx.deserialize(BytesIO(bytes.fromhex(self.nodes[2].createrawtransaction(inputs=[
                        {'txid': txid, 'vout': 9}], outputs=OrderedDict([(address, 99), (address2, 99)])))))
         assert_equal(len(tx.vout), 2)
         assert_equal(
             tx.serialize().hex(),
             self.nodes[2].createrawtransaction(inputs=[{'txid': txid, 'vout': 9}], outputs=[
                                                {address: 99}, {address2: 99}]),
         )
         # Multiple mixed outputs
         tx.deserialize(BytesIO(bytes.fromhex(self.nodes[2].createrawtransaction(inputs=[
                        {'txid': txid, 'vout': 9}], outputs=multidict([(address, 99), (address2, 99), ('data', '99')])))))
         assert_equal(len(tx.vout), 3)
         assert_equal(
             tx.serialize().hex(),
             self.nodes[2].createrawtransaction(inputs=[{'txid': txid, 'vout': 9}], outputs=[
                                                {address: 99}, {address2: 99}, {'data': '99'}]),
         )
 
-        for type in ["legacy"]:
-            addr = self.nodes[0].getnewaddress("", type)
+        for addr_type in ["legacy"]:
+            addr = self.nodes[0].getnewaddress("", addr_type)
             addrinfo = self.nodes[0].getaddressinfo(addr)
             pubkey = addrinfo["scriptPubKey"]
 
             self.log.info(
-                f'sendrawtransaction with missing prevtx info ({type})')
+                f'sendrawtransaction with missing prevtx info ({addr_type})')
 
             # Test `signrawtransactionwithwallet` invalid `prevtxs`
             inputs = [{'txid': txid, 'vout': 3, 'sequence': 1000}]
             outputs = {self.nodes[0].getnewaddress(): 1}
             rawtx = self.nodes[0].createrawtransaction(inputs, outputs)
 
             prevtx = {"txid": txid, "scriptPubKey": pubkey, "vout": 3, "amount": 1}
             succ = self.nodes[0].signrawtransactionwithwallet(rawtx, [prevtx])
             assert succ["complete"]
 
             assert_raises_rpc_error(-8, "Missing amount", self.nodes[0].signrawtransactionwithwallet, rawtx, [
                 {
                     "txid": txid,
                     "scriptPubKey": pubkey,
                     "vout": 3,
                 }
             ])
 
             assert_raises_rpc_error(-3, "Missing vout", self.nodes[0].signrawtransactionwithwallet, rawtx, [
                 {
                     "txid": txid,
                     "scriptPubKey": pubkey,
                     "amount": 1,
                 }
             ])
             assert_raises_rpc_error(-3, "Missing txid", self.nodes[0].signrawtransactionwithwallet, rawtx, [
                 {
                     "scriptPubKey": pubkey,
                     "vout": 3,
                     "amount": 1,
                 }
             ])
             assert_raises_rpc_error(-3, "Missing scriptPubKey", self.nodes[0].signrawtransactionwithwallet, rawtx, [
                 {
                     "txid": txid,
                     "vout": 3,
                     "amount": 1
                 }
             ])
 
         #########################################
         # sendrawtransaction with missing input #
         #########################################
 
         self.log.info('sendrawtransaction with missing input')
         # won't exists
         inputs = [
             {'txid': "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout': 1}]
         outputs = {self.nodes[0].getnewaddress(): 4998000}
         rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
         rawtx = pad_raw_tx(rawtx)
         rawtx = self.nodes[2].signrawtransactionwithwallet(rawtx)
 
         # This will raise an exception since there are missing inputs
         assert_raises_rpc_error(-25,
                                 "bad-txns-inputs-missingorspent",
                                 self.nodes[2].sendrawtransaction,
                                 rawtx['hex'])
 
         #####################################
         # getrawtransaction with block hash #
         #####################################
 
         # make a tx by sending then generate 2 blocks; block1 has the tx in it
         tx = self.nodes[2].sendtoaddress(
             self.nodes[1].getnewaddress(), 1000000)
         block1, block2 = self.generate(self.nodes[2], 2)
         self.sync_all()
         # We should be able to get the raw transaction by providing the correct
         # block
         gottx = self.nodes[0].getrawtransaction(tx, True, block1)
         assert_equal(gottx['txid'], tx)
         assert_equal(gottx['in_active_chain'], True)
         # We should not have the 'in_active_chain' flag when we don't provide a
         # block
         gottx = self.nodes[0].getrawtransaction(tx, True)
         assert_equal(gottx['txid'], tx)
         assert 'in_active_chain' not in gottx
         # We should not get the tx if we provide an unrelated block
         assert_raises_rpc_error(-5, "No such transaction found",
                                 self.nodes[0].getrawtransaction, tx, True, block2)
         # An invalid block hash should raise the correct errors
         assert_raises_rpc_error(-1,
                                 "JSON value is not a string as expected",
                                 self.nodes[0].getrawtransaction,
                                 tx,
                                 True,
                                 True)
         assert_raises_rpc_error(-8,
                                 "parameter 3 must be of length 64 (not 6, for 'foobar')",
                                 self.nodes[0].getrawtransaction,
                                 tx,
                                 True,
                                 "foobar")
         assert_raises_rpc_error(-8,
                                 "parameter 3 must be of length 64 (not 8, for 'abcd1234')",
                                 self.nodes[0].getrawtransaction,
                                 tx,
                                 True,
                                 "abcd1234")
         assert_raises_rpc_error(
             -8,
             "parameter 3 must be hexadecimal string (not 'ZZZ0000000000000000000000000000000000000000000000000000000000000')",
             self.nodes[0].getrawtransaction,
             tx,
             True,
             "ZZZ0000000000000000000000000000000000000000000000000000000000000")
         assert_raises_rpc_error(-5, "Block hash not found", self.nodes[0].getrawtransaction,
                                 tx, True, "0000000000000000000000000000000000000000000000000000000000000000")
         # Undo the blocks and check in_active_chain
         self.nodes[0].invalidateblock(block1)
         gottx = self.nodes[0].getrawtransaction(
             txid=tx, verbose=True, blockhash=block1)
         assert_equal(gottx['in_active_chain'], False)
         self.nodes[0].reconsiderblock(block1)
         assert_equal(self.nodes[0].getbestblockhash(), block2)
 
         if not self.options.descriptors:
             # The traditional multisig workflow does not work with descriptor
             # wallets so these are legacy only.
             # The multisig workflow with descriptor wallets uses PSBTs and is
             # tested elsewhere, no need to do them here.
             #
             # RAW TX MULTISIG TESTS #
             #
             # 2of2 test
             addr1 = self.nodes[2].getnewaddress()
             addr2 = self.nodes[2].getnewaddress()
 
             addr1Obj = self.nodes[2].getaddressinfo(addr1)
             addr2Obj = self.nodes[2].getaddressinfo(addr2)
 
             # Tests for createmultisig and addmultisigaddress
             assert_raises_rpc_error(-5, "Invalid public key",
                                     self.nodes[0].createmultisig, 1,
                                     ["01020304"])
             # createmultisig can only take public keys
             self.nodes[0].createmultisig(
                 2, [addr1Obj['pubkey'], addr2Obj['pubkey']])
             # addmultisigaddress can take both pubkeys and addresses so long as
             # they are in the wallet, which is tested here.
             assert_raises_rpc_error(-5, "Invalid public key",
                                     self.nodes[0].createmultisig, 2,
                                     [addr1Obj['pubkey'], addr1])
 
             mSigObj = self.nodes[2].addmultisigaddress(
                 2, [addr1Obj['pubkey'], addr1])['address']
 
             # use balance deltas instead of absolute values
             bal = self.nodes[2].getbalance()
 
             # send 1,200,000 XEC to msig adr
             txId = self.nodes[0].sendtoaddress(mSigObj, 1200000)
             self.sync_all()
             self.generate(self.nodes[0], 1)
             self.sync_all()
             # node2 has both keys of the 2of2 ms addr., tx should affect the
             # balance
             assert_equal(self.nodes[2].getbalance(),
                          bal + Decimal('1200000.00'))
 
             # 2of3 test from different nodes
             bal = self.nodes[2].getbalance()
             addr1 = self.nodes[1].getnewaddress()
             addr2 = self.nodes[2].getnewaddress()
             addr3 = self.nodes[2].getnewaddress()
 
             addr1Obj = self.nodes[1].getaddressinfo(addr1)
             addr2Obj = self.nodes[2].getaddressinfo(addr2)
             addr3Obj = self.nodes[2].getaddressinfo(addr3)
 
             mSigObj = self.nodes[2].addmultisigaddress(
                 2, [addr1Obj['pubkey'], addr2Obj['pubkey'], addr3Obj['pubkey']]
             )['address']
 
             txId = self.nodes[0].sendtoaddress(mSigObj, 2200000)
             decTx = self.nodes[0].gettransaction(txId)
             rawTx = self.nodes[0].decoderawtransaction(decTx['hex'])
             self.sync_all()
             self.generate(self.nodes[0], 1)
             self.sync_all()
 
             # THIS IS AN INCOMPLETE FEATURE
             # NODE2 HAS TWO OF THREE KEY AND THE FUNDS SHOULD BE SPENDABLE AND
             # COUNT AT BALANCE CALCULATION
             # for now, assume the funds of a 2of3 multisig tx are not marked as
             # spendable
             assert_equal(self.nodes[2].getbalance(), bal)
 
             txDetails = self.nodes[0].gettransaction(txId, True)
             rawTx = self.nodes[0].decoderawtransaction(txDetails['hex'])
             vout = next(o for o in rawTx['vout']
                         if o['value'] == Decimal('2200000.00'))
 
             bal = self.nodes[0].getbalance()
             inputs = [{
                 "txid": txId,
                 "vout": vout['n'],
                 "scriptPubKey": vout['scriptPubKey']['hex'],
                 "amount": vout['value'],
             }]
             outputs = {self.nodes[0].getnewaddress(): 2190000}
             rawTx = self.nodes[2].createrawtransaction(inputs, outputs)
             rawTxPartialSigned = self.nodes[1].signrawtransactionwithwallet(
                 rawTx, inputs)
             # node1 only has one key, can't comp. sign the tx
             assert_equal(rawTxPartialSigned['complete'], False)
 
             rawTxSigned = self.nodes[2].signrawtransactionwithwallet(rawTx,
                                                                      inputs)
             # node2 can sign the tx compl., own two of three keys
             assert_equal(rawTxSigned['complete'], True)
             self.nodes[2].sendrawtransaction(rawTxSigned['hex'])
             rawTx = self.nodes[0].decoderawtransaction(rawTxSigned['hex'])
             self.sync_all()
             self.generate(self.nodes[0], 1)
             self.sync_all()
             assert_equal(self.nodes[0].getbalance(), bal + Decimal(
                 '50000000.00') + Decimal('2190000.00'))  # block reward + tx
 
             rawTxBlock = self.nodes[0].getblock(
                 self.nodes[0].getbestblockhash())
 
             # 2of2 test for combining transactions
             bal = self.nodes[2].getbalance()
             addr1 = self.nodes[1].getnewaddress()
             addr2 = self.nodes[2].getnewaddress()
 
             addr1Obj = self.nodes[1].getaddressinfo(addr1)
             addr2Obj = self.nodes[2].getaddressinfo(addr2)
 
             self.nodes[1].addmultisigaddress(
                 2, [addr1Obj['pubkey'], addr2Obj['pubkey']])['address']
             mSigObj = self.nodes[2].addmultisigaddress(
                 2, [addr1Obj['pubkey'], addr2Obj['pubkey']])['address']
             mSigObjValid = self.nodes[2].getaddressinfo(mSigObj)
 
             txId = self.nodes[0].sendtoaddress(mSigObj, 2200000)
             decTx = self.nodes[0].gettransaction(txId)
             rawTx2 = self.nodes[0].decoderawtransaction(decTx['hex'])
             self.sync_all()
             self.generate(self.nodes[0], 1)
             self.sync_all()
 
             # the funds of a 2of2 multisig tx should not be marked as spendable
             assert_equal(self.nodes[2].getbalance(), bal)
 
             txDetails = self.nodes[0].gettransaction(txId, True)
             rawTx2 = self.nodes[0].decoderawtransaction(txDetails['hex'])
             vout = next(o for o in rawTx2['vout']
                         if o['value'] == Decimal('2200000.00'))
 
             bal = self.nodes[0].getbalance()
             inputs = [{"txid": txId, "vout": vout['n'],
                        "scriptPubKey": vout['scriptPubKey']['hex'],
                        "redeemScript": mSigObjValid['hex'],
                        "amount": vout['value']}]
             outputs = {self.nodes[0].getnewaddress(): 2190000}
             rawTx2 = self.nodes[2].createrawtransaction(inputs, outputs)
             rawTxPartialSigned1 = self.nodes[1].signrawtransactionwithwallet(
                 rawTx2, inputs)
             self.log.debug(rawTxPartialSigned1)
             # node1 only has one key, can't comp. sign the tx
             assert_equal(rawTxPartialSigned1['complete'], False)
 
             rawTxPartialSigned2 = self.nodes[2].signrawtransactionwithwallet(
                 rawTx2, inputs)
             self.log.debug(rawTxPartialSigned2)
             # node2 only has one key, can't comp. sign the tx
             assert_equal(rawTxPartialSigned2['complete'], False)
             rawTxComb = self.nodes[2].combinerawtransaction(
                 [rawTxPartialSigned1['hex'], rawTxPartialSigned2['hex']])
             self.log.debug(rawTxComb)
             self.nodes[2].sendrawtransaction(rawTxComb)
             rawTx2 = self.nodes[0].decoderawtransaction(rawTxComb)
             self.sync_all()
             self.generate(self.nodes[0], 1)
             self.sync_all()
             # block reward + tx
             assert_equal(self.nodes[0].getbalance(),
                          bal + Decimal('50000000.00') + Decimal('2190000.00'))
 
             # Sanity checks on verbose getrawtransaction output
             txId = rawTx["txid"]
             rawTxOutput = self.nodes[0].getrawtransaction(txId, True)
             assert_equal(rawTxOutput["hex"], rawTxSigned["hex"])
             assert_equal(rawTxOutput["txid"], txId)
             assert_equal(rawTxOutput["hash"], txId)
             assert_greater_than(rawTxOutput["size"], 300)
             assert_equal(rawTxOutput["version"], 0x02)
             assert_equal(rawTxOutput["locktime"], 0)
             assert_equal(len(rawTxOutput["vin"]), 1)
             assert_equal(len(rawTxOutput["vout"]), 1)
             assert_equal(rawTxOutput["blockhash"], rawTxBlock["hash"])
             assert_equal(rawTxOutput["confirmations"], 3)
             assert_equal(rawTxOutput["time"], rawTxBlock["time"])
             assert_equal(rawTxOutput["blocktime"], rawTxBlock["time"])
 
         # Basic signrawtransaction test
         addr = self.nodes[1].getnewaddress()
         txid = self.nodes[0].sendtoaddress(addr, 10_000_000)
         self.generate(self.nodes[0], 1)
         self.sync_all()
         vout = find_vout_for_address(self.nodes[1], txid, addr)
         rawTx = self.nodes[1].createrawtransaction(
             [{'txid': txid, 'vout': vout}],
             {self.nodes[1].getnewaddress(): 9_999_000})
         rawTxSigned = self.nodes[1].signrawtransactionwithwallet(rawTx)
         txId = self.nodes[1].sendrawtransaction(rawTxSigned['hex'])
         self.generate(self.nodes[0], 1)
         self.sync_all()
 
         # getrawtransaction tests
         # 1. valid parameters - only supply txid
         assert_equal(
             self.nodes[0].getrawtransaction(txId), rawTxSigned['hex'])
 
         # 2. valid parameters - supply txid and 0 for non-verbose
         assert_equal(
             self.nodes[0].getrawtransaction(txId, 0), rawTxSigned['hex'])
 
         # 3. valid parameters - supply txid and False for non-verbose
         assert_equal(self.nodes[0].getrawtransaction(txId, False),
                      rawTxSigned['hex'])
 
         # 4. valid parameters - supply txid and 1 for verbose.
         # We only check the "hex" field of the output so we don't need to
         # update this test every time the output format changes.
         assert_equal(self.nodes[0].getrawtransaction(txId, 1)["hex"],
                      rawTxSigned['hex'])
 
         # 5. valid parameters - supply txid and True for non-verbose
         assert_equal(self.nodes[0].getrawtransaction(txId, True)["hex"],
                      rawTxSigned['hex'])
 
         # 6. invalid parameters - supply txid and string "Flase"
         assert_raises_rpc_error(-1, "not a boolean",
                                 self.nodes[0].getrawtransaction,
                                 txId, "Flase")
 
         # 7. invalid parameters - supply txid and empty array
         assert_raises_rpc_error(-1, "not a boolean",
                                 self.nodes[0].getrawtransaction, txId, [])
 
         # 8. invalid parameters - supply txid and empty dict
         assert_raises_rpc_error(
             -1, "not a boolean", self.nodes[0].getrawtransaction, txId, {})
 
         inputs = [
             {'txid': "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'sequence': 1000}]
         outputs = {self.nodes[0].getnewaddress(): 1}
         assert_raises_rpc_error(
             -8, 'Invalid parameter, missing vout key',
             self.nodes[0].createrawtransaction, inputs, outputs)
 
         inputs[0]['vout'] = "1"
         assert_raises_rpc_error(
             -8, 'Invalid parameter, vout must be a number',
             self.nodes[0].createrawtransaction, inputs, outputs)
 
         inputs[0]['vout'] = -1
         assert_raises_rpc_error(
             -8, 'Invalid parameter, vout cannot be negative',
             self.nodes[0].createrawtransaction, inputs, outputs)
 
         inputs[0]['vout'] = 1
         rawtx = self.nodes[0].createrawtransaction(inputs, outputs)
         decrawtx = self.nodes[0].decoderawtransaction(rawtx)
         assert_equal(decrawtx['vin'][0]['sequence'], 1000)
 
         # 9. invalid parameters - sequence number out of range
         inputs[0]['sequence'] = -1
         assert_raises_rpc_error(
             -8, 'Invalid parameter, sequence number is out of range',
             self.nodes[0].createrawtransaction, inputs, outputs)
 
         # 10. invalid parameters - sequence number out of range
         inputs[0]['sequence'] = 4294967296
         assert_raises_rpc_error(
             -8, 'Invalid parameter, sequence number is out of range',
             self.nodes[0].createrawtransaction, inputs, outputs)
 
         inputs[0]['sequence'] = 4294967294
         rawtx = self.nodes[0].createrawtransaction(inputs, outputs)
         decrawtx = self.nodes[0].decoderawtransaction(rawtx)
         assert_equal(decrawtx['vin'][0]['sequence'], 4294967294)
 
         ####################################
         # TRANSACTION VERSION NUMBER TESTS #
         ####################################
 
         # Test the minimum transaction version number that fits in a signed
         # 32-bit integer.
         # As transaction version is unsigned, this should convert to its
         # unsigned equivalent.
         tx = CTransaction()
         tx.nVersion = -0x80000000
         rawtx = ToHex(tx)
         decrawtx = self.nodes[0].decoderawtransaction(rawtx)
         assert_equal(decrawtx['version'], 0x80000000)
 
         # Test the maximum transaction version number that fits in a signed
         # 32-bit integer.
         tx = CTransaction()
         tx.nVersion = 0x7fffffff
         rawtx = ToHex(tx)
         decrawtx = self.nodes[0].decoderawtransaction(rawtx)
         assert_equal(decrawtx['version'], 0x7fffffff)
 
         self.log.info('sendrawtransaction/testmempoolaccept with maxfeerate')
 
         # Test a transaction with a small fee.
         txId = self.nodes[0].sendtoaddress(
             self.nodes[2].getnewaddress(), 1000000)
         rawTx = self.nodes[0].getrawtransaction(txId, True)
         vout = next(o for o in rawTx['vout']
                     if o['value'] == Decimal('1000000.00'))
 
         self.sync_all()
         inputs = [{"txid": txId, "vout": vout['n']}]
         # Fee 10,000 satoshis, (1,000,000 - (10000 sat * 0.01 XEC/sat)) =
         # 999900
         outputs = {self.nodes[0].getnewaddress(): Decimal("999900.00")}
         rawTx = self.nodes[2].createrawtransaction(inputs, outputs)
         rawTxSigned = self.nodes[2].signrawtransactionwithwallet(rawTx)
         assert_equal(rawTxSigned['complete'], True)
         # Fee 10,000 satoshis, ~200 b transaction, fee rate should land around 50 sat/byte = 500 XEC/kB
         # Thus, testmempoolaccept should reject
         testres = self.nodes[2].testmempoolaccept(
             [rawTxSigned['hex']], 500.00)[0]
         assert_equal(testres['allowed'], False)
         assert_equal(testres['reject-reason'], 'max-fee-exceeded')
         # and sendrawtransaction should throw
         assert_raises_rpc_error(-25,
                                 'Fee exceeds maximum configured by user (e.g. -maxtxfee, maxfeerate)',
                                 self.nodes[2].sendrawtransaction,
                                 rawTxSigned['hex'],
                                 10.00)
         # and the following calls should both succeed
         testres = self.nodes[2].testmempoolaccept(
             rawtxs=[rawTxSigned['hex']])[0]
         assert_equal(testres['allowed'], True)
         self.nodes[2].sendrawtransaction(hexstring=rawTxSigned['hex'])
 
         # Test a transaction with a large fee.
         txId = self.nodes[0].sendtoaddress(
             self.nodes[2].getnewaddress(), 1000000)
         rawTx = self.nodes[0].getrawtransaction(txId, True)
         vout = next(o for o in rawTx['vout']
                     if o['value'] == Decimal('1000000.00'))
 
         self.sync_all()
         inputs = [{"txid": txId, "vout": vout['n']}]
         # Fee 2,000,000 satoshis, (1,000,000 - (2,000,000 sat * 0.01 XEC/sat)) =
         # 980000
         outputs = {self.nodes[0].getnewaddress(): Decimal("980000.00")}
         rawTx = self.nodes[2].createrawtransaction(inputs, outputs)
         rawTxSigned = self.nodes[2].signrawtransactionwithwallet(rawTx)
         assert_equal(rawTxSigned['complete'], True)
         # Fee 2,000,000 satoshis, ~100 b transaction, fee rate should land around 20,000 sat/byte = 200,000 XEC/kB
         # Thus, testmempoolaccept should reject
         testres = self.nodes[2].testmempoolaccept([rawTxSigned['hex']])[0]
         assert_equal(testres['allowed'], False)
         assert_equal(testres['reject-reason'], 'max-fee-exceeded')
         # and sendrawtransaction should throw
         assert_raises_rpc_error(-25,
                                 'Fee exceeds maximum configured by user (e.g. -maxtxfee, maxfeerate)',
                                 self.nodes[2].sendrawtransaction,
                                 rawTxSigned['hex'])
         # and the following calls should both succeed
         testres = self.nodes[2].testmempoolaccept(
             rawtxs=[rawTxSigned['hex']], maxfeerate='200000.00')[0]
         assert_equal(testres['allowed'], True)
         self.nodes[2].sendrawtransaction(
             hexstring=rawTxSigned['hex'],
             maxfeerate='200000.00')
 
         self.log.info(
             'sendrawtransaction/testmempoolaccept with tx that is already in the chain')
         self.generate(self.nodes[2], 1)
         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'])
 
         ##########################################
         # Decoding weird scripts in transactions #
         ##########################################
 
         self.log.info('Decode correctly-formatted but weird transactions')
         tx = CTransaction()
         # empty
         self.nodes[0].decoderawtransaction(ToHex(tx))
         # truncated push
         tx.vin.append(CTxIn(COutPoint(42, 0), b'\x4e\x00\x00'))
         tx.vin.append(CTxIn(COutPoint(42, 0), b'\x4c\x10TRUNC'))
         tx.vout.append(CTxOut(0, b'\x4e\x00\x00'))
         tx.vout.append(CTxOut(0, b'\x4c\x10TRUNC'))
         self.nodes[0].decoderawtransaction(ToHex(tx))
         # giant pushes and long scripts
         tx.vin.append(
             CTxIn(COutPoint(42, 0), CScript([b'giant push' * 10000])))
         tx.vout.append(CTxOut(0, CScript([b'giant push' * 10000])))
         self.nodes[0].decoderawtransaction(ToHex(tx))
 
         self.log.info('Refuse garbage after transaction')
         assert_raises_rpc_error(-22, 'TX decode failed',
                                 self.nodes[0].decoderawtransaction, f"{ToHex(tx)}00")
 
 
 if __name__ == '__main__':
     RawTransactionsTest().main()
diff --git a/test/functional/wallet_coinbase_category.py b/test/functional/wallet_coinbase_category.py
index b48d3b8fe..91628456c 100755
--- a/test/functional/wallet_coinbase_category.py
+++ b/test/functional/wallet_coinbase_category.py
@@ -1,59 +1,59 @@
 #!/usr/bin/env python3
 # Copyright (c) 2014-2018 The Bitcoin Core developers
 # Distributed under the MIT software license, see the accompanying
 # file COPYING or http://www.opensource.org/licenses/mit-license.php.
 """Test coinbase transactions return the correct categories.
 
 Tests listtransactions, listsinceblock, and gettransaction.
 """
 
 from test_framework.test_framework import BitcoinTestFramework
 from test_framework.util import assert_array_result
 
 
 class CoinbaseCategoryTest(BitcoinTestFramework):
     def set_test_params(self):
         self.num_nodes = 1
 
     def skip_test_if_missing_module(self):
         self.skip_if_no_wallet()
 
     def assert_category(self, category, address, txid, skip):
         assert_array_result(self.nodes[0].listtransactions(skip=skip),
                             {"address": address},
                             {"category": category})
         assert_array_result(self.nodes[0].listsinceblock()["transactions"],
                             {"address": address},
                             {"category": category})
         assert_array_result(self.nodes[0].gettransaction(txid)["details"],
                             {"address": address},
                             {"category": category})
 
     def run_test(self):
         # Generate one block to an address
         address = self.nodes[0].getnewaddress()
         self.generatetoaddress(self.nodes[0], 1, address)
-        hash = self.nodes[0].getbestblockhash()
-        txid = self.nodes[0].getblock(hash)["tx"][0]
+        blockhash = self.nodes[0].getbestblockhash()
+        txid = self.nodes[0].getblock(blockhash)["tx"][0]
 
         # Coinbase transaction is immature after 1 confirmation
         self.assert_category("immature", address, txid, 0)
 
         # Mine another 99 blocks on top
         self.generate(self.nodes[0], 99)
         # Coinbase transaction is still immature after 100 confirmations
         self.assert_category("immature", address, txid, 99)
 
         # Mine one more block
         self.generate(self.nodes[0], 1)
         # Coinbase transaction is now matured, so category is "generate"
         self.assert_category("generate", address, txid, 100)
 
         # Orphan block that paid to address
-        self.nodes[0].invalidateblock(hash)
+        self.nodes[0].invalidateblock(blockhash)
         # Coinbase transaction is now orphaned
         self.assert_category("orphan", address, txid, 100)
 
 
 if __name__ == '__main__':
     CoinbaseCategoryTest().main()
diff --git a/test/functional/wallet_send.py b/test/functional/wallet_send.py
index 0b8eab9fb..2896951e9 100755
--- a/test/functional/wallet_send.py
+++ b/test/functional/wallet_send.py
@@ -1,421 +1,421 @@
 #!/usr/bin/env python3
 # Copyright (c) 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 the send RPC command."""
 
 from decimal import Decimal
 
 from test_framework.authproxy import JSONRPCException
 from test_framework.test_framework import BitcoinTestFramework
 from test_framework.util import (
     assert_equal,
     assert_fee_amount,
     assert_greater_than,
     assert_raises_rpc_error,
 )
 
 
 class WalletSendTest(BitcoinTestFramework):
     def set_test_params(self):
         self.num_nodes = 2
         # whitelist all peers to speed up tx relay / mempool sync
         self.extra_args = [
             ["-whitelist=127.0.0.1", ],
             ["-whitelist=127.0.0.1", ],
         ]
 
     def skip_test_if_missing_module(self):
         self.skip_if_no_wallet()
 
     def test_send(self, from_wallet, to_wallet=None, amount=None, data=None,
                   add_to_wallet=None, psbt=None, inputs=None, add_inputs=None,
                   change_address=None, change_position=None,
                   include_watching=None, locktime=None, lock_unspents=None,
                   subtract_fee_from_outputs=None, fee_rate=None,
                   expect_error=None):
         assert (amount is None) != (data is None)
 
         from_balance_before = from_wallet.getbalance()
         if to_wallet is None:
             assert amount is None
         else:
             to_untrusted_pending_before = \
                 to_wallet.getbalances()["mine"]["untrusted_pending"]
 
         if amount:
             dest = to_wallet.getnewaddress()
             outputs = {dest: amount}
         else:
             outputs = {"data": data}
 
         # Construct options dictionary
         options = {}
         if add_to_wallet is not None:
             options["add_to_wallet"] = add_to_wallet
         else:
             add_to_wallet = (
                 False if psbt else
                 from_wallet.getwalletinfo()["private_keys_enabled"]
             )
         if psbt is not None:
             options["psbt"] = psbt
         if inputs is not None:
             options["inputs"] = inputs
         if add_inputs is not None:
             options["add_inputs"] = add_inputs
         if change_address is not None:
             options["change_address"] = change_address
         if change_position is not None:
             options["change_position"] = change_position
         if include_watching is not None:
             options["include_watching"] = include_watching
         if locktime is not None:
             options["locktime"] = locktime
         if lock_unspents is not None:
             options["lock_unspents"] = lock_unspents
         if subtract_fee_from_outputs is not None:
             options["subtract_fee_from_outputs"] = subtract_fee_from_outputs
         if fee_rate is not None:
             options["fee_rate"] = fee_rate
 
         if len(options.keys()) == 0:
             options = None
 
         if expect_error is None:
             res = from_wallet.send(
                 outputs=outputs,
                 options=options)
         else:
             try:
                 assert_raises_rpc_error(
                     expect_error[0], expect_error[1], from_wallet.send,
                     outputs=outputs, options=options)
             except AssertionError:
                 # Provide debug info if the test fails
                 self.log.error("Unexpected successful result:")
                 self.log.error(options)
                 res = from_wallet.send(
                     outputs=outputs,
                     options=options)
                 self.log.error(res)
                 if "txid" in res and add_to_wallet:
                     self.log.error("Transaction details:")
                     try:
                         tx = from_wallet.gettransaction(res["txid"])
                         self.log.error(tx)
                         self.log.error(
                             "testmempoolaccept (transaction may already be in mempool):")
                         self.log.error(
                             from_wallet.testmempoolaccept([tx["hex"]]))
                     except JSONRPCException as exc:
                         self.log.error(exc)
 
                 raise
 
             return
 
         if locktime:
             return res
 
         if (from_wallet.getwalletinfo()["private_keys_enabled"]
                 and not include_watching):
             assert_equal(res["complete"], True)
             assert "txid" in res
         else:
             assert_equal(res["complete"], False)
             assert "txid" not in res
             assert "psbt" in res
 
         if add_to_wallet and not include_watching:
             # Ensure transaction exists in the wallet:
             tx = from_wallet.gettransaction(res["txid"])
             assert tx
             # Ensure transaction exists in the mempool:
             tx = from_wallet.getrawtransaction(res["txid"], True)
             assert tx
             if amount:
                 if subtract_fee_from_outputs:
                     assert_equal(
                         from_balance_before -
                         from_wallet.getbalance(),
                         amount)
                 else:
                     assert_greater_than(
                         from_balance_before - from_wallet.getbalance(), amount)
             else:
                 assert next(
                     (out for out in tx["vout"] if out["scriptPubKey"]
                      ["asm"] == "OP_RETURN 35"),
                     None)
         else:
             assert_equal(from_balance_before, from_wallet.getbalance())
 
         if to_wallet:
             self.sync_mempools()
             if add_to_wallet:
                 if not subtract_fee_from_outputs:
                     assert_equal(
                         to_wallet.getbalances()["mine"]["untrusted_pending"],
                         to_untrusted_pending_before +
                         Decimal(
                             amount if amount else 0))
             else:
                 assert_equal(
                     to_wallet.getbalances()["mine"]["untrusted_pending"],
                     to_untrusted_pending_before)
 
         return res
 
     def run_test(self):
         self.log.info("Setup wallets...")
         # w0 is a wallet with coinbase rewards
         w0 = self.nodes[0].get_wallet_rpc(self.default_wallet_name)
         # w1 is a regular wallet
         self.nodes[1].createwallet(wallet_name="w1")
         w1 = self.nodes[1].get_wallet_rpc("w1")
         # w2 contains the private keys for w3
         self.nodes[1].createwallet(wallet_name="w2")
         w2 = self.nodes[1].get_wallet_rpc("w2")
         # w3 is a watch-only wallet, based on w2
         self.nodes[1].createwallet(wallet_name="w3", disable_private_keys=True)
         w3 = self.nodes[1].get_wallet_rpc("w3")
         for _ in range(3):
             a2_receive = w2.getnewaddress()
             # doesn't actually use change derivation
             a2_change = w2.getrawchangeaddress()
             res = w3.importmulti([{
                 "desc": w2.getaddressinfo(a2_receive)["desc"],
                 "timestamp": "now",
                 "keypool": True,
                 "watchonly": True
             }, {
                 "desc": w2.getaddressinfo(a2_change)["desc"],
                 "timestamp": "now",
                 "keypool": True,
                 "internal": True,
                 "watchonly": True
             }])
             assert_equal(res, [{"success": True}, {"success": True}])
 
         # fund w3
         w0.sendtoaddress(a2_receive, 10_000_000)
         self.generate(self.nodes[0], 1)
 
         # w4 has private keys enabled, but only contains watch-only keys (from
         # w2)
         self.nodes[1].createwallet(
             wallet_name="w4",
             disable_private_keys=False)
         w4 = self.nodes[1].get_wallet_rpc("w4")
         for _ in range(3):
             a2_receive = w2.getnewaddress()
             res = w4.importmulti([{
                 "desc": w2.getaddressinfo(a2_receive)["desc"],
                 "timestamp": "now",
                 "keypool": False,
                 "watchonly": True
             }])
             assert_equal(res, [{"success": True}])
 
         # fund w4
         w0.sendtoaddress(a2_receive, 10_000_000)
         self.generate(self.nodes[0], 1)
 
         self.log.info("Send to address...")
         self.test_send(from_wallet=w0, to_wallet=w1, amount=1_000_000)
         self.test_send(
             from_wallet=w0,
             to_wallet=w1,
             amount=1_000_000,
             add_to_wallet=True)
 
         self.log.info("Don't broadcast...")
         res = self.test_send(
             from_wallet=w0,
             to_wallet=w1,
             amount=1_000_000,
             add_to_wallet=False)
         assert res["hex"]
 
         self.log.info("Return PSBT...")
         res = self.test_send(
             from_wallet=w0,
             to_wallet=w1,
             amount=1_000_000,
             psbt=True)
         assert res["psbt"]
 
         self.log.info(
             "Create transaction that spends to address, but don't broadcast...")
         self.test_send(
             from_wallet=w0,
             to_wallet=w1,
             amount=1_000_000,
             add_to_wallet=False)
 
         self.log.info("Create PSBT from watch-only wallet w3, sign with w2...")
         res = self.test_send(from_wallet=w3, to_wallet=w1, amount=1_000_000)
         res = w2.walletprocesspsbt(res["psbt"])
         assert res["complete"]
 
         self.log.info(
             "Create PSBT from wallet w4 with watch-only keys, sign with w2...")
         self.test_send(from_wallet=w4, to_wallet=w1, amount=1_000_000,
                        expect_error=(-4, "Insufficient funds"))
         res = self.test_send(
             from_wallet=w4,
             to_wallet=w1,
             amount=1_000_000,
             include_watching=True,
             add_to_wallet=False)
         res = w2.walletprocesspsbt(res["psbt"])
         assert res["complete"]
 
         self.log.info("Create OP_RETURN...")
         self.test_send(from_wallet=w0, to_wallet=w1, amount=1_000_000)
         self.test_send(from_wallet=w0,
                        data="Hello World",
                        expect_error=(-8,
                                      "Data must be hexadecimal string (not 'Hello World')"))
         self.test_send(from_wallet=w0, data="23")
         res = self.test_send(from_wallet=w3, data="23")
         res = w2.walletprocesspsbt(res["psbt"])
         assert res["complete"]
 
         self.log.info("Set fee rate...")
         res = self.test_send(
             from_wallet=w0,
             to_wallet=w1,
             amount=1_000_000,
             fee_rate=Decimal("20.00"),
             add_to_wallet=False)
         fee = self.nodes[1].decodepsbt(res["psbt"])["fee"]
         assert_fee_amount(fee,
                           len(res["hex"]) // 2,
                           Decimal("20.00"))
         self.test_send(from_wallet=w0, to_wallet=w1, amount=1_000_000, fee_rate=-1,
                        expect_error=(-3, "Amount out of range"))
         # Fee rate of 0.1 satoshi per byte should throw an error
         self.test_send(from_wallet=w0, to_wallet=w1, amount=1_000_000,
                        fee_rate=Decimal("1.00"),
                        expect_error=(-4, "Fee rate (1.00 XEC/kB) is lower than the minimum fee rate setting (10.00 XEC/kB)"))
 
         # TODO: Return hex if fee rate is below -maxmempool
         # res = self.test_send(from_wallet=w0, to_wallet=w1, amount=1_000_000,
         #                      feeRate=Decimal("1.00"), add_to_wallet=False)
         # assert res["hex"]
         # hex = res["hex"]
         # res = self.nodes[0].testmempoolaccept([hex])
         # assert not res[0]["allowed"]
         # assert_equal(res[0]["reject-reason"], "...") # low fee
         # assert_fee_amount(fee, Decimal(len(res["hex"]) / 2), Decimal("1.00"))
 
         self.log.info(
             "If inputs are specified, do not automatically add more...")
         res = self.test_send(
             from_wallet=w0,
             to_wallet=w1,
             amount=51_000_000,
             inputs=[],
             add_to_wallet=False)
         assert res["complete"]
         utxo1 = w0.listunspent()[0]
         assert_equal(utxo1["amount"], 50_000_000)
         self.test_send(from_wallet=w0, to_wallet=w1, amount=51_000_000,
                        inputs=[utxo1], expect_error=(-4, "Insufficient funds"))
         self.test_send(from_wallet=w0, to_wallet=w1, amount=51_000_000,
                        inputs=[utxo1], add_inputs=False,
                        expect_error=(-4, "Insufficient funds"))
         res = self.test_send(
             from_wallet=w0,
             to_wallet=w1,
             amount=51_000_000,
             inputs=[utxo1],
             add_inputs=True,
             add_to_wallet=False)
         assert res["complete"]
 
         self.log.info("Manual change address and position...")
         self.test_send(from_wallet=w0, to_wallet=w1, amount=1_000_000, change_address="not an address",
                        expect_error=(-5, "Change address must be a valid bitcoin address"))
         change_address = w0.getnewaddress()
         self.test_send(
             from_wallet=w0,
             to_wallet=w1,
             amount=1_000_000,
             add_to_wallet=False,
             change_address=change_address)
         assert res["complete"]
         res = self.test_send(
             from_wallet=w0,
             to_wallet=w1,
             amount=1_000_000,
             add_to_wallet=False,
             change_address=change_address,
             change_position=0)
         assert res["complete"]
         assert_equal(
             self.nodes[0].decodepsbt(
                 res["psbt"])["tx"]["vout"][0]["scriptPubKey"]["addresses"],
             [change_address])
 
         self.log.info("Set lock time...")
         height = self.nodes[0].getblockchaininfo()["blocks"]
         res = self.test_send(
             from_wallet=w0,
             to_wallet=w1,
             amount=1_000_000,
             locktime=height + 1)
         assert res["complete"]
         assert res["txid"]
         txid = res["txid"]
         # Although the wallet finishes the transaction, it can't be added to
         # the mempool yet:
-        hex = self.nodes[0].gettransaction(res["txid"])["hex"]
-        res = self.nodes[0].testmempoolaccept([hex])
+        tx_hex = self.nodes[0].gettransaction(res["txid"])["hex"]
+        res = self.nodes[0].testmempoolaccept([tx_hex])
         assert not res[0]["allowed"]
         assert_equal(res[0]["reject-reason"], "bad-txns-nonfinal")
         # It shouldn't be confirmed in the next block
         self.generate(self.nodes[0], 1)
         assert_equal(self.nodes[0].gettransaction(txid)["confirmations"], 0)
         # The mempool should allow it now:
-        res = self.nodes[0].testmempoolaccept([hex])
+        res = self.nodes[0].testmempoolaccept([tx_hex])
         assert res[0]["allowed"]
         # Don't wait for wallet to add it to the mempool:
-        res = self.nodes[0].sendrawtransaction(hex)
+        res = self.nodes[0].sendrawtransaction(tx_hex)
         self.generate(self.nodes[0], 1)
         assert_equal(self.nodes[0].gettransaction(txid)["confirmations"], 1)
 
         self.log.info("Lock unspents...")
         utxo1 = w0.listunspent()[0]
         assert_greater_than(utxo1["amount"], 1_000_000)
         res = self.test_send(
             from_wallet=w0,
             to_wallet=w1,
             amount=1_000_000,
             inputs=[utxo1],
             add_to_wallet=False,
             lock_unspents=True)
         assert res["complete"]
         locked_coins = w0.listlockunspent()
         assert_equal(len(locked_coins), 1)
         # Locked coins are automatically unlocked when manually selected
         res = self.test_send(
             from_wallet=w0,
             to_wallet=w1,
             amount=1_000_000,
             inputs=[utxo1],
             add_to_wallet=False)
         assert res["complete"]
 
         self.log.info("Subtract fee from output")
         self.test_send(
             from_wallet=w0,
             to_wallet=w1,
             amount=1_000_000,
             subtract_fee_from_outputs=[0])
 
 
 if __name__ == '__main__':
     WalletSendTest().main()