aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/functional/README.md2
-rwxr-xr-xtest/functional/feature_addrman.py52
-rwxr-xr-xtest/functional/feature_asmap.py29
-rwxr-xr-xtest/functional/feature_bip68_sequence.py5
-rwxr-xr-xtest/functional/feature_coinstatsindex.py12
-rwxr-xr-xtest/functional/feature_csv_activation.py1
-rwxr-xr-xtest/functional/feature_maxuploadtarget.py1
-rwxr-xr-xtest/functional/feature_rbf.py2
-rwxr-xr-xtest/functional/interface_bitcoin_cli.py11
-rwxr-xr-xtest/functional/mempool_packages.py20
-rwxr-xr-xtest/functional/mempool_reorg.py2
-rwxr-xr-xtest/functional/mempool_spend_coinbase.py8
-rwxr-xr-xtest/functional/p2p_blocksonly.py24
-rwxr-xr-xtest/functional/rpc_blockchain.py2
-rwxr-xr-xtest/functional/rpc_net.py35
-rwxr-xr-xtest/functional/test_framework/p2p.py2
-rw-r--r--test/functional/test_framework/util.py5
-rw-r--r--test/functional/test_framework/wallet.py13
18 files changed, 167 insertions, 59 deletions
diff --git a/test/functional/README.md b/test/functional/README.md
index d830ba0334..926810cf03 100644
--- a/test/functional/README.md
+++ b/test/functional/README.md
@@ -188,5 +188,5 @@ perf report -i /path/to/datadir/send-big-msgs.perf.data.xxxx --stdio | c++filt |
#### See also:
- [Installing perf](https://askubuntu.com/q/50145)
-- [Perf examples](http://www.brendangregg.com/perf.html)
+- [Perf examples](https://www.brendangregg.com/perf.html)
- [Hotspot](https://github.com/KDAB/hotspot): a GUI for perf output analysis
diff --git a/test/functional/feature_addrman.py b/test/functional/feature_addrman.py
index ee421c89b5..42afd74ac9 100755
--- a/test/functional/feature_addrman.py
+++ b/test/functional/feature_addrman.py
@@ -14,22 +14,30 @@ from test_framework.test_node import ErrorMatch
from test_framework.util import assert_equal
-def serialize_addrman(*, format=1, lowest_compatible=3):
+def serialize_addrman(
+ *,
+ format=1,
+ lowest_compatible=3,
+ net_magic="regtest",
+ len_new=None,
+ len_tried=None,
+ mock_checksum=None,
+):
new = []
tried = []
INCOMPATIBILITY_BASE = 32
- r = MAGIC_BYTES["regtest"]
+ r = MAGIC_BYTES[net_magic]
r += struct.pack("B", format)
r += struct.pack("B", INCOMPATIBILITY_BASE + lowest_compatible)
r += ser_uint256(1)
- r += struct.pack("i", len(new))
- r += struct.pack("i", len(tried))
+ r += struct.pack("i", len_new or len(new))
+ r += struct.pack("i", len_tried or len(tried))
ADDRMAN_NEW_BUCKET_COUNT = 1 << 10
r += struct.pack("i", ADDRMAN_NEW_BUCKET_COUNT ^ (1 << 30))
for _ in range(ADDRMAN_NEW_BUCKET_COUNT):
r += struct.pack("i", 0)
checksum = hash256(r)
- r += checksum
+ r += mock_checksum or checksum
return r
@@ -70,7 +78,7 @@ class AddrmanTest(BitcoinTestFramework):
match=ErrorMatch.FULL_REGEX,
)
- self.log.info("Check that corrupt addrman cannot be read")
+ self.log.info("Check that corrupt addrman cannot be read (EOF)")
self.stop_node(0)
with open(peers_dat, "wb") as f:
f.write(serialize_addrman()[:-1])
@@ -79,6 +87,38 @@ class AddrmanTest(BitcoinTestFramework):
match=ErrorMatch.FULL_REGEX,
)
+ self.log.info("Check that corrupt addrman cannot be read (magic)")
+ self.stop_node(0)
+ write_addrman(peers_dat, net_magic="signet")
+ self.nodes[0].assert_start_raises_init_error(
+ expected_msg=init_error("Invalid network magic number"),
+ match=ErrorMatch.FULL_REGEX,
+ )
+
+ self.log.info("Check that corrupt addrman cannot be read (checksum)")
+ self.stop_node(0)
+ write_addrman(peers_dat, mock_checksum=b"ab" * 32)
+ self.nodes[0].assert_start_raises_init_error(
+ expected_msg=init_error("Checksum mismatch, data corrupted"),
+ match=ErrorMatch.FULL_REGEX,
+ )
+
+ self.log.info("Check that corrupt addrman cannot be read (len_tried)")
+ self.stop_node(0)
+ write_addrman(peers_dat, len_tried=-1)
+ self.nodes[0].assert_start_raises_init_error(
+ expected_msg=init_error("Corrupt CAddrMan serialization: nTried=-1, should be in \\[0, 16384\\]:.*"),
+ match=ErrorMatch.FULL_REGEX,
+ )
+
+ self.log.info("Check that corrupt addrman cannot be read (len_new)")
+ self.stop_node(0)
+ write_addrman(peers_dat, len_new=-1)
+ self.nodes[0].assert_start_raises_init_error(
+ expected_msg=init_error("Corrupt CAddrMan serialization: nNew=-1, should be in \\[0, 65536\\]:.*"),
+ match=ErrorMatch.FULL_REGEX,
+ )
+
self.log.info("Check that missing addrman is recreated")
self.stop_node(0)
os.remove(peers_dat)
diff --git a/test/functional/feature_asmap.py b/test/functional/feature_asmap.py
index 704dd6126b..2dc1e3a7cb 100755
--- a/test/functional/feature_asmap.py
+++ b/test/functional/feature_asmap.py
@@ -14,9 +14,11 @@ Verify node behaviour and debug log when launching bitcoind in these cases:
4. `bitcoind -asmap/-asmap=` with no file specified, using the default asmap
-5. `bitcoind -asmap` with no file specified and a missing default asmap file
+5. `bitcoind -asmap` restart with an addrman containing new and tried entries
-6. `bitcoind -asmap` with an empty (unparsable) default asmap file
+6. `bitcoind -asmap` with no file specified and a missing default asmap file
+
+7. `bitcoind -asmap` with an empty (unparsable) default asmap file
The tests are order-independent.
@@ -37,6 +39,12 @@ def expected_messages(filename):
class AsmapTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 1
+ self.extra_args = [["-checkaddrman=1"]] # Do addrman checks on all operations.
+
+ def fill_addrman(self, node_id):
+ """Add 2 tried addresses to the addrman, followed by 2 new addresses."""
+ for addr, tried in [[0, True], [1, True], [2, False], [3, False]]:
+ self.nodes[node_id].addpeeraddress(address=f"101.{addr}.0.0", tried=tried, port=8333)
def test_without_asmap_arg(self):
self.log.info('Test bitcoind with no -asmap arg passed')
@@ -72,6 +80,22 @@ class AsmapTest(BitcoinTestFramework):
self.start_node(0, [arg])
os.remove(self.default_asmap)
+ def test_asmap_interaction_with_addrman_containing_entries(self):
+ self.log.info("Test bitcoind -asmap restart with addrman containing new and tried entries")
+ self.stop_node(0)
+ shutil.copyfile(self.asmap_raw, self.default_asmap)
+ self.start_node(0, ["-asmap", "-checkaddrman=1"])
+ self.fill_addrman(node_id=0)
+ self.restart_node(0, ["-asmap", "-checkaddrman=1"])
+ with self.node.assert_debug_log(
+ expected_msgs=[
+ "Addrman checks started: new 2, tried 2, total 4",
+ "Addrman checks completed successfully",
+ ]
+ ):
+ self.node.getnodeaddresses() # getnodeaddresses re-runs the addrman checks
+ os.remove(self.default_asmap)
+
def test_default_asmap_with_missing_file(self):
self.log.info('Test bitcoind -asmap with missing default map file')
self.stop_node(0)
@@ -97,6 +121,7 @@ class AsmapTest(BitcoinTestFramework):
self.test_asmap_with_absolute_path()
self.test_asmap_with_relative_path()
self.test_default_asmap()
+ self.test_asmap_interaction_with_addrman_containing_entries()
self.test_default_asmap_with_missing_file()
self.test_empty_asmap()
diff --git a/test/functional/feature_bip68_sequence.py b/test/functional/feature_bip68_sequence.py
index 85522164d2..09cda8444a 100755
--- a/test/functional/feature_bip68_sequence.py
+++ b/test/functional/feature_bip68_sequence.py
@@ -41,10 +41,7 @@ class BIP68Test(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 2
self.extra_args = [
- [
- "-acceptnonstdtxn=1",
- "-peertimeout=9999", # bump because mocktime might cause a disconnect otherwise
- ],
+ ["-acceptnonstdtxn=1"],
["-acceptnonstdtxn=0"],
]
diff --git a/test/functional/feature_coinstatsindex.py b/test/functional/feature_coinstatsindex.py
index 146e776b07..c592d7bd69 100755
--- a/test/functional/feature_coinstatsindex.py
+++ b/test/functional/feature_coinstatsindex.py
@@ -164,7 +164,7 @@ class CoinStatsIndexTest(BitcoinTestFramework):
# Generate and send another tx with an OP_RETURN output (which is unspendable)
tx2 = CTransaction()
tx2.vin.append(CTxIn(COutPoint(int(tx1_txid, 16), n), b''))
- tx2.vout.append(CTxOut(int(20.99 * COIN), CScript([OP_RETURN] + [OP_FALSE]*30)))
+ tx2.vout.append(CTxOut(int(Decimal('20.99') * COIN), CScript([OP_RETURN] + [OP_FALSE]*30)))
tx2_hex = self.nodes[0].signrawtransactionwithwallet(tx2.serialize().hex())['hex']
self.nodes[0].sendrawtransaction(tx2_hex)
@@ -175,16 +175,16 @@ class CoinStatsIndexTest(BitcoinTestFramework):
for hash_option in index_hash_options:
# Check all amounts were registered correctly
res6 = index_node.gettxoutsetinfo(hash_option, 108)
- assert_equal(res6['total_unspendable_amount'], Decimal('70.98999999'))
+ assert_equal(res6['total_unspendable_amount'], Decimal('70.99000000'))
assert_equal(res6['block_info'], {
- 'unspendable': Decimal('20.98999999'),
+ 'unspendable': Decimal('20.99000000'),
'prevout_spent': 111,
'new_outputs_ex_coinbase': Decimal('89.99993620'),
- 'coinbase': Decimal('50.01006381'),
+ 'coinbase': Decimal('50.01006380'),
'unspendables': {
'genesis_block': 0,
'bip30': 0,
- 'scripts': Decimal('20.98999999'),
+ 'scripts': Decimal('20.99000000'),
'unclaimed_rewards': 0
}
})
@@ -206,7 +206,7 @@ class CoinStatsIndexTest(BitcoinTestFramework):
for hash_option in index_hash_options:
res7 = index_node.gettxoutsetinfo(hash_option, 109)
- assert_equal(res7['total_unspendable_amount'], Decimal('80.98999999'))
+ assert_equal(res7['total_unspendable_amount'], Decimal('80.99000000'))
assert_equal(res7['block_info'], {
'unspendable': 10,
'prevout_spent': 0,
diff --git a/test/functional/feature_csv_activation.py b/test/functional/feature_csv_activation.py
index 2bfe22267b..d2b3fe45d1 100755
--- a/test/functional/feature_csv_activation.py
+++ b/test/functional/feature_csv_activation.py
@@ -94,7 +94,6 @@ class BIP68_112_113Test(BitcoinTestFramework):
self.num_nodes = 1
self.setup_clean_chain = True
self.extra_args = [[
- '-peertimeout=999999', # bump because mocktime might cause a disconnect otherwise
'-whitelist=noban@127.0.0.1',
'-par=1', # Use only one script thread to get the exact reject reason for testing
]]
diff --git a/test/functional/feature_maxuploadtarget.py b/test/functional/feature_maxuploadtarget.py
index 12bcc2ffc5..ac4d40638e 100755
--- a/test/functional/feature_maxuploadtarget.py
+++ b/test/functional/feature_maxuploadtarget.py
@@ -38,7 +38,6 @@ class MaxUploadTest(BitcoinTestFramework):
self.extra_args = [[
"-maxuploadtarget=800",
"-acceptnonstdtxn=1",
- "-peertimeout=9999", # bump because mocktime might cause a disconnect otherwise
]]
self.supports_cli = False
diff --git a/test/functional/feature_rbf.py b/test/functional/feature_rbf.py
index cb7556feb4..b941061963 100755
--- a/test/functional/feature_rbf.py
+++ b/test/functional/feature_rbf.py
@@ -46,7 +46,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
# the pre-mined test framework chain contains coinbase outputs to the
# MiniWallet's default address ADDRESS_BCRT1_P2WSH_OP_TRUE in blocks
# 76-100 (see method BitcoinTestFramework._initialize_chain())
- self.wallet.scan_blocks(start=76, num=2)
+ self.wallet.rescan_utxos()
self.log.info("Running test simple doublespend...")
self.test_simple_doublespend()
diff --git a/test/functional/interface_bitcoin_cli.py b/test/functional/interface_bitcoin_cli.py
index 89503adda3..c28186cde7 100755
--- a/test/functional/interface_bitcoin_cli.py
+++ b/test/functional/interface_bitcoin_cli.py
@@ -57,7 +57,7 @@ def cli_get_info_string_to_dict(cli_get_info_string):
if key == 'Wallet' and value == '""':
# Set default wallet("") to empty string
value = ''
- if key == "Proxy" and value == "N/A":
+ if key == "Proxies" and value == "n/a":
# Set N/A to empty string to represent no proxy
value = ''
cli_get_info[key.strip()] = value.strip()
@@ -127,10 +127,17 @@ class TestBitcoinCli(BitcoinTestFramework):
assert_equal(int(cli_get_info['Time offset (s)']), network_info['timeoffset'])
expected_network_info = f"in {network_info['connections_in']}, out {network_info['connections_out']}, total {network_info['connections']}"
assert_equal(cli_get_info["Network"], expected_network_info)
- assert_equal(cli_get_info['Proxy'], network_info['networks'][0]['proxy'])
+ assert_equal(cli_get_info['Proxies'], network_info['networks'][0]['proxy'])
assert_equal(Decimal(cli_get_info['Difficulty']), blockchain_info['difficulty'])
assert_equal(cli_get_info['Chain'], blockchain_info['chain'])
+ self.log.info("Test -getinfo and bitcoin-cli return all proxies")
+ self.restart_node(0, extra_args=["-proxy=127.0.0.1:9050", "-i2psam=127.0.0.1:7656"])
+ network_info = self.nodes[0].getnetworkinfo()
+ cli_get_info_string = self.nodes[0].cli('-getinfo').send_cli()
+ cli_get_info = cli_get_info_string_to_dict(cli_get_info_string)
+ assert_equal(cli_get_info["Proxies"], "127.0.0.1:9050 (ipv4, ipv6, onion), 127.0.0.1:7656 (i2p)")
+
if self.is_wallet_compiled():
self.log.info("Test -getinfo and bitcoin-cli getwalletinfo return expected wallet info")
assert_equal(Decimal(cli_get_info['Balance']), BALANCE)
diff --git a/test/functional/mempool_packages.py b/test/functional/mempool_packages.py
index b9344ad6da..c042961937 100755
--- a/test/functional/mempool_packages.py
+++ b/test/functional/mempool_packages.py
@@ -51,12 +51,17 @@ class MempoolPackagesTest(BitcoinTestFramework):
txid = utxo[0]['txid']
vout = utxo[0]['vout']
value = utxo[0]['amount']
+ assert 'ancestorcount' not in utxo[0]
+ assert 'ancestorsize' not in utxo[0]
+ assert 'ancestorfees' not in utxo[0]
fee = Decimal("0.0001")
# MAX_ANCESTORS transactions off a confirmed tx should be fine
chain = []
witness_chain = []
- for _ in range(MAX_ANCESTORS):
+ ancestor_vsize = 0
+ ancestor_fees = Decimal(0)
+ for i in range(MAX_ANCESTORS):
(txid, sent_value) = chain_transaction(self.nodes[0], [txid], [0], value, fee, 1)
value = sent_value
chain.append(txid)
@@ -65,6 +70,15 @@ class MempoolPackagesTest(BitcoinTestFramework):
witnesstx = self.nodes[0].decoderawtransaction(fulltx, True)
witness_chain.append(witnesstx['hash'])
+ # Check that listunspent ancestor{count, size, fees} yield the correct results
+ wallet_unspent = self.nodes[0].listunspent(minconf=0)
+ this_unspent = next(utxo_info for utxo_info in wallet_unspent if utxo_info['txid'] == txid)
+ assert_equal(this_unspent['ancestorcount'], i + 1)
+ ancestor_vsize += self.nodes[0].getrawtransaction(txid=txid, verbose=True)['vsize']
+ assert_equal(this_unspent['ancestorsize'], ancestor_vsize)
+ ancestor_fees -= self.nodes[0].gettransaction(txid=txid)['fee']
+ assert_equal(this_unspent['ancestorfees'], ancestor_fees * COIN)
+
# Wait until mempool transactions have passed initial broadcast (sent inv and received getdata)
# Otherwise, getrawmempool may be inconsistent with getmempoolentry if unbroadcast changes in between
peer_inv_store.wait_for_broadcast(witness_chain)
@@ -77,9 +91,9 @@ class MempoolPackagesTest(BitcoinTestFramework):
descendant_fees = 0
descendant_vsize = 0
- ancestor_vsize = sum([mempool[tx]['vsize'] for tx in mempool])
+ assert_equal(ancestor_vsize, sum([mempool[tx]['vsize'] for tx in mempool]))
ancestor_count = MAX_ANCESTORS
- ancestor_fees = sum([mempool[tx]['fee'] for tx in mempool])
+ assert_equal(ancestor_fees, sum([mempool[tx]['fee'] for tx in mempool]))
descendants = []
ancestors = list(chain)
diff --git a/test/functional/mempool_reorg.py b/test/functional/mempool_reorg.py
index 0ee6af62f6..260b41ef12 100755
--- a/test/functional/mempool_reorg.py
+++ b/test/functional/mempool_reorg.py
@@ -31,7 +31,7 @@ class MempoolCoinbaseTest(BitcoinTestFramework):
self.log.info("Add 4 coinbase utxos to the miniwallet")
# Block 76 contains the first spendable coinbase txs.
first_block = 76
- wallet.scan_blocks(start=first_block, num=4)
+ wallet.rescan_utxos()
# Three scenarios for re-orging coinbase spends in the memory pool:
# 1. Direct coinbase spend : spend_1
diff --git a/test/functional/mempool_spend_coinbase.py b/test/functional/mempool_spend_coinbase.py
index e97595ed86..4e1dd80ba7 100755
--- a/test/functional/mempool_spend_coinbase.py
+++ b/test/functional/mempool_spend_coinbase.py
@@ -28,14 +28,14 @@ class MempoolSpendCoinbaseTest(BitcoinTestFramework):
chain_height = 198
self.nodes[0].invalidateblock(self.nodes[0].getblockhash(chain_height + 1))
assert_equal(chain_height, self.nodes[0].getblockcount())
+ wallet.rescan_utxos()
# Coinbase at height chain_height-100+1 ok in mempool, should
# get mined. Coinbase at height chain_height-100+2 is
# too immature to spend.
- wallet.scan_blocks(start=chain_height - 100 + 1, num=1)
- utxo_mature = wallet.get_utxo()
- wallet.scan_blocks(start=chain_height - 100 + 2, num=1)
- utxo_immature = wallet.get_utxo()
+ coinbase_txid = lambda h: self.nodes[0].getblock(self.nodes[0].getblockhash(h))['tx'][0]
+ utxo_mature = wallet.get_utxo(txid=coinbase_txid(chain_height - 100 + 1))
+ utxo_immature = wallet.get_utxo(txid=coinbase_txid(chain_height - 100 + 2))
spend_mature_id = wallet.send_self_transfer(from_node=self.nodes[0], utxo_to_spend=utxo_mature)["txid"]
diff --git a/test/functional/p2p_blocksonly.py b/test/functional/p2p_blocksonly.py
index 480bff361d..94ae758d46 100755
--- a/test/functional/p2p_blocksonly.py
+++ b/test/functional/p2p_blocksonly.py
@@ -6,8 +6,7 @@
import time
-from test_framework.blocktools import COINBASE_MATURITY
-from test_framework.messages import msg_tx
+from test_framework.messages import msg_tx, msg_inv, CInv, MSG_WTX
from test_framework.p2p import P2PInterface, P2PTxInvStore
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal
@@ -16,15 +15,13 @@ from test_framework.wallet import MiniWallet
class P2PBlocksOnly(BitcoinTestFramework):
def set_test_params(self):
- self.setup_clean_chain = True
self.num_nodes = 1
self.extra_args = [["-blocksonly"]]
def run_test(self):
self.miniwallet = MiniWallet(self.nodes[0])
# Add enough mature utxos to the wallet, so that all txs spend confirmed coins
- self.generate(self.miniwallet, 2)
- self.generate(self.nodes[0], COINBASE_MATURITY)
+ self.miniwallet.rescan_utxos()
self.blocksonly_mode_tests()
self.blocks_relay_conn_tests()
@@ -36,12 +33,19 @@ class P2PBlocksOnly(BitcoinTestFramework):
self.nodes[0].add_p2p_connection(P2PInterface())
tx, txid, wtxid, tx_hex = self.check_p2p_tx_violation()
+ self.log.info('Check that tx invs also violate the protocol')
+ self.nodes[0].add_p2p_connection(P2PInterface())
+ with self.nodes[0].assert_debug_log(['transaction (0000000000000000000000000000000000000000000000000000000000001234) inv sent in violation of protocol, disconnecting peer']):
+ self.nodes[0].p2ps[0].send_message(msg_inv([CInv(t=MSG_WTX, h=0x1234)]))
+ self.nodes[0].p2ps[0].wait_for_disconnect()
+ del self.nodes[0].p2ps[0]
+
self.log.info('Check that txs from rpc are not rejected and relayed to other peers')
tx_relay_peer = self.nodes[0].add_p2p_connection(P2PInterface())
assert_equal(self.nodes[0].getpeerinfo()[0]['relaytxes'], True)
assert_equal(self.nodes[0].testmempoolaccept([tx_hex])[0]['allowed'], True)
- with self.nodes[0].assert_debug_log(['received getdata for: wtx {} peer=1'.format(wtxid)]):
+ with self.nodes[0].assert_debug_log(['received getdata for: wtx {} peer'.format(wtxid)]):
self.nodes[0].sendrawtransaction(tx_hex)
tx_relay_peer.wait_for_tx(txid)
assert_equal(self.nodes[0].getmempoolinfo()['size'], 1)
@@ -83,7 +87,7 @@ class P2PBlocksOnly(BitcoinTestFramework):
# Ensure we disconnect if a block-relay-only connection sends us a transaction
self.nodes[0].add_outbound_p2p_connection(P2PInterface(), p2p_idx=0, connection_type="block-relay-only")
assert_equal(self.nodes[0].getpeerinfo()[0]['relaytxes'], False)
- _, txid, _, tx_hex = self.check_p2p_tx_violation(index=2)
+ _, txid, _, tx_hex = self.check_p2p_tx_violation()
self.log.info("Check that txs from RPC are not sent to blockrelay connection")
conn = self.nodes[0].add_outbound_p2p_connection(P2PTxInvStore(), p2p_idx=1, connection_type="block-relay-only")
@@ -96,11 +100,9 @@ class P2PBlocksOnly(BitcoinTestFramework):
conn.sync_send_with_ping()
assert(int(txid, 16) not in conn.get_invs())
- def check_p2p_tx_violation(self, index=1):
+ def check_p2p_tx_violation(self):
self.log.info('Check that txs from P2P are rejected and result in disconnect')
- input_txid = self.nodes[0].getblock(self.nodes[0].getblockhash(index), 2)['tx'][0]['txid']
- utxo_to_spend = self.miniwallet.get_utxo(txid=input_txid)
- spendtx = self.miniwallet.create_self_transfer(from_node=self.nodes[0], utxo_to_spend=utxo_to_spend)
+ spendtx = self.miniwallet.create_self_transfer(from_node=self.nodes[0])
with self.nodes[0].assert_debug_log(['transaction sent in violation of protocol peer=0']):
self.nodes[0].p2ps[0].send_message(msg_tx(spendtx['tx']))
diff --git a/test/functional/rpc_blockchain.py b/test/functional/rpc_blockchain.py
index e13de4395b..0600d8b9c5 100755
--- a/test/functional/rpc_blockchain.py
+++ b/test/functional/rpc_blockchain.py
@@ -406,7 +406,7 @@ class BlockchainTest(BitcoinTestFramework):
node = self.nodes[0]
miniwallet = MiniWallet(node)
- miniwallet.scan_blocks(num=5)
+ miniwallet.rescan_utxos()
fee_per_byte = Decimal('0.00000010')
fee_per_kb = 1000 * fee_per_byte
diff --git a/test/functional/rpc_net.py b/test/functional/rpc_net.py
index aa53e354a3..3fcca97cb7 100755
--- a/test/functional/rpc_net.py
+++ b/test/functional/rpc_net.py
@@ -239,7 +239,16 @@ class NetTest(BitcoinTestFramework):
assert_raises_rpc_error(-8, "Network not recognized: Foo", self.nodes[0].getnodeaddresses, 1, "Foo")
def test_addpeeraddress(self):
+ """RPC addpeeraddress sets the source address equal to the destination address.
+ If an address with the same /16 as an existing new entry is passed, it will be
+ placed in the same new bucket and have a 1/64 chance of the bucket positions
+ colliding (depending on the value of nKey in the addrman), in which case the
+ new address won't be added. The probability of collision can be reduced to
+ 1/2^16 = 1/65536 by using an address from a different /16. We avoid this here
+ by first testing adding a tried table entry before testing adding a new table one.
+ """
self.log.info("Test addpeeraddress")
+ self.restart_node(1, ["-checkaddrman=1"])
node = self.nodes[1]
self.log.debug("Test that addpeerinfo is a hidden RPC")
@@ -251,17 +260,25 @@ class NetTest(BitcoinTestFramework):
assert_equal(node.addpeeraddress(address="", port=8333), {"success": False})
assert_equal(node.getnodeaddresses(count=0), [])
- self.log.debug("Test that adding a valid address succeeds")
- assert_equal(node.addpeeraddress(address="1.2.3.4", port=8333), {"success": True})
- addrs = node.getnodeaddresses(count=0)
- assert_equal(len(addrs), 1)
- assert_equal(addrs[0]["address"], "1.2.3.4")
- assert_equal(addrs[0]["port"], 8333)
-
- self.log.debug("Test that adding the same address again when already present fails")
- assert_equal(node.addpeeraddress(address="1.2.3.4", port=8333), {"success": False})
+ self.log.debug("Test that adding a valid address to the tried table succeeds")
+ assert_equal(node.addpeeraddress(address="1.2.3.4", tried=True, port=8333), {"success": True})
+ with node.assert_debug_log(expected_msgs=["Addrman checks started: new 0, tried 1, total 1"]):
+ addrs = node.getnodeaddresses(count=0) # getnodeaddresses re-runs the addrman checks
+ assert_equal(len(addrs), 1)
+ assert_equal(addrs[0]["address"], "1.2.3.4")
+ assert_equal(addrs[0]["port"], 8333)
+
+ self.log.debug("Test that adding an already-present tried address to the new and tried tables fails")
+ for value in [True, False]:
+ assert_equal(node.addpeeraddress(address="1.2.3.4", tried=value, port=8333), {"success": False})
assert_equal(len(node.getnodeaddresses(count=0)), 1)
+ self.log.debug("Test that adding a second address, this time to the new table, succeeds")
+ assert_equal(node.addpeeraddress(address="2.0.0.0", port=8333), {"success": True})
+ with node.assert_debug_log(expected_msgs=["Addrman checks started: new 1, tried 1, total 2"]):
+ addrs = node.getnodeaddresses(count=0) # getnodeaddresses re-runs the addrman checks
+ assert_equal(len(addrs), 2)
+
if __name__ == '__main__':
NetTest().main()
diff --git a/test/functional/test_framework/p2p.py b/test/functional/test_framework/p2p.py
index b7d5bd8fab..ec563cc290 100755
--- a/test/functional/test_framework/p2p.py
+++ b/test/functional/test_framework/p2p.py
@@ -577,6 +577,8 @@ class NetworkThread(threading.Thread):
NetworkThread.listeners = {}
NetworkThread.protos = {}
+ if sys.platform == 'win32':
+ asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
NetworkThread.network_event_loop = asyncio.new_event_loop()
def run(self):
diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py
index ec27fd7f85..d66499dbcb 100644
--- a/test/functional/test_framework/util.py
+++ b/test/functional/test_framework/util.py
@@ -364,6 +364,11 @@ def write_config(config_path, *, n, chain, extra_config="", disable_autoconnect=
f.write("dnsseed=0\n")
f.write("fixedseeds=0\n")
f.write("listenonion=0\n")
+ # Increase peertimeout to avoid disconnects while using mocktime.
+ # peertimeout is measured in wall clock time, so setting it to the
+ # duration of the longest test is sufficient. It can be overriden in
+ # tests.
+ f.write("peertimeout=999999\n")
f.write("printtoconsole=0\n")
f.write("upnp=0\n")
f.write("natpmp=0\n")
diff --git a/test/functional/test_framework/wallet.py b/test/functional/test_framework/wallet.py
index ba5b95f930..2d7f061912 100644
--- a/test/functional/test_framework/wallet.py
+++ b/test/functional/test_framework/wallet.py
@@ -79,12 +79,13 @@ class MiniWallet:
self._address = ADDRESS_BCRT1_P2WSH_OP_TRUE
self._scriptPubKey = bytes.fromhex(self._test_node.validateaddress(self._address)['scriptPubKey'])
- def scan_blocks(self, *, start=1, num):
- """Scan the blocks for self._address outputs and add them to self._utxos"""
- for i in range(start, start + num):
- block = self._test_node.getblock(blockhash=self._test_node.getblockhash(i), verbosity=2)
- for tx in block['tx']:
- self.scan_tx(tx)
+ def rescan_utxos(self):
+ """Drop all utxos and rescan the utxo set"""
+ self._utxos = []
+ res = self._test_node.scantxoutset(action="start", scanobjects=[f'raw({self._scriptPubKey.hex()})'])
+ assert_equal(True, res['success'])
+ for utxo in res['unspents']:
+ self._utxos.append({'txid': utxo['txid'], 'vout': utxo['vout'], 'value': utxo['amount']})
def scan_tx(self, tx):
"""Scan the tx for self._scriptPubKey outputs and add them to self._utxos"""