aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rwxr-xr-xtest/functional/feature_backwards_compatibility.py3
-rwxr-xr-xtest/functional/feature_maxuploadtarget.py12
-rwxr-xr-xtest/functional/p2p_dos_header_tree.py9
-rwxr-xr-xtest/functional/p2p_filter.py11
-rwxr-xr-xtest/functional/p2p_invalid_messages.py1
-rwxr-xr-xtest/functional/p2p_leak.py8
-rwxr-xr-xtest/functional/p2p_leak_tx.py3
-rwxr-xr-xtest/functional/p2p_segwit.py21
-rwxr-xr-xtest/functional/p2p_sendheaders.py7
-rwxr-xr-xtest/functional/p2p_timeouts.py9
-rwxr-xr-xtest/functional/p2p_tx_download.py6
-rwxr-xr-xtest/functional/p2p_unrequested_blocks.py35
-rwxr-xr-xtest/functional/rpc_blockchain.py3
-rwxr-xr-xtest/functional/test_framework/messages.py19
-rwxr-xr-xtest/functional/test_framework/mininode.py3
-rwxr-xr-xtest/functional/test_framework/test_node.py15
-rw-r--r--test/functional/test_framework/util.py6
-rwxr-xr-xtest/functional/wallet_bumpfee.py18
-rwxr-xr-xtest/functional/wallet_multiwallet.py4
-rwxr-xr-xtest/fuzz/test_runner.py1
-rw-r--r--test/sanitizer_suppressions/tsan8
21 files changed, 113 insertions, 89 deletions
diff --git a/test/functional/feature_backwards_compatibility.py b/test/functional/feature_backwards_compatibility.py
index 0db74432e2..adf66243b7 100755
--- a/test/functional/feature_backwards_compatibility.py
+++ b/test/functional/feature_backwards_compatibility.py
@@ -40,6 +40,9 @@ class BackwardsCompatibilityTest(BitcoinTestFramework):
["-nowallet", "-walletrbf=1", "-addresstype=bech32"] # v0.17.1
]
+ def skip_test_if_missing_module(self):
+ self.skip_if_no_wallet()
+
def setup_nodes(self):
if os.getenv("TEST_PREVIOUS_RELEASES") == "false":
raise SkipTest("backwards compatibility tests")
diff --git a/test/functional/feature_maxuploadtarget.py b/test/functional/feature_maxuploadtarget.py
index 974388d798..dc00e03fe7 100755
--- a/test/functional/feature_maxuploadtarget.py
+++ b/test/functional/feature_maxuploadtarget.py
@@ -94,8 +94,7 @@ class MaxUploadTest(BitcoinTestFramework):
# 576MB will be reserved for relaying new blocks, so expect this to
# succeed for ~235 tries.
for i in range(success_count):
- p2p_conns[0].send_message(getdata_request)
- p2p_conns[0].sync_with_ping()
+ p2p_conns[0].send_and_ping(getdata_request)
assert_equal(p2p_conns[0].block_receive_map[big_old_block], i+1)
assert_equal(len(self.nodes[0].getpeerinfo()), 3)
@@ -112,8 +111,7 @@ class MaxUploadTest(BitcoinTestFramework):
# We'll try 800 times
getdata_request.inv = [CInv(2, big_new_block)]
for i in range(800):
- p2p_conns[1].send_message(getdata_request)
- p2p_conns[1].sync_with_ping()
+ p2p_conns[1].send_and_ping(getdata_request)
assert_equal(p2p_conns[1].block_receive_map[big_new_block], i+1)
self.log.info("Peer 1 able to repeatedly download new block")
@@ -132,8 +130,7 @@ class MaxUploadTest(BitcoinTestFramework):
# and p2p_conns[2] should be able to retrieve the old block.
self.nodes[0].setmocktime(int(time.time()))
p2p_conns[2].sync_with_ping()
- p2p_conns[2].send_message(getdata_request)
- p2p_conns[2].sync_with_ping()
+ p2p_conns[2].send_and_ping(getdata_request)
assert_equal(p2p_conns[2].block_receive_map[big_old_block], 1)
self.log.info("Peer 2 able to download old block")
@@ -150,8 +147,7 @@ class MaxUploadTest(BitcoinTestFramework):
#retrieve 20 blocks which should be enough to break the 1MB limit
getdata_request.inv = [CInv(2, big_new_block)]
for i in range(20):
- self.nodes[0].p2p.send_message(getdata_request)
- self.nodes[0].p2p.sync_with_ping()
+ self.nodes[0].p2p.send_and_ping(getdata_request)
assert_equal(self.nodes[0].p2p.block_receive_map[big_new_block], i+1)
getdata_request.inv = [CInv(2, big_old_block)]
diff --git a/test/functional/p2p_dos_header_tree.py b/test/functional/p2p_dos_header_tree.py
index 6676b84e54..28dd809ca5 100755
--- a/test/functional/p2p_dos_header_tree.py
+++ b/test/functional/p2p_dos_header_tree.py
@@ -47,8 +47,7 @@ class RejectLowDifficultyHeadersTest(BitcoinTestFramework):
self.log.info("Feed all non-fork headers, including and up to the first checkpoint")
self.nodes[0].add_p2p_connection(P2PInterface())
- self.nodes[0].p2p.send_message(msg_headers(self.headers))
- self.nodes[0].p2p.sync_with_ping()
+ self.nodes[0].p2p.send_and_ping(msg_headers(self.headers))
assert {
'height': 546,
'hash': '000000002a936ca763904c3c35fce2f3556c559c0214345d31b1bcebf76acb70',
@@ -65,8 +64,7 @@ class RejectLowDifficultyHeadersTest(BitcoinTestFramework):
# On node 0 it succeeds because checkpoints are disabled
self.restart_node(0, extra_args=['-nocheckpoints'])
self.nodes[0].add_p2p_connection(P2PInterface())
- self.nodes[0].p2p.send_message(msg_headers(self.headers_fork))
- self.nodes[0].p2p.sync_with_ping()
+ self.nodes[0].p2p.send_and_ping(msg_headers(self.headers_fork))
assert {
"height": 2,
"hash": "00000000b0494bd6c3d5ff79c497cfce40831871cbf39b1bc28bd1dac817dc39",
@@ -76,8 +74,7 @@ class RejectLowDifficultyHeadersTest(BitcoinTestFramework):
# On node 1 it succeeds because no checkpoint has been reached yet by a chain tip
self.nodes[1].add_p2p_connection(P2PInterface())
- self.nodes[1].p2p.send_message(msg_headers(self.headers_fork))
- self.nodes[1].p2p.sync_with_ping()
+ self.nodes[1].p2p.send_and_ping(msg_headers(self.headers_fork))
assert {
"height": 2,
"hash": "00000000b0494bd6c3d5ff79c497cfce40831871cbf39b1bc28bd1dac817dc39",
diff --git a/test/functional/p2p_filter.py b/test/functional/p2p_filter.py
index ad7a9dcf6e..188b130a57 100755
--- a/test/functional/p2p_filter.py
+++ b/test/functional/p2p_filter.py
@@ -11,6 +11,7 @@ from test_framework.messages import (
MSG_FILTERED_BLOCK,
msg_getdata,
msg_filterload,
+ msg_filteradd,
msg_filterclear,
)
from test_framework.mininode import (
@@ -64,8 +65,7 @@ class FilterTest(BitcoinTestFramework):
def run_test(self):
self.log.info('Add filtered P2P connection to the node')
filter_node = self.nodes[0].add_p2p_connection(FilterNode())
- filter_node.send_message(filter_node.watch_filter_init)
- filter_node.sync_with_ping()
+ filter_node.send_and_ping(filter_node.watch_filter_init)
filter_address = self.nodes[0].decodescript(filter_node.watch_script_pubkey)['addresses'][0]
self.log.info('Check that we receive merkleblock and tx if the filter matches a tx in a block')
@@ -99,12 +99,15 @@ class FilterTest(BitcoinTestFramework):
assert not filter_node.merkleblock_received
self.log.info('Check that after deleting filter all txs get relayed again')
- filter_node.send_message(msg_filterclear())
- filter_node.sync_with_ping()
+ filter_node.send_and_ping(msg_filterclear())
for _ in range(5):
txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 7)
filter_node.wait_for_tx(txid)
+ self.log.info("Check that division-by-zero remote crash bug [CVE-2013-5700] is fixed")
+ filter_node.send_and_ping(msg_filterload(data=b'', nHashFuncs=1))
+ filter_node.send_and_ping(msg_filteradd(data=b'letstrytocrashthisnode'))
+
if __name__ == '__main__':
FilterTest().main()
diff --git a/test/functional/p2p_invalid_messages.py b/test/functional/p2p_invalid_messages.py
index 9876d749ff..759f111e69 100755
--- a/test/functional/p2p_invalid_messages.py
+++ b/test/functional/p2p_invalid_messages.py
@@ -140,7 +140,6 @@ class InvalidMessagesTest(BitcoinTestFramework):
# Node is still up.
conn = node.add_p2p_connection(P2PDataStore())
- conn.sync_with_ping()
def test_magic_bytes(self):
conn = self.nodes[0].add_p2p_connection(P2PDataStore())
diff --git a/test/functional/p2p_leak.py b/test/functional/p2p_leak.py
index 06049db54c..2751ae6a5b 100755
--- a/test/functional/p2p_leak.py
+++ b/test/functional/p2p_leak.py
@@ -19,6 +19,7 @@ from test_framework.util import wait_until
banscore = 10
+
class CLazyNode(P2PInterface):
def __init__(self):
super().__init__()
@@ -88,6 +89,7 @@ class CNodeNoVerackIdle(CLazyNode):
self.send_message(msg_ping())
self.send_message(msg_getaddr())
+
class P2PLeakTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 1
@@ -96,7 +98,11 @@ class P2PLeakTest(BitcoinTestFramework):
def run_test(self):
no_version_bannode = self.nodes[0].add_p2p_connection(CNodeNoVersionBan(), send_version=False, wait_for_verack=False)
no_version_idlenode = self.nodes[0].add_p2p_connection(CNodeNoVersionIdle(), send_version=False, wait_for_verack=False)
- no_verack_idlenode = self.nodes[0].add_p2p_connection(CNodeNoVerackIdle())
+ no_verack_idlenode = self.nodes[0].add_p2p_connection(CNodeNoVerackIdle(), wait_for_verack=False)
+
+ # Wait until we got the verack in response to the version. Though, don't wait for the other node to receive the
+ # verack, since we never sent one
+ no_verack_idlenode.wait_for_verack()
wait_until(lambda: no_version_bannode.ever_connected, timeout=10, lock=mininode_lock)
wait_until(lambda: no_version_idlenode.ever_connected, timeout=10, lock=mininode_lock)
diff --git a/test/functional/p2p_leak_tx.py b/test/functional/p2p_leak_tx.py
index dc4d475b2d..c6fcc5e200 100755
--- a/test/functional/p2p_leak_tx.py
+++ b/test/functional/p2p_leak_tx.py
@@ -39,8 +39,7 @@ class P2PLeakTxTest(BitcoinTestFramework):
want_tx = msg_getdata()
want_tx.inv.append(CInv(t=1, h=int(txid, 16)))
inbound_peer.last_message.pop('notfound', None)
- inbound_peer.send_message(want_tx)
- inbound_peer.sync_with_ping()
+ inbound_peer.send_and_ping(want_tx)
if inbound_peer.last_message.get('notfound'):
self.log.debug('tx {} was not yet announced to us.'.format(txid))
diff --git a/test/functional/p2p_segwit.py b/test/functional/p2p_segwit.py
index 785c476e19..d8dce7fe56 100755
--- a/test/functional/p2p_segwit.py
+++ b/test/functional/p2p_segwit.py
@@ -125,8 +125,7 @@ def test_transaction_acceptance(node, p2p, tx, with_witness, accepted, reason=No
- use the getrawmempool rpc to check for acceptance."""
reason = [reason] if reason else []
with node.assert_debug_log(expected_msgs=reason):
- p2p.send_message(msg_tx(tx) if with_witness else msg_no_witness_tx(tx))
- p2p.sync_with_ping()
+ p2p.send_and_ping(msg_tx(tx) if with_witness else msg_no_witness_tx(tx))
assert_equal(tx.hash in node.getrawmempool(), accepted)
@@ -137,8 +136,7 @@ def test_witness_block(node, p2p, block, accepted, with_witness=True, reason=Non
- use the getbestblockhash rpc to check for acceptance."""
reason = [reason] if reason else []
with node.assert_debug_log(expected_msgs=reason):
- p2p.send_message(msg_block(block) if with_witness else msg_no_witness_block(block))
- p2p.sync_with_ping()
+ p2p.send_and_ping(msg_block(block) if with_witness else msg_no_witness_block(block))
assert_equal(node.getbestblockhash() == block.hash, accepted)
@@ -303,8 +301,7 @@ class SegWitTest(BitcoinTestFramework):
block = self.build_next_block(version=1)
block.solve()
- self.test_node.send_message(msg_no_witness_block(block))
- self.test_node.sync_with_ping() # make sure the block was processed
+ self.test_node.send_and_ping(msg_no_witness_block(block)) # make sure the block was processed
txid = block.vtx[0].sha256
self.nodes[0].generate(99) # let the block mature
@@ -319,8 +316,7 @@ class SegWitTest(BitcoinTestFramework):
# This is a sanity check of our testing framework.
assert_equal(msg_no_witness_tx(tx).serialize(), msg_tx(tx).serialize())
- self.test_node.send_message(msg_tx(tx))
- self.test_node.sync_with_ping() # make sure the tx was processed
+ self.test_node.send_and_ping(msg_tx(tx)) # make sure the block was processed
assert tx.hash in self.nodes[0].getrawmempool()
# Save this transaction for later
self.utxo.append(UTXO(tx.sha256, 0, 49 * 100000000))
@@ -350,8 +346,7 @@ class SegWitTest(BitcoinTestFramework):
# But it should not be permanently marked bad...
# Resend without witness information.
- self.test_node.send_message(msg_no_witness_block(block))
- self.test_node.sync_with_ping()
+ self.test_node.send_and_ping(msg_no_witness_block(block)) # make sure the block was processed
assert_equal(self.nodes[0].getbestblockhash(), block.hash)
# Update our utxo list; we spent the first entry.
@@ -2054,16 +2049,14 @@ class SegWitTest(BitcoinTestFramework):
tx = FromHex(CTransaction(), raw)
assert_raises_rpc_error(-22, "TX decode failed", self.nodes[0].decoderawtransaction, serialize_with_bogus_witness(tx).hex())
with self.nodes[0].assert_debug_log(['Superfluous witness record']):
- self.nodes[0].p2p.send_message(msg_bogus_tx(tx))
- self.nodes[0].p2p.sync_with_ping()
+ self.nodes[0].p2p.send_and_ping(msg_bogus_tx(tx))
raw = self.nodes[0].signrawtransactionwithwallet(raw)
assert raw['complete']
raw = raw['hex']
tx = FromHex(CTransaction(), raw)
assert_raises_rpc_error(-22, "TX decode failed", self.nodes[0].decoderawtransaction, serialize_with_bogus_witness(tx).hex())
with self.nodes[0].assert_debug_log(['Unknown transaction optional data']):
- self.nodes[0].p2p.send_message(msg_bogus_tx(tx))
- self.nodes[0].p2p.sync_with_ping()
+ self.nodes[0].p2p.send_and_ping(msg_bogus_tx(tx))
if __name__ == '__main__':
diff --git a/test/functional/p2p_sendheaders.py b/test/functional/p2p_sendheaders.py
index 161b67e6d0..84d818400a 100755
--- a/test/functional/p2p_sendheaders.py
+++ b/test/functional/p2p_sendheaders.py
@@ -243,10 +243,6 @@ class SendHeadersTest(BitcoinTestFramework):
# will occur outside of direct fetching
test_node = self.nodes[0].add_p2p_connection(BaseNode(), services=NODE_WITNESS)
- # Ensure verack's have been processed by our peer
- inv_node.sync_with_ping()
- test_node.sync_with_ping()
-
self.test_null_locators(test_node, inv_node)
self.test_nonnull_locators(test_node, inv_node)
@@ -307,8 +303,7 @@ class SendHeadersTest(BitcoinTestFramework):
new_block.solve()
test_node.send_header_for_blocks([new_block])
test_node.wait_for_getdata([new_block.sha256])
- test_node.send_message(msg_block(new_block))
- test_node.sync_with_ping() # make sure this block is processed
+ test_node.send_and_ping(msg_block(new_block)) # make sure this block is processed
wait_until(lambda: inv_node.block_announced, timeout=60, lock=mininode_lock)
inv_node.clear_block_announcements()
test_node.clear_block_announcements()
diff --git a/test/functional/p2p_timeouts.py b/test/functional/p2p_timeouts.py
index 02ceec3dc1..c1235f8a6b 100755
--- a/test/functional/p2p_timeouts.py
+++ b/test/functional/p2p_timeouts.py
@@ -27,11 +27,13 @@ from test_framework.messages import msg_ping
from test_framework.mininode import P2PInterface
from test_framework.test_framework import BitcoinTestFramework
+
class TestP2PConn(P2PInterface):
def on_version(self, message):
# Don't send a verack in response
pass
+
class TimeoutsTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
@@ -41,10 +43,14 @@ class TimeoutsTest(BitcoinTestFramework):
def run_test(self):
# Setup the p2p connections
- no_verack_node = self.nodes[0].add_p2p_connection(TestP2PConn())
+ no_verack_node = self.nodes[0].add_p2p_connection(TestP2PConn(), wait_for_verack=False)
no_version_node = self.nodes[0].add_p2p_connection(TestP2PConn(), send_version=False, wait_for_verack=False)
no_send_node = self.nodes[0].add_p2p_connection(TestP2PConn(), send_version=False, wait_for_verack=False)
+ # Wait until we got the verack in response to the version. Though, don't wait for the other node to receive the
+ # verack, since we never sent one
+ no_verack_node.wait_for_verack()
+
sleep(1)
assert no_verack_node.is_connected
@@ -81,5 +87,6 @@ class TimeoutsTest(BitcoinTestFramework):
assert not no_version_node.is_connected
assert not no_send_node.is_connected
+
if __name__ == '__main__':
TimeoutsTest().main()
diff --git a/test/functional/p2p_tx_download.py b/test/functional/p2p_tx_download.py
index aada04f66f..b56dc994e7 100755
--- a/test/functional/p2p_tx_download.py
+++ b/test/functional/p2p_tx_download.py
@@ -65,8 +65,7 @@ class TxDownloadTest(BitcoinTestFramework):
self.log.info("Announce the txid from each incoming peer to node 0")
msg = msg_inv([CInv(t=1, h=txid)])
for p in self.nodes[0].p2ps:
- p.send_message(msg)
- p.sync_with_ping()
+ p.send_and_ping(msg)
outstanding_peer_index = [i for i in range(len(self.nodes[0].p2ps))]
@@ -107,8 +106,7 @@ class TxDownloadTest(BitcoinTestFramework):
"Announce the transaction to all nodes from all {} incoming peers, but never send it".format(NUM_INBOUND))
msg = msg_inv([CInv(t=1, h=txid)])
for p in self.peers:
- p.send_message(msg)
- p.sync_with_ping()
+ p.send_and_ping(msg)
self.log.info("Put the tx in node 0's mempool")
self.nodes[0].sendrawtransaction(tx)
diff --git a/test/functional/p2p_unrequested_blocks.py b/test/functional/p2p_unrequested_blocks.py
index 534d275c28..d18d4b069a 100755
--- a/test/functional/p2p_unrequested_blocks.py
+++ b/test/functional/p2p_unrequested_blocks.py
@@ -97,11 +97,9 @@ class AcceptBlockTest(BitcoinTestFramework):
blocks_h2.append(create_block(tips[i], create_coinbase(2), block_time))
blocks_h2[i].solve()
block_time += 1
- test_node.send_message(msg_block(blocks_h2[0]))
- min_work_node.send_message(msg_block(blocks_h2[1]))
+ test_node.send_and_ping(msg_block(blocks_h2[0]))
+ min_work_node.send_and_ping(msg_block(blocks_h2[1]))
- for x in [test_node, min_work_node]:
- x.sync_with_ping()
assert_equal(self.nodes[0].getblockcount(), 2)
assert_equal(self.nodes[1].getblockcount(), 1)
self.log.info("First height 2 block accepted by node0; correctly rejected by node1")
@@ -110,9 +108,8 @@ class AcceptBlockTest(BitcoinTestFramework):
block_h1f = create_block(int("0x" + self.nodes[0].getblockhash(0), 0), create_coinbase(1), block_time)
block_time += 1
block_h1f.solve()
- test_node.send_message(msg_block(block_h1f))
+ test_node.send_and_ping(msg_block(block_h1f))
- test_node.sync_with_ping()
tip_entry_found = False
for x in self.nodes[0].getchaintips():
if x['hash'] == block_h1f.hash:
@@ -125,9 +122,8 @@ class AcceptBlockTest(BitcoinTestFramework):
block_h2f = create_block(block_h1f.sha256, create_coinbase(2), block_time)
block_time += 1
block_h2f.solve()
- test_node.send_message(msg_block(block_h2f))
+ test_node.send_and_ping(msg_block(block_h2f))
- test_node.sync_with_ping()
# Since the earlier block was not processed by node, the new block
# can't be fully validated.
tip_entry_found = False
@@ -144,9 +140,8 @@ class AcceptBlockTest(BitcoinTestFramework):
# 4b. Now send another block that builds on the forking chain.
block_h3 = create_block(block_h2f.sha256, create_coinbase(3), block_h2f.nTime+1)
block_h3.solve()
- test_node.send_message(msg_block(block_h3))
+ test_node.send_and_ping(msg_block(block_h3))
- test_node.sync_with_ping()
# Since the earlier block was not processed by node, the new block
# can't be fully validated.
tip_entry_found = False
@@ -172,8 +167,7 @@ class AcceptBlockTest(BitcoinTestFramework):
tip = next_block
# Now send the block at height 5 and check that it wasn't accepted (missing header)
- test_node.send_message(msg_block(all_blocks[1]))
- test_node.sync_with_ping()
+ test_node.send_and_ping(msg_block(all_blocks[1]))
assert_raises_rpc_error(-5, "Block not found", self.nodes[0].getblock, all_blocks[1].hash)
assert_raises_rpc_error(-5, "Block not found", self.nodes[0].getblockheader, all_blocks[1].hash)
@@ -181,8 +175,7 @@ class AcceptBlockTest(BitcoinTestFramework):
headers_message = msg_headers()
headers_message.headers.append(CBlockHeader(all_blocks[0]))
test_node.send_message(headers_message)
- test_node.send_message(msg_block(all_blocks[1]))
- test_node.sync_with_ping()
+ test_node.send_and_ping(msg_block(all_blocks[1]))
self.nodes[0].getblock(all_blocks[1].hash)
# Now send the blocks in all_blocks
@@ -207,9 +200,7 @@ class AcceptBlockTest(BitcoinTestFramework):
test_node = self.nodes[0].add_p2p_connection(P2PInterface())
- test_node.send_message(msg_block(block_h1f))
-
- test_node.sync_with_ping()
+ test_node.send_and_ping(msg_block(block_h1f))
assert_equal(self.nodes[0].getblockcount(), 2)
self.log.info("Unrequested block that would complete more-work chain was ignored")
@@ -230,9 +221,7 @@ class AcceptBlockTest(BitcoinTestFramework):
self.log.info("Inv at tip triggered getdata for unprocessed block")
# 7. Send the missing block for the third time (now it is requested)
- test_node.send_message(msg_block(block_h1f))
-
- test_node.sync_with_ping()
+ test_node.send_and_ping(msg_block(block_h1f))
assert_equal(self.nodes[0].getblockcount(), 290)
self.nodes[0].getblock(all_blocks[286].hash)
assert_equal(self.nodes[0].getbestblockhash(), all_blocks[286].hash)
@@ -259,9 +248,8 @@ class AcceptBlockTest(BitcoinTestFramework):
headers_message.headers.append(CBlockHeader(block_290f))
headers_message.headers.append(CBlockHeader(block_291))
headers_message.headers.append(CBlockHeader(block_292))
- test_node.send_message(headers_message)
+ test_node.send_and_ping(headers_message)
- test_node.sync_with_ping()
tip_entry_found = False
for x in self.nodes[0].getchaintips():
if x['hash'] == block_292.hash:
@@ -271,9 +259,8 @@ class AcceptBlockTest(BitcoinTestFramework):
assert_raises_rpc_error(-1, "Block not found on disk", self.nodes[0].getblock, block_292.hash)
test_node.send_message(msg_block(block_289f))
- test_node.send_message(msg_block(block_290f))
+ test_node.send_and_ping(msg_block(block_290f))
- test_node.sync_with_ping()
self.nodes[0].getblock(block_289f.hash)
self.nodes[0].getblock(block_290f.hash)
diff --git a/test/functional/rpc_blockchain.py b/test/functional/rpc_blockchain.py
index adf6f1ca4f..a6eaaa4539 100755
--- a/test/functional/rpc_blockchain.py
+++ b/test/functional/rpc_blockchain.py
@@ -315,8 +315,7 @@ class BlockchainTest(BitcoinTestFramework):
def solve_and_send_block(prevhash, height, time):
b = create_block(prevhash, create_coinbase(height), time)
b.solve()
- node.p2p.send_message(msg_block(b))
- node.p2p.sync_with_ping()
+ node.p2p.send_and_ping(msg_block(b))
return b
b21f = solve_and_send_block(int(b20hash, 16), 21, b20['time'] + 1)
diff --git a/test/functional/test_framework/messages.py b/test/functional/test_framework/messages.py
index ff0c763b72..5f8fcc6fd8 100755
--- a/test/functional/test_framework/messages.py
+++ b/test/functional/test_framework/messages.py
@@ -1356,6 +1356,25 @@ class msg_filterload:
self.data, self.nHashFuncs, self.nTweak, self.nFlags)
+class msg_filteradd:
+ __slots__ = ("data")
+ command = b"filteradd"
+
+ def __init__(self, data):
+ self.data = data
+
+ def deserialize(self, f):
+ self.data = deser_string(f)
+
+ def serialize(self):
+ r = b""
+ r += ser_string(self.data)
+ return r
+
+ def __repr__(self):
+ return "msg_filteradd(data={})".format(self.data)
+
+
class msg_filterclear:
__slots__ = ()
command = b"filterclear"
diff --git a/test/functional/test_framework/mininode.py b/test/functional/test_framework/mininode.py
index ce51513ce9..ad330f2a93 100755
--- a/test/functional/test_framework/mininode.py
+++ b/test/functional/test_framework/mininode.py
@@ -30,6 +30,7 @@ from test_framework.messages import (
msg_blocktxn,
msg_cmpctblock,
msg_feefilter,
+ msg_filteradd,
msg_filterclear,
msg_filterload,
msg_getaddr,
@@ -65,6 +66,7 @@ MESSAGEMAP = {
b"blocktxn": msg_blocktxn,
b"cmpctblock": msg_cmpctblock,
b"feefilter": msg_feefilter,
+ b"filteradd": msg_filteradd,
b"filterclear": msg_filterclear,
b"filterload": msg_filterload,
b"getaddr": msg_getaddr,
@@ -324,6 +326,7 @@ class P2PInterface(P2PConnection):
def on_blocktxn(self, message): pass
def on_cmpctblock(self, message): pass
def on_feefilter(self, message): pass
+ def on_filteradd(self, message): pass
def on_filterclear(self, message): pass
def on_filterload(self, message): pass
def on_getaddr(self, message): pass
diff --git a/test/functional/test_framework/test_node.py b/test/functional/test_framework/test_node.py
index c7559ac7c8..8260c917fe 100755
--- a/test/functional/test_framework/test_node.py
+++ b/test/functional/test_framework/test_node.py
@@ -468,7 +468,19 @@ class TestNode():
p2p_conn.peer_connect(**kwargs, net=self.chain)()
self.p2ps.append(p2p_conn)
if wait_for_verack:
+ # Wait for the node to send us the version and verack
p2p_conn.wait_for_verack()
+ # At this point we have sent our version message and received the version and verack, however the full node
+ # has not yet received the verack from us (in reply to their version). So, the connection is not yet fully
+ # established (fSuccessfullyConnected).
+ #
+ # This shouldn't lead to any issues when sending messages, since the verack will be in-flight before the
+ # message we send. However, it might lead to races where we are expecting to receive a message. E.g. a
+ # transaction that will be added to the mempool as soon as we return here.
+ #
+ # So syncing here is redundant when we only want to send a message, but the cost is low (a few milliseconds)
+ # in comparision to the upside of making tests less fragile and unexpected intermittent errors less likely.
+ p2p_conn.sync_with_ping()
return p2p_conn
@@ -487,6 +499,7 @@ class TestNode():
p.peer_disconnect()
del self.p2ps[:]
+
class TestNodeCLIAttr:
def __init__(self, cli, command):
self.cli = cli
@@ -498,6 +511,7 @@ class TestNodeCLIAttr:
def get_request(self, *args, **kwargs):
return lambda: self(*args, **kwargs)
+
def arg_to_cli(arg):
if isinstance(arg, bool):
return str(arg).lower()
@@ -506,6 +520,7 @@ def arg_to_cli(arg):
else:
return str(arg)
+
class TestNodeCLI():
"""Interface to bitcoin-cli for an individual node"""
diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py
index 5bb73aee7e..e89b4e9879 100644
--- a/test/functional/test_framework/util.py
+++ b/test/functional/test_framework/util.py
@@ -393,6 +393,7 @@ def connect_nodes(from_connection, node_num):
# with transaction relaying
wait_until(lambda: all(peer['version'] != 0 for peer in from_connection.getpeerinfo()))
+
def sync_blocks(rpc_connections, *, wait=1, timeout=60):
"""
Wait until everybody has the same tip.
@@ -406,9 +407,12 @@ def sync_blocks(rpc_connections, *, wait=1, timeout=60):
best_hash = [x.getbestblockhash() for x in rpc_connections]
if best_hash.count(best_hash[0]) == len(rpc_connections):
return
+ # Check that each peer has at least one connection
+ assert (all([len(x.getpeerinfo()) for x in rpc_connections]))
time.sleep(wait)
raise AssertionError("Block sync timed out:{}".format("".join("\n {!r}".format(b) for b in best_hash)))
+
def sync_mempools(rpc_connections, *, wait=1, timeout=60, flush_scheduler=True):
"""
Wait until everybody has the same transactions in their memory
@@ -422,6 +426,8 @@ def sync_mempools(rpc_connections, *, wait=1, timeout=60, flush_scheduler=True):
for r in rpc_connections:
r.syncwithvalidationinterfacequeue()
return
+ # Check that each peer has at least one connection
+ assert (all([len(x.getpeerinfo()) for x in rpc_connections]))
time.sleep(wait)
raise AssertionError("Mempool sync timed out:{}".format("".join("\n {!r}".format(m) for m in pool)))
diff --git a/test/functional/wallet_bumpfee.py b/test/functional/wallet_bumpfee.py
index 38c9807757..2e6a3e0ce4 100755
--- a/test/functional/wallet_bumpfee.py
+++ b/test/functional/wallet_bumpfee.py
@@ -253,12 +253,18 @@ def test_dust_to_fee(self, rbf_node, dest_address):
self.log.info('Test that bumped output that is dust is dropped to fee')
rbfid = spend_one_input(rbf_node, dest_address)
fulltx = rbf_node.getrawtransaction(rbfid, 1)
- # size of transaction (p2wpkh, 1 input, 2 outputs): 141 vbytes
- assert_equal(fulltx["vsize"], 141)
- # bump with fee_rate of 0.00350000 BTC per 1000 vbytes
- # expected bump fee of 141 vbytes * fee_rate 0.00350000 BTC / 1000 vbytes = 0.00049350 BTC
- # but dust is dropped, so actual bump fee is 0.00050000
- bumped_tx = rbf_node.bumpfee(rbfid, {"fee_rate": 0.0035})
+ # The DER formatting used by Bitcoin to serialize ECDSA signatures means that signatures can have a
+ # variable size of 70-72 bytes (or possibly even less), with most being 71 or 72 bytes. The signature
+ # in the witness is divided by 4 for the vsize, so this variance can take the weight across a 4-byte
+ # boundary. Thus expected transaction size (p2wpkh, 1 input, 2 outputs) is 140-141 vbytes, usually 141.
+ if not 140 <= fulltx["vsize"] <= 141:
+ print("Error: Invalid tx vsize of {} (140-141 expected), full tx: {}".format(fulltx["vsize"], fulltx))
+ raise AssertionError
+ # Bump with fee_rate of 0.00350250 BTC per 1000 vbytes to create dust.
+ # Expected fee is 141 vbytes * fee_rate 0.00350250 BTC / 1000 vbytes = 0.00049385 BTC.
+ # or occasionally 140 vbytes * fee_rate 0.00350250 BTC / 1000 vbytes = 0.00049035 BTC.
+ # Dust should be dropped to the fee, so actual bump fee is 0.00050000 BTC.
+ bumped_tx = rbf_node.bumpfee(rbfid, {"fee_rate": 0.00350250})
full_bumped_tx = rbf_node.getrawtransaction(bumped_tx["txid"], 1)
assert_equal(bumped_tx["fee"], Decimal("0.00050000"))
assert_equal(len(fulltx["vout"]), 2)
diff --git a/test/functional/wallet_multiwallet.py b/test/functional/wallet_multiwallet.py
index 78ead514a5..a2c502f280 100755
--- a/test/functional/wallet_multiwallet.py
+++ b/test/functional/wallet_multiwallet.py
@@ -236,10 +236,10 @@ class MultiWalletTest(BitcoinTestFramework):
assert_raises_rpc_error(-4, "Wallet file verification failed: Error loading wallet wallet.dat. Duplicate -wallet filename specified.", self.nodes[0].loadwallet, 'wallet.dat')
# Fail to load if one wallet is a copy of another
- assert_raises_rpc_error(-1, "BerkeleyBatch: Can't open database w8_copy (duplicates fileid", self.nodes[0].loadwallet, 'w8_copy')
+ assert_raises_rpc_error(-4, "BerkeleyBatch: Can't open database w8_copy (duplicates fileid", self.nodes[0].loadwallet, 'w8_copy')
# Fail to load if one wallet is a copy of another, test this twice to make sure that we don't re-introduce #14304
- assert_raises_rpc_error(-1, "BerkeleyBatch: Can't open database w8_copy (duplicates fileid", self.nodes[0].loadwallet, 'w8_copy')
+ assert_raises_rpc_error(-4, "BerkeleyBatch: Can't open database w8_copy (duplicates fileid", self.nodes[0].loadwallet, 'w8_copy')
# Fail to load if wallet file is a symlink
diff --git a/test/fuzz/test_runner.py b/test/fuzz/test_runner.py
index 1786c39c36..bb93060739 100755
--- a/test/fuzz/test_runner.py
+++ b/test/fuzz/test_runner.py
@@ -131,6 +131,7 @@ def main():
build_dir=config["environment"]["BUILDDIR"],
merge_dir=args.m_dir,
)
+ return
run_once(
corpus=args.seed_dir,
diff --git a/test/sanitizer_suppressions/tsan b/test/sanitizer_suppressions/tsan
index b9c5c038d0..70eea34363 100644
--- a/test/sanitizer_suppressions/tsan
+++ b/test/sanitizer_suppressions/tsan
@@ -7,14 +7,6 @@ deadlock:WalletBatch
# Intentional deadlock in tests
deadlock:TestPotentialDeadLockDetected
-# Race due to unprotected calls to thread-unsafe BOOST_TEST_MESSAGE from different threads:
-# * G_TEST_LOG_FUN in the index thread
-# * boost test case invoker (entering a test case) in the main thread
-# TODO: get rid of BOOST_ macros, see also https://github.com/bitcoin/bitcoin/issues/8670
-race:blockfilter_index_initial_sync_invoker
-race:txindex_initial_sync_invoker
-race:validation_block_tests::TestSubscriber
-
# Wildcard for all gui tests, should be replaced with non-wildcard suppressions
race:src/qt/test/*
deadlock:src/qt/test/*