diff options
Diffstat (limited to 'test')
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/* |