diff options
Diffstat (limited to 'test')
36 files changed, 259 insertions, 199 deletions
diff --git a/test/functional/README.md b/test/functional/README.md index 0d85a74074..82b30fed51 100644 --- a/test/functional/README.md +++ b/test/functional/README.md @@ -87,7 +87,9 @@ P2P messages. These can be found in the following source files: #### Using the P2P interface -- [messages.py](test_framework/messages.py) contains all the definitions for objects that pass +- `P2P`s can be used to test specific P2P protocol behavior. +[p2p.py](test_framework/p2p.py) contains test framework p2p objects and +[messages.py](test_framework/messages.py) contains all the definitions for objects passed over the network (`CBlock`, `CTransaction`, etc, along with the network-level wrappers for them, `msg_block`, `msg_tx`, etc). @@ -100,8 +102,22 @@ contains the higher level logic for processing P2P payloads and connecting to the Bitcoin Core node application logic. For custom behaviour, subclass the P2PInterface object and override the callback methods. -- Can be used to write tests where specific P2P protocol behavior is tested. -Examples tests are [p2p_unrequested_blocks.py](p2p_unrequested_blocks.py), +`P2PConnection`s can be used as such: + +```python +p2p_conn = node.add_p2p_connection(P2PInterface()) +p2p_conn.send_and_ping(msg) +``` + +They can also be referenced by indexing into a `TestNode`'s `p2ps` list, which +contains the list of test framework `p2p` objects connected to itself +(it does not include any `TestNode`s): + +```python +node.p2ps[0].sync_with_ping() +``` + +More examples can be found in [p2p_unrequested_blocks.py](p2p_unrequested_blocks.py), [p2p_compactblocks.py](p2p_compactblocks.py). #### Prototyping tests @@ -157,7 +173,7 @@ way is the use the `profile_with_perf` context manager, e.g. with node.profile_with_perf("send-big-msgs"): # Perform activity on the node you're interested in profiling, e.g.: for _ in range(10000): - node.p2p.send_message(some_large_message) + node.p2ps[0].send_message(some_large_message) ``` To see useful textual output, run diff --git a/test/functional/example_test.py b/test/functional/example_test.py index 083deb6460..3b9bd3048f 100755 --- a/test/functional/example_test.py +++ b/test/functional/example_test.py @@ -136,7 +136,7 @@ class ExampleTest(BitcoinTestFramework): """Main test logic""" # Create P2P connections will wait for a verack to make sure the connection is fully up - self.nodes[0].add_p2p_connection(BaseNode()) + peer_messaging = self.nodes[0].add_p2p_connection(BaseNode()) # Generating a block on one of the nodes will get us out of IBD blocks = [int(self.nodes[0].generate(nblocks=1)[0], 16)] @@ -173,7 +173,7 @@ class ExampleTest(BitcoinTestFramework): block.solve() block_message = msg_block(block) # Send message is used to send a P2P message to the node over our P2PInterface - self.nodes[0].p2p.send_message(block_message) + peer_messaging.send_message(block_message) self.tip = block.sha256 blocks.append(self.tip) self.block_time += 1 @@ -191,25 +191,25 @@ class ExampleTest(BitcoinTestFramework): self.log.info("Add P2P connection to node2") self.nodes[0].disconnect_p2ps() - self.nodes[2].add_p2p_connection(BaseNode()) + peer_receiving = self.nodes[2].add_p2p_connection(BaseNode()) self.log.info("Test that node2 propagates all the blocks to us") getdata_request = msg_getdata() for block in blocks: getdata_request.inv.append(CInv(MSG_BLOCK, block)) - self.nodes[2].p2p.send_message(getdata_request) + peer_receiving.send_message(getdata_request) # wait_until() will loop until a predicate condition is met. Use it to test properties of the # P2PInterface objects. - self.nodes[2].p2p.wait_until(lambda: sorted(blocks) == sorted(list(self.nodes[2].p2p.block_receive_map.keys())), timeout=5) + peer_receiving.wait_until(lambda: sorted(blocks) == sorted(list(peer_receiving.block_receive_map.keys())), timeout=5) self.log.info("Check that each block was received only once") # The network thread uses a global lock on data access to the P2PConnection objects when sending and receiving # messages. The test thread should acquire the global lock before accessing any P2PConnection data to avoid locking # and synchronization issues. Note p2p.wait_until() acquires this global lock internally when testing the predicate. with p2p_lock: - for block in self.nodes[2].p2p.block_receive_map.values(): + for block in peer_receiving.block_receive_map.values(): assert_equal(block, 1) diff --git a/test/functional/feature_block.py b/test/functional/feature_block.py index efafcfaec3..19753d73ef 100755 --- a/test/functional/feature_block.py +++ b/test/functional/feature_block.py @@ -1386,14 +1386,14 @@ class FullBlockTest(BitcoinTestFramework): """Add a P2P connection to the node. Helper to connect and wait for version handshake.""" - self.nodes[0].add_p2p_connection(P2PDataStore()) + self.helper_peer = self.nodes[0].add_p2p_connection(P2PDataStore()) # We need to wait for the initial getheaders from the peer before we # start populating our blockstore. If we don't, then we may run ahead # to the next subtest before we receive the getheaders. We'd then send # an INV for the next block and receive two getheaders - one for the # IBD and one for the INV. We'd respond to both and could get # unexpectedly disconnected if the DoS score for that error is 50. - self.nodes[0].p2p.wait_for_getheaders(timeout=timeout) + self.helper_peer.wait_for_getheaders(timeout=timeout) def reconnect_p2p(self, timeout=60): """Tear down and bootstrap the P2P connection to the node. @@ -1407,7 +1407,7 @@ class FullBlockTest(BitcoinTestFramework): """Sends blocks to test node. Syncs and verifies that tip has advanced to most recent block. Call with success = False if the tip shouldn't advance to the most recent block.""" - self.nodes[0].p2p.send_blocks_and_test(blocks, self.nodes[0], success=success, reject_reason=reject_reason, force_send=force_send, timeout=timeout, expect_disconnect=reconnect) + self.helper_peer.send_blocks_and_test(blocks, self.nodes[0], success=success, reject_reason=reject_reason, force_send=force_send, timeout=timeout, expect_disconnect=reconnect) if reconnect: self.reconnect_p2p(timeout=timeout) diff --git a/test/functional/feature_cltv.py b/test/functional/feature_cltv.py index 2919b0ea0b..aad255c4a9 100755 --- a/test/functional/feature_cltv.py +++ b/test/functional/feature_cltv.py @@ -75,7 +75,7 @@ class BIP65Test(BitcoinTestFramework): ) def run_test(self): - self.nodes[0].add_p2p_connection(P2PInterface()) + peer = self.nodes[0].add_p2p_connection(P2PInterface()) self.test_cltv_info(is_active=False) @@ -99,7 +99,7 @@ class BIP65Test(BitcoinTestFramework): block.solve() self.test_cltv_info(is_active=False) # Not active as of current tip and next block does not need to obey rules - self.nodes[0].p2p.send_and_ping(msg_block(block)) + peer.send_and_ping(msg_block(block)) self.test_cltv_info(is_active=True) # Not active as of current tip, but next block must obey rules assert_equal(self.nodes[0].getbestblockhash(), block.hash) @@ -111,9 +111,9 @@ class BIP65Test(BitcoinTestFramework): block.solve() with self.nodes[0].assert_debug_log(expected_msgs=['{}, bad-version(0x00000003)'.format(block.hash)]): - self.nodes[0].p2p.send_and_ping(msg_block(block)) + peer.send_and_ping(msg_block(block)) assert_equal(int(self.nodes[0].getbestblockhash(), 16), tip) - self.nodes[0].p2p.sync_with_ping() + peer.sync_with_ping() self.log.info("Test that invalid-according-to-cltv transactions cannot appear in a block") block.nVersion = 4 @@ -136,9 +136,9 @@ class BIP65Test(BitcoinTestFramework): block.solve() with self.nodes[0].assert_debug_log(expected_msgs=['CheckInputScripts on {} failed with non-mandatory-script-verify-flag (Negative locktime)'.format(block.vtx[-1].hash)]): - self.nodes[0].p2p.send_and_ping(msg_block(block)) + peer.send_and_ping(msg_block(block)) assert_equal(int(self.nodes[0].getbestblockhash(), 16), tip) - self.nodes[0].p2p.sync_with_ping() + peer.sync_with_ping() self.log.info("Test that a version 4 block with a valid-according-to-CLTV transaction is accepted") spendtx = cltv_validate(self.nodes[0], spendtx, CLTV_HEIGHT - 1) @@ -150,7 +150,7 @@ class BIP65Test(BitcoinTestFramework): block.solve() self.test_cltv_info(is_active=True) # Not active as of current tip, but next block must obey rules - self.nodes[0].p2p.send_and_ping(msg_block(block)) + peer.send_and_ping(msg_block(block)) self.test_cltv_info(is_active=True) # Active as of current tip assert_equal(int(self.nodes[0].getbestblockhash(), 16), block.sha256) diff --git a/test/functional/feature_config_args.py b/test/functional/feature_config_args.py index 34e856c1ba..b4355a6587 100755 --- a/test/functional/feature_config_args.py +++ b/test/functional/feature_config_args.py @@ -78,6 +78,12 @@ class ConfArgsTest(BitcoinTestFramework): with open(inc_conf_file2_path, 'w', encoding='utf-8') as conf: conf.write('') # clear + def test_invalid_command_line_options(self): + self.nodes[0].assert_start_raises_init_error( + expected_msg='Error: No proxy server specified. Use -proxy=<ip> or -proxy=<ip:port>.', + extra_args=['-proxy'], + ) + def test_log_buffer(self): with self.nodes[0].assert_debug_log(expected_msgs=['Warning: parsed potentially confusing double-negative -connect=0\n']): self.start_node(0, extra_args=['-noconnect=0']) @@ -146,6 +152,7 @@ class ConfArgsTest(BitcoinTestFramework): self.test_networkactive() self.test_config_file_parser() + self.test_invalid_command_line_options() # Remove the -datadir argument so it doesn't override the config file self.nodes[0].args = [arg for arg in self.nodes[0].args if not arg.startswith("-datadir")] diff --git a/test/functional/feature_csv_activation.py b/test/functional/feature_csv_activation.py index 38e95f00e9..39e8bca751 100755 --- a/test/functional/feature_csv_activation.py +++ b/test/functional/feature_csv_activation.py @@ -182,10 +182,10 @@ class BIP68_112_113Test(BitcoinTestFramework): """Sends blocks to test node. Syncs and verifies that tip has advanced to most recent block. Call with success = False if the tip shouldn't advance to the most recent block.""" - self.nodes[0].p2p.send_blocks_and_test(blocks, self.nodes[0], success=success, reject_reason=reject_reason) + self.helper_peer.send_blocks_and_test(blocks, self.nodes[0], success=success, reject_reason=reject_reason) def run_test(self): - self.nodes[0].add_p2p_connection(P2PDataStore()) + self.helper_peer = self.nodes[0].add_p2p_connection(P2PDataStore()) self.log.info("Generate blocks in the past for coinbase outputs.") long_past_time = int(time.time()) - 600 * 1000 # enough to build up to 1000 blocks 10 minutes apart without worrying about getting into the future diff --git a/test/functional/feature_dersig.py b/test/functional/feature_dersig.py index f263c93c8a..3f7efdbded 100755 --- a/test/functional/feature_dersig.py +++ b/test/functional/feature_dersig.py @@ -59,7 +59,7 @@ class BIP66Test(BitcoinTestFramework): ) def run_test(self): - self.nodes[0].add_p2p_connection(P2PInterface()) + peer = self.nodes[0].add_p2p_connection(P2PInterface()) self.test_dersig_info(is_active=False) @@ -84,7 +84,7 @@ class BIP66Test(BitcoinTestFramework): block.solve() self.test_dersig_info(is_active=False) # Not active as of current tip and next block does not need to obey rules - self.nodes[0].p2p.send_and_ping(msg_block(block)) + peer.send_and_ping(msg_block(block)) self.test_dersig_info(is_active=True) # Not active as of current tip, but next block must obey rules assert_equal(self.nodes[0].getbestblockhash(), block.hash) @@ -97,9 +97,9 @@ class BIP66Test(BitcoinTestFramework): block.solve() with self.nodes[0].assert_debug_log(expected_msgs=['{}, bad-version(0x00000002)'.format(block.hash)]): - self.nodes[0].p2p.send_and_ping(msg_block(block)) + peer.send_and_ping(msg_block(block)) assert_equal(int(self.nodes[0].getbestblockhash(), 16), tip) - self.nodes[0].p2p.sync_with_ping() + peer.sync_with_ping() self.log.info("Test that transactions with non-DER signatures cannot appear in a block") block.nVersion = 3 @@ -123,9 +123,9 @@ class BIP66Test(BitcoinTestFramework): block.solve() with self.nodes[0].assert_debug_log(expected_msgs=['CheckInputScripts on {} failed with non-mandatory-script-verify-flag (Non-canonical DER signature)'.format(block.vtx[-1].hash)]): - self.nodes[0].p2p.send_and_ping(msg_block(block)) + peer.send_and_ping(msg_block(block)) assert_equal(int(self.nodes[0].getbestblockhash(), 16), tip) - self.nodes[0].p2p.sync_with_ping() + peer.sync_with_ping() self.log.info("Test that a version 3 block with a DERSIG-compliant transaction is accepted") block.vtx[1] = create_transaction(self.nodes[0], self.coinbase_txids[1], self.nodeaddress, amount=1.0) @@ -134,7 +134,7 @@ class BIP66Test(BitcoinTestFramework): block.solve() self.test_dersig_info(is_active=True) # Not active as of current tip, but next block must obey rules - self.nodes[0].p2p.send_and_ping(msg_block(block)) + peer.send_and_ping(msg_block(block)) self.test_dersig_info(is_active=True) # Active as of current tip assert_equal(int(self.nodes[0].getbestblockhash(), 16), block.sha256) diff --git a/test/functional/feature_maxuploadtarget.py b/test/functional/feature_maxuploadtarget.py index e5c62d1ea7..d0a94658ff 100755 --- a/test/functional/feature_maxuploadtarget.py +++ b/test/functional/feature_maxuploadtarget.py @@ -145,16 +145,16 @@ class MaxUploadTest(BitcoinTestFramework): self.restart_node(0, ["-whitelist=download@127.0.0.1", "-maxuploadtarget=1"]) # Reconnect to self.nodes[0] - self.nodes[0].add_p2p_connection(TestP2PConn()) + peer = self.nodes[0].add_p2p_connection(TestP2PConn()) #retrieve 20 blocks which should be enough to break the 1MB limit getdata_request.inv = [CInv(MSG_BLOCK, big_new_block)] for i in range(20): - self.nodes[0].p2p.send_and_ping(getdata_request) - assert_equal(self.nodes[0].p2p.block_receive_map[big_new_block], i+1) + peer.send_and_ping(getdata_request) + assert_equal(peer.block_receive_map[big_new_block], i+1) getdata_request.inv = [CInv(MSG_BLOCK, big_old_block)] - self.nodes[0].p2p.send_and_ping(getdata_request) + peer.send_and_ping(getdata_request) self.log.info("Peer still connected after trying to download old block (download permission)") peer_info = self.nodes[0].getpeerinfo() diff --git a/test/functional/feature_signet.py b/test/functional/feature_signet.py index a0e7f3ee6e..96c581dede 100755 --- a/test/functional/feature_signet.py +++ b/test/functional/feature_signet.py @@ -65,6 +65,10 @@ class SignetBasicTest(BitcoinTestFramework): assert_equal(self.nodes[4].submitblock(signet_blocks[0]), 'bad-signet-blksig') + self.log.info("test that signet logs the network magic on node start") + with self.nodes[0].assert_debug_log(["Signet derived magic (message start)"]): + self.restart_node(0) + if __name__ == '__main__': SignetBasicTest().main() diff --git a/test/functional/feature_versionbits_warning.py b/test/functional/feature_versionbits_warning.py index e1016e1581..2e4f4796b0 100755 --- a/test/functional/feature_versionbits_warning.py +++ b/test/functional/feature_versionbits_warning.py @@ -61,7 +61,7 @@ class VersionBitsWarningTest(BitcoinTestFramework): def run_test(self): node = self.nodes[0] - node.add_p2p_connection(P2PInterface()) + peer = node.add_p2p_connection(P2PInterface()) node_deterministic_address = node.get_deterministic_priv_key().address # Mine one period worth of blocks @@ -69,7 +69,7 @@ class VersionBitsWarningTest(BitcoinTestFramework): self.log.info("Check that there is no warning if previous VB_BLOCKS have <VB_THRESHOLD blocks with unknown versionbits version.") # Build one period of blocks with < VB_THRESHOLD blocks signaling some unknown bit - self.send_blocks_with_version(node.p2p, VB_THRESHOLD - 1, VB_UNKNOWN_VERSION) + self.send_blocks_with_version(peer, VB_THRESHOLD - 1, VB_UNKNOWN_VERSION) node.generatetoaddress(VB_PERIOD - VB_THRESHOLD + 1, node_deterministic_address) # Check that we're not getting any versionbit-related errors in get*info() @@ -77,7 +77,7 @@ class VersionBitsWarningTest(BitcoinTestFramework): assert not VB_PATTERN.match(node.getnetworkinfo()["warnings"]) # Build one period of blocks with VB_THRESHOLD blocks signaling some unknown bit - self.send_blocks_with_version(node.p2p, VB_THRESHOLD, VB_UNKNOWN_VERSION) + self.send_blocks_with_version(peer, VB_THRESHOLD, VB_UNKNOWN_VERSION) node.generatetoaddress(VB_PERIOD - VB_THRESHOLD, node_deterministic_address) self.log.info("Check that there is a warning if previous VB_BLOCKS have >=VB_THRESHOLD blocks with unknown versionbits version.") diff --git a/test/functional/mempool_packages.py b/test/functional/mempool_packages.py index e74ef8cf16..d7cb7db9f8 100755 --- a/test/functional/mempool_packages.py +++ b/test/functional/mempool_packages.py @@ -58,7 +58,7 @@ class MempoolPackagesTest(BitcoinTestFramework): def run_test(self): # Mine some blocks and have them mature. - self.nodes[0].add_p2p_connection(P2PTxInvStore()) # keep track of invs + peer_inv_store = self.nodes[0].add_p2p_connection(P2PTxInvStore()) # keep track of invs self.nodes[0].generate(101) utxo = self.nodes[0].listunspent(10) txid = utxo[0]['txid'] @@ -80,7 +80,7 @@ class MempoolPackagesTest(BitcoinTestFramework): # 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 - self.nodes[0].p2p.wait_for_broadcast(witness_chain) + peer_inv_store.wait_for_broadcast(witness_chain) # Check mempool has MAX_ANCESTORS transactions in it, and descendant and ancestor # count and fees should look correct diff --git a/test/functional/mining_basic.py b/test/functional/mining_basic.py index b13740750f..1b2c7644bd 100755 --- a/test/functional/mining_basic.py +++ b/test/functional/mining_basic.py @@ -234,9 +234,9 @@ class MiningTest(BitcoinTestFramework): assert_raises_rpc_error(-25, 'time-too-old', lambda: node.submitheader(hexdata=CBlockHeader(bad_block_time).serialize().hex())) # Should ask for the block from a p2p node, if they announce the header as well: - node.add_p2p_connection(P2PDataStore()) - node.p2p.wait_for_getheaders(timeout=5) # Drop the first getheaders - node.p2p.send_blocks_and_test(blocks=[block], node=node) + peer = node.add_p2p_connection(P2PDataStore()) + peer.wait_for_getheaders(timeout=5) # Drop the first getheaders + peer.send_blocks_and_test(blocks=[block], node=node) # Must be active now: assert chain_tip(block.hash, status='active', branchlen=0) in node.getchaintips() diff --git a/test/functional/p2p_blocksonly.py b/test/functional/p2p_blocksonly.py index 3ead31c9ea..646baa1550 100755 --- a/test/functional/p2p_blocksonly.py +++ b/test/functional/p2p_blocksonly.py @@ -17,7 +17,7 @@ class P2PBlocksOnly(BitcoinTestFramework): self.extra_args = [["-blocksonly"]] def run_test(self): - self.nodes[0].add_p2p_connection(P2PInterface()) + block_relay_peer = self.nodes[0].add_p2p_connection(P2PInterface()) self.log.info('Check that txs from p2p are rejected and result in disconnect') prevtx = self.nodes[0].getblock(self.nodes[0].getblockhash(1), 2)['tx'][0] @@ -41,20 +41,20 @@ class P2PBlocksOnly(BitcoinTestFramework): )['hex'] assert_equal(self.nodes[0].getnetworkinfo()['localrelay'], False) with self.nodes[0].assert_debug_log(['transaction sent in violation of protocol peer=0']): - self.nodes[0].p2p.send_message(msg_tx(FromHex(CTransaction(), sigtx))) - self.nodes[0].p2p.wait_for_disconnect() + block_relay_peer.send_message(msg_tx(FromHex(CTransaction(), sigtx))) + block_relay_peer.wait_for_disconnect() assert_equal(self.nodes[0].getmempoolinfo()['size'], 0) # Remove the disconnected peer and add a new one. del self.nodes[0].p2ps[0] - self.nodes[0].add_p2p_connection(P2PInterface()) + tx_relay_peer = self.nodes[0].add_p2p_connection(P2PInterface()) self.log.info('Check that txs from rpc are not rejected and relayed to other peers') assert_equal(self.nodes[0].getpeerinfo()[0]['relaytxes'], True) txid = self.nodes[0].testmempoolaccept([sigtx])[0]['txid'] with self.nodes[0].assert_debug_log(['received getdata for: wtx {} peer=1'.format(txid)]): self.nodes[0].sendrawtransaction(sigtx) - self.nodes[0].p2p.wait_for_tx(txid) + tx_relay_peer.wait_for_tx(txid) assert_equal(self.nodes[0].getmempoolinfo()['size'], 1) self.log.info('Check that txs from peers with relay-permission are not rejected and relayed to others') diff --git a/test/functional/p2p_dos_header_tree.py b/test/functional/p2p_dos_header_tree.py index 7dd8c3146b..2349afa1ee 100755 --- a/test/functional/p2p_dos_header_tree.py +++ b/test/functional/p2p_dos_header_tree.py @@ -46,8 +46,8 @@ class RejectLowDifficultyHeadersTest(BitcoinTestFramework): self.headers_fork = [FromHex(CBlockHeader(), h) for h in self.headers_fork] 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_and_ping(msg_headers(self.headers)) + peer_checkpoint = self.nodes[0].add_p2p_connection(P2PInterface()) + peer_checkpoint.send_and_ping(msg_headers(self.headers)) assert { 'height': 546, 'hash': '000000002a936ca763904c3c35fce2f3556c559c0214345d31b1bcebf76acb70', @@ -57,14 +57,14 @@ class RejectLowDifficultyHeadersTest(BitcoinTestFramework): self.log.info("Feed all fork headers (fails due to checkpoint)") with self.nodes[0].assert_debug_log(['bad-fork-prior-to-checkpoint']): - self.nodes[0].p2p.send_message(msg_headers(self.headers_fork)) - self.nodes[0].p2p.wait_for_disconnect() + peer_checkpoint.send_message(msg_headers(self.headers_fork)) + peer_checkpoint.wait_for_disconnect() self.log.info("Feed all fork headers (succeeds without checkpoint)") # 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_and_ping(msg_headers(self.headers_fork)) + peer_no_checkpoint = self.nodes[0].add_p2p_connection(P2PInterface()) + peer_no_checkpoint.send_and_ping(msg_headers(self.headers_fork)) assert { "height": 2, "hash": "00000000b0494bd6c3d5ff79c497cfce40831871cbf39b1bc28bd1dac817dc39", @@ -73,8 +73,8 @@ class RejectLowDifficultyHeadersTest(BitcoinTestFramework): } in self.nodes[0].getchaintips() # 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_and_ping(msg_headers(self.headers_fork)) + peer_before_checkpoint = self.nodes[1].add_p2p_connection(P2PInterface()) + peer_before_checkpoint.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 613d96eaad..642a217047 100755 --- a/test/functional/p2p_filter.py +++ b/test/functional/p2p_filter.py @@ -131,7 +131,7 @@ class FilterTest(BitcoinTestFramework): self.log.debug("Send a mempool msg after connecting and check that the tx is received") self.nodes[0].add_p2p_connection(filter_peer) filter_peer.send_and_ping(filter_peer.watch_filter_init) - self.nodes[0].p2p.send_message(msg_mempool()) + filter_peer.send_message(msg_mempool()) filter_peer.wait_for_tx(txid) def test_frelay_false(self, filter_peer): diff --git a/test/functional/p2p_getdata.py b/test/functional/p2p_getdata.py index 51921a8ab5..89d68d5ba0 100755 --- a/test/functional/p2p_getdata.py +++ b/test/functional/p2p_getdata.py @@ -42,7 +42,7 @@ class GetdataTest(BitcoinTestFramework): good_getdata = msg_getdata() good_getdata.inv.append(CInv(t=2, h=best_block)) p2p_block_store.send_and_ping(good_getdata) - p2p_block_store.wait_until(lambda: self.nodes[0].p2ps[0].blocks[best_block] == 1) + p2p_block_store.wait_until(lambda: p2p_block_store.blocks[best_block] == 1) if __name__ == '__main__': diff --git a/test/functional/p2p_invalid_block.py b/test/functional/p2p_invalid_block.py index b2c3c5d45f..483f25f48c 100755 --- a/test/functional/p2p_invalid_block.py +++ b/test/functional/p2p_invalid_block.py @@ -27,7 +27,7 @@ class InvalidBlockRequestTest(BitcoinTestFramework): def run_test(self): # Add p2p connection to node0 node = self.nodes[0] # convenience reference to the node - node.add_p2p_connection(P2PDataStore()) + peer = node.add_p2p_connection(P2PDataStore()) best_block = node.getblock(node.getbestblockhash()) tip = int(node.getbestblockhash(), 16) @@ -42,7 +42,7 @@ class InvalidBlockRequestTest(BitcoinTestFramework): # Save the coinbase for later block1 = block tip = block.sha256 - node.p2p.send_blocks_and_test([block1], node, success=True) + peer.send_blocks_and_test([block1], node, success=True) self.log.info("Mature the block.") node.generatetoaddress(100, node.get_deterministic_priv_key().address) @@ -80,7 +80,7 @@ class InvalidBlockRequestTest(BitcoinTestFramework): assert_equal(orig_hash, block2.rehash()) assert block2_orig.vtx != block2.vtx - node.p2p.send_blocks_and_test([block2], node, success=False, reject_reason='bad-txns-duplicate') + peer.send_blocks_and_test([block2], node, success=False, reject_reason='bad-txns-duplicate') # Check transactions for duplicate inputs (CVE-2018-17144) self.log.info("Test duplicate input block.") @@ -91,7 +91,7 @@ class InvalidBlockRequestTest(BitcoinTestFramework): block2_dup.hashMerkleRoot = block2_dup.calc_merkle_root() block2_dup.rehash() block2_dup.solve() - node.p2p.send_blocks_and_test([block2_dup], node, success=False, reject_reason='bad-txns-inputs-duplicate') + peer.send_blocks_and_test([block2_dup], node, success=False, reject_reason='bad-txns-inputs-duplicate') self.log.info("Test very broken block.") @@ -104,14 +104,14 @@ class InvalidBlockRequestTest(BitcoinTestFramework): block3.rehash() block3.solve() - node.p2p.send_blocks_and_test([block3], node, success=False, reject_reason='bad-cb-amount') + peer.send_blocks_and_test([block3], node, success=False, reject_reason='bad-cb-amount') # Complete testing of CVE-2012-2459 by sending the original block. # It should be accepted even though it has the same hash as the mutated one. self.log.info("Test accepting original block after rejecting its mutated version.") - node.p2p.send_blocks_and_test([block2_orig], node, success=True, timeout=5) + peer.send_blocks_and_test([block2_orig], node, success=True, timeout=5) # Update tip info height += 1 @@ -131,7 +131,7 @@ class InvalidBlockRequestTest(BitcoinTestFramework): block4.rehash() block4.solve() self.log.info("Test inflation by duplicating input") - node.p2p.send_blocks_and_test([block4], node, success=False, reject_reason='bad-txns-inputs-duplicate') + peer.send_blocks_and_test([block4], node, success=False, reject_reason='bad-txns-inputs-duplicate') if __name__ == '__main__': InvalidBlockRequestTest().main() diff --git a/test/functional/p2p_invalid_locator.py b/test/functional/p2p_invalid_locator.py index 24328c2919..e4fc9fd178 100755 --- a/test/functional/p2p_invalid_locator.py +++ b/test/functional/p2p_invalid_locator.py @@ -23,20 +23,20 @@ class InvalidLocatorTest(BitcoinTestFramework): block_count = node.getblockcount() for msg in [msg_getheaders(), msg_getblocks()]: self.log.info('Wait for disconnect when sending {} hashes in locator'.format(MAX_LOCATOR_SZ + 1)) - node.add_p2p_connection(P2PInterface()) + exceed_max_peer = node.add_p2p_connection(P2PInterface()) msg.locator.vHave = [int(node.getblockhash(i - 1), 16) for i in range(block_count, block_count - (MAX_LOCATOR_SZ + 1), -1)] - node.p2p.send_message(msg) - node.p2p.wait_for_disconnect() + exceed_max_peer.send_message(msg) + exceed_max_peer.wait_for_disconnect() node.disconnect_p2ps() self.log.info('Wait for response when sending {} hashes in locator'.format(MAX_LOCATOR_SZ)) - node.add_p2p_connection(P2PInterface()) + within_max_peer = node.add_p2p_connection(P2PInterface()) msg.locator.vHave = [int(node.getblockhash(i - 1), 16) for i in range(block_count, block_count - (MAX_LOCATOR_SZ), -1)] - node.p2p.send_message(msg) + within_max_peer.send_message(msg) if type(msg) == msg_getheaders: - node.p2p.wait_for_header(node.getbestblockhash()) + within_max_peer.wait_for_header(node.getbestblockhash()) else: - node.p2p.wait_for_block(int(node.getbestblockhash(), 16)) + within_max_peer.wait_for_block(int(node.getbestblockhash(), 16)) if __name__ == '__main__': diff --git a/test/functional/p2p_invalid_messages.py b/test/functional/p2p_invalid_messages.py index fe57057a83..fbe58c5e2f 100755 --- a/test/functional/p2p_invalid_messages.py +++ b/test/functional/p2p_invalid_messages.py @@ -22,12 +22,11 @@ from test_framework.p2p import ( P2PInterface, ) from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import ( - assert_equal, -) +from test_framework.util import assert_equal VALID_DATA_LIMIT = MAX_PROTOCOL_MESSAGE_LENGTH - 5 # Account for the 5-byte length prefix + class msg_unrecognized: """Nonsensical message. Modeled after similar types in test_framework.messages.""" @@ -64,13 +63,13 @@ class InvalidMessagesTest(BitcoinTestFramework): conn = self.nodes[0].add_p2p_connection(P2PDataStore()) # Create valid message msg = conn.build_message(msg_ping(nonce=12345)) - cut_pos = 12 # Chosen at an arbitrary position within the header + cut_pos = 12 # Chosen at an arbitrary position within the header # Send message in two pieces - before = int(self.nodes[0].getnettotals()['totalbytesrecv']) + before = self.nodes[0].getnettotals()['totalbytesrecv'] conn.send_raw_message(msg[:cut_pos]) # Wait until node has processed the first half of the message - self.wait_until(lambda: int(self.nodes[0].getnettotals()['totalbytesrecv']) != before) - middle = int(self.nodes[0].getnettotals()['totalbytesrecv']) + self.wait_until(lambda: self.nodes[0].getnettotals()['totalbytesrecv'] != before) + middle = self.nodes[0].getnettotals()['totalbytesrecv'] # If this assert fails, we've hit an unlikely race # where the test framework sent a message in between the two halves assert_equal(middle, before + cut_pos) @@ -81,7 +80,7 @@ class InvalidMessagesTest(BitcoinTestFramework): def test_magic_bytes(self): self.log.info("Test message with invalid magic bytes disconnects peer") conn = self.nodes[0].add_p2p_connection(P2PDataStore()) - with self.nodes[0].assert_debug_log(['PROCESSMESSAGE: INVALID MESSAGESTART badmsg']): + with self.nodes[0].assert_debug_log(['HEADER ERROR - MESSAGESTART (badmsg, 2 bytes), received ffffffff']): msg = conn.build_message(msg_unrecognized(str_data="d")) # modify magic bytes msg = b'\xff' * 4 + msg[4:] @@ -100,12 +99,14 @@ class InvalidMessagesTest(BitcoinTestFramework): msg = msg[:cut_len] + b'\xff' * 4 + msg[cut_len + 4:] conn.send_raw_message(msg) conn.sync_with_ping(timeout=1) + # Check that traffic is accounted for (24 bytes header + 2 bytes payload) + assert_equal(self.nodes[0].getpeerinfo()[0]['bytesrecv_per_msg']['*other*'], 26) self.nodes[0].disconnect_p2ps() def test_size(self): self.log.info("Test message with oversized payload disconnects peer") conn = self.nodes[0].add_p2p_connection(P2PDataStore()) - with self.nodes[0].assert_debug_log(['']): + with self.nodes[0].assert_debug_log(['HEADER ERROR - SIZE (badmsg, 4000001 bytes)']): msg = msg_unrecognized(str_data="d" * (VALID_DATA_LIMIT + 1)) msg = conn.build_message(msg) conn.send_raw_message(msg) @@ -115,14 +116,15 @@ class InvalidMessagesTest(BitcoinTestFramework): def test_msgtype(self): self.log.info("Test message with invalid message type logs an error") conn = self.nodes[0].add_p2p_connection(P2PDataStore()) - with self.nodes[0].assert_debug_log(['PROCESSMESSAGE: ERRORS IN HEADER']): + with self.nodes[0].assert_debug_log(['HEADER ERROR - COMMAND']): msg = msg_unrecognized(str_data="d") - msg.msgtype = b'\xff' * 12 msg = conn.build_message(msg) # Modify msgtype msg = msg[:7] + b'\x00' + msg[7 + 1:] conn.send_raw_message(msg) conn.sync_with_ping(timeout=1) + # Check that traffic is accounted for (24 bytes header + 2 bytes payload) + assert_equal(self.nodes[0].getpeerinfo()[0]['bytesrecv_per_msg']['*other*'], 26) self.nodes[0].disconnect_p2ps() def test_oversized_msg(self, msg, size): diff --git a/test/functional/p2p_invalid_tx.py b/test/functional/p2p_invalid_tx.py index a0ef6c9d6e..489d903c21 100755 --- a/test/functional/p2p_invalid_tx.py +++ b/test/functional/p2p_invalid_tx.py @@ -61,7 +61,7 @@ class InvalidTxRequestTest(BitcoinTestFramework): # Save the coinbase for later block1 = block tip = block.sha256 - node.p2p.send_blocks_and_test([block], node, success=True) + node.p2ps[0].send_blocks_and_test([block], node, success=True) self.log.info("Mature the block.") self.nodes[0].generatetoaddress(100, self.nodes[0].get_deterministic_priv_key().address) @@ -72,7 +72,7 @@ class InvalidTxRequestTest(BitcoinTestFramework): self.log.info("Testing invalid transaction: %s", BadTxTemplate.__name__) template = BadTxTemplate(spend_block=block1) tx = template.get_tx() - node.p2p.send_txs_and_test( + node.p2ps[0].send_txs_and_test( [tx], node, success=False, expect_disconnect=template.expect_disconnect, reject_reason=template.reject_reason, @@ -121,7 +121,7 @@ class InvalidTxRequestTest(BitcoinTestFramework): self.log.info('Send the orphans ... ') # Send valid orphan txs from p2ps[0] - node.p2p.send_txs_and_test([tx_orphan_1, tx_orphan_2_no_fee, tx_orphan_2_valid], node, success=False) + node.p2ps[0].send_txs_and_test([tx_orphan_1, tx_orphan_2_no_fee, tx_orphan_2_valid], node, success=False) # Send invalid tx from p2ps[1] node.p2ps[1].send_txs_and_test([tx_orphan_2_invalid], node, success=False) @@ -130,7 +130,7 @@ class InvalidTxRequestTest(BitcoinTestFramework): self.log.info('Send the withhold tx ... ') with node.assert_debug_log(expected_msgs=["bad-txns-in-belowout"]): - node.p2p.send_txs_and_test([tx_withhold], node, success=True) + node.p2ps[0].send_txs_and_test([tx_withhold], node, success=True) # Transactions that should end up in the mempool expected_mempool = { @@ -155,14 +155,14 @@ class InvalidTxRequestTest(BitcoinTestFramework): orphan_tx_pool[i].vout.append(CTxOut(nValue=11 * COIN, scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE)) with node.assert_debug_log(['mapOrphan overflow, removed 1 tx']): - node.p2p.send_txs_and_test(orphan_tx_pool, node, success=False) + node.p2ps[0].send_txs_and_test(orphan_tx_pool, node, success=False) rejected_parent = CTransaction() rejected_parent.vin.append(CTxIn(outpoint=COutPoint(tx_orphan_2_invalid.sha256, 0))) rejected_parent.vout.append(CTxOut(nValue=11 * COIN, scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE)) rejected_parent.rehash() with node.assert_debug_log(['not keeping orphan with rejected parents {}'.format(rejected_parent.hash)]): - node.p2p.send_txs_and_test([rejected_parent], node, success=False) + node.p2ps[0].send_txs_and_test([rejected_parent], node, success=False) if __name__ == '__main__': diff --git a/test/functional/p2p_segwit.py b/test/functional/p2p_segwit.py index dfbf5d52f4..d79ed449e5 100755 --- a/test/functional/p2p_segwit.py +++ b/test/functional/p2p_segwit.py @@ -89,7 +89,6 @@ from test_framework.util import ( # The versionbit bit used to signal activation of SegWit VB_WITNESS_BIT = 1 -VB_PERIOD = 144 VB_TOP_BITS = 0x20000000 MAX_SIGOP_COST = 80000 @@ -2097,14 +2096,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_and_ping(msg_bogus_tx(tx)) + self.test_node.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_and_ping(msg_bogus_tx(tx)) + self.test_node.send_and_ping(msg_bogus_tx(tx)) @subtest # type: ignore def test_wtxid_relay(self): diff --git a/test/functional/rpc_blockchain.py b/test/functional/rpc_blockchain.py index c005584485..35cea85c07 100755 --- a/test/functional/rpc_blockchain.py +++ b/test/functional/rpc_blockchain.py @@ -317,7 +317,7 @@ class BlockchainTest(BitcoinTestFramework): def _test_waitforblockheight(self): self.log.info("Test waitforblockheight") node = self.nodes[0] - node.add_p2p_connection(P2PInterface()) + peer = node.add_p2p_connection(P2PInterface()) current_height = node.getblock(node.getbestblockhash())['height'] @@ -334,7 +334,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_and_ping(msg_block(b)) + peer.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/rpc_getpeerinfo_banscore_deprecation.py b/test/functional/rpc_getpeerinfo_banscore_deprecation.py deleted file mode 100755 index b830248e1e..0000000000 --- a/test/functional/rpc_getpeerinfo_banscore_deprecation.py +++ /dev/null @@ -1,24 +0,0 @@ -#!/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 deprecation of getpeerinfo RPC banscore field.""" - -from test_framework.test_framework import BitcoinTestFramework - - -class GetpeerinfoBanscoreDeprecationTest(BitcoinTestFramework): - def set_test_params(self): - self.num_nodes = 2 - self.extra_args = [[], ["-deprecatedrpc=banscore"]] - - def run_test(self): - self.log.info("Test getpeerinfo by default no longer returns a banscore field") - assert "banscore" not in self.nodes[0].getpeerinfo()[0].keys() - - self.log.info("Test getpeerinfo returns banscore with -deprecatedrpc=banscore") - assert "banscore" in self.nodes[1].getpeerinfo()[0].keys() - - -if __name__ == "__main__": - GetpeerinfoBanscoreDeprecationTest().main() diff --git a/test/functional/rpc_getpeerinfo_deprecation.py b/test/functional/rpc_getpeerinfo_deprecation.py new file mode 100755 index 0000000000..287c40ae3e --- /dev/null +++ b/test/functional/rpc_getpeerinfo_deprecation.py @@ -0,0 +1,39 @@ +#!/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 deprecation of getpeerinfo RPC fields.""" + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import connect_nodes + + +class GetpeerinfoDeprecationTest(BitcoinTestFramework): + def set_test_params(self): + self.num_nodes = 2 + self.extra_args = [[], ["-deprecatedrpc=banscore"]] + + def run_test(self): + self.test_banscore_deprecation() + self.test_addnode_deprecation() + + def test_banscore_deprecation(self): + self.log.info("Test getpeerinfo by default no longer returns a banscore field") + assert "banscore" not in self.nodes[0].getpeerinfo()[0].keys() + + self.log.info("Test getpeerinfo returns banscore with -deprecatedrpc=banscore") + assert "banscore" in self.nodes[1].getpeerinfo()[0].keys() + + def test_addnode_deprecation(self): + self.restart_node(1, ["-deprecatedrpc=getpeerinfo_addnode"]) + connect_nodes(self.nodes[0], 1) + + self.log.info("Test getpeerinfo by default no longer returns an addnode field") + assert "addnode" not in self.nodes[0].getpeerinfo()[0].keys() + + self.log.info("Test getpeerinfo returns addnode with -deprecatedrpc=addnode") + assert "addnode" in self.nodes[1].getpeerinfo()[0].keys() + + +if __name__ == "__main__": + GetpeerinfoDeprecationTest().main() diff --git a/test/functional/rpc_net.py b/test/functional/rpc_net.py index bc0e5b458e..b8a04f494d 100755 --- a/test/functional/rpc_net.py +++ b/test/functional/rpc_net.py @@ -175,6 +175,12 @@ class NetTest(BitcoinTestFramework): for info in peer_info: assert_net_servicesnames(int(info[0]["services"], 0x10), info[0]["servicesnames"]) + assert_equal(peer_info[0][0]['connection_type'], 'inbound') + assert_equal(peer_info[0][1]['connection_type'], 'manual') + + assert_equal(peer_info[1][0]['connection_type'], 'manual') + assert_equal(peer_info[1][1]['connection_type'], 'inbound') + def test_service_flags(self): self.log.info("Test service flags") self.nodes[0].add_p2p_connection(P2PInterface(), services=(1 << 4) | (1 << 63)) diff --git a/test/functional/test_framework/address.py b/test/functional/test_framework/address.py index 9506b63f82..360962b8da 100644 --- a/test/functional/test_framework/address.py +++ b/test/functional/test_framework/address.py @@ -2,17 +2,17 @@ # Copyright (c) 2016-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. -"""Encode and decode BASE58, P2PKH and P2SH addresses.""" +"""Encode and decode Bitcoin addresses. + +- base58 P2PKH and P2SH addresses. +- bech32 segwit v0 P2WPKH and P2WSH addresses.""" import enum import unittest from .script import hash256, hash160, sha256, CScript, OP_0 -from .util import hex_str_to_bytes - -from . import segwit_addr - -from test_framework.util import assert_equal +from .segwit_addr import encode_segwit_address +from .util import assert_equal, hex_str_to_bytes ADDRESS_BCRT1_UNSPENDABLE = 'bcrt1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq3xueyj' ADDRESS_BCRT1_UNSPENDABLE_DESCRIPTOR = 'addr(bcrt1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq3xueyj)#juyq9d97' @@ -35,7 +35,7 @@ def byte_to_base58(b, version): str = chr(version).encode('latin-1').hex() + str checksum = hash256(hex_str_to_bytes(str)).hex() str += checksum[:8] - value = int('0x'+str,0) + value = int('0x' + str, 0) while value > 0: result = chars[value % 58] + result value //= 58 @@ -45,7 +45,10 @@ def byte_to_base58(b, version): return result -def base58_to_byte(s, verify_checksum=True): +def base58_to_byte(s): + """Converts a base58-encoded string to its data and version. + + Throws if the base58 checksum is invalid.""" if not s: return b'' n = 0 @@ -65,66 +68,67 @@ def base58_to_byte(s, verify_checksum=True): else: break res = b'\x00' * pad + res - if verify_checksum: - assert_equal(hash256(res[:-4])[:4], res[-4:]) + + # Assert if the checksum is invalid + assert_equal(hash256(res[:-4])[:4], res[-4:]) return res[1:-4], int(res[0]) -def keyhash_to_p2pkh(hash, main = False): +def keyhash_to_p2pkh(hash, main=False): assert len(hash) == 20 version = 0 if main else 111 return byte_to_base58(hash, version) -def scripthash_to_p2sh(hash, main = False): +def scripthash_to_p2sh(hash, main=False): assert len(hash) == 20 version = 5 if main else 196 return byte_to_base58(hash, version) -def key_to_p2pkh(key, main = False): +def key_to_p2pkh(key, main=False): key = check_key(key) return keyhash_to_p2pkh(hash160(key), main) -def script_to_p2sh(script, main = False): +def script_to_p2sh(script, main=False): script = check_script(script) return scripthash_to_p2sh(hash160(script), main) -def key_to_p2sh_p2wpkh(key, main = False): +def key_to_p2sh_p2wpkh(key, main=False): key = check_key(key) p2shscript = CScript([OP_0, hash160(key)]) return script_to_p2sh(p2shscript, main) -def program_to_witness(version, program, main = False): +def program_to_witness(version, program, main=False): if (type(program) is str): program = hex_str_to_bytes(program) assert 0 <= version <= 16 assert 2 <= len(program) <= 40 assert version > 0 or len(program) in [20, 32] - return segwit_addr.encode("bc" if main else "bcrt", version, program) + return encode_segwit_address("bc" if main else "bcrt", version, program) -def script_to_p2wsh(script, main = False): +def script_to_p2wsh(script, main=False): script = check_script(script) return program_to_witness(0, sha256(script), main) -def key_to_p2wpkh(key, main = False): +def key_to_p2wpkh(key, main=False): key = check_key(key) return program_to_witness(0, hash160(key), main) -def script_to_p2sh_p2wsh(script, main = False): +def script_to_p2sh_p2wsh(script, main=False): script = check_script(script) p2shscript = CScript([OP_0, sha256(script)]) return script_to_p2sh(p2shscript, main) def check_key(key): if (type(key) is str): - key = hex_str_to_bytes(key) # Assuming this is hex string + key = hex_str_to_bytes(key) # Assuming this is hex string if (type(key) is bytes and (len(key) == 33 or len(key) == 65)): return key assert False def check_script(script): if (type(script) is str): - script = hex_str_to_bytes(script) # Assuming this is hex string + script = hex_str_to_bytes(script) # Assuming this is hex string if (type(script) is bytes or type(script) is CScript): return script assert False @@ -135,15 +139,15 @@ class TestFrameworkScript(unittest.TestCase): def check_base58(data, version): self.assertEqual(base58_to_byte(byte_to_base58(data, version)), (data, version)) - check_base58(b'\x1f\x8e\xa1p*{\xd4\x94\x1b\xca\tA\xb8R\xc4\xbb\xfe\xdb.\x05', 111) - check_base58(b':\x0b\x05\xf4\xd7\xf6l;\xa7\x00\x9fE50)l\x84\\\xc9\xcf', 111) - check_base58(b'A\xc1\xea\xf1\x11\x80%Y\xba\xd6\x1b`\xd6+\x1f\x89|c\x92\x8a', 111) - check_base58(b'\0A\xc1\xea\xf1\x11\x80%Y\xba\xd6\x1b`\xd6+\x1f\x89|c\x92\x8a', 111) - check_base58(b'\0\0A\xc1\xea\xf1\x11\x80%Y\xba\xd6\x1b`\xd6+\x1f\x89|c\x92\x8a', 111) - check_base58(b'\0\0\0A\xc1\xea\xf1\x11\x80%Y\xba\xd6\x1b`\xd6+\x1f\x89|c\x92\x8a', 111) - check_base58(b'\x1f\x8e\xa1p*{\xd4\x94\x1b\xca\tA\xb8R\xc4\xbb\xfe\xdb.\x05', 0) - check_base58(b':\x0b\x05\xf4\xd7\xf6l;\xa7\x00\x9fE50)l\x84\\\xc9\xcf', 0) - check_base58(b'A\xc1\xea\xf1\x11\x80%Y\xba\xd6\x1b`\xd6+\x1f\x89|c\x92\x8a', 0) - check_base58(b'\0A\xc1\xea\xf1\x11\x80%Y\xba\xd6\x1b`\xd6+\x1f\x89|c\x92\x8a', 0) - check_base58(b'\0\0A\xc1\xea\xf1\x11\x80%Y\xba\xd6\x1b`\xd6+\x1f\x89|c\x92\x8a', 0) - check_base58(b'\0\0\0A\xc1\xea\xf1\x11\x80%Y\xba\xd6\x1b`\xd6+\x1f\x89|c\x92\x8a', 0) + check_base58(bytes.fromhex('1f8ea1702a7bd4941bca0941b852c4bbfedb2e05'), 111) + check_base58(bytes.fromhex('3a0b05f4d7f66c3ba7009f453530296c845cc9cf'), 111) + check_base58(bytes.fromhex('41c1eaf111802559bad61b60d62b1f897c63928a'), 111) + check_base58(bytes.fromhex('0041c1eaf111802559bad61b60d62b1f897c63928a'), 111) + check_base58(bytes.fromhex('000041c1eaf111802559bad61b60d62b1f897c63928a'), 111) + check_base58(bytes.fromhex('00000041c1eaf111802559bad61b60d62b1f897c63928a'), 111) + check_base58(bytes.fromhex('1f8ea1702a7bd4941bca0941b852c4bbfedb2e05'), 0) + check_base58(bytes.fromhex('3a0b05f4d7f66c3ba7009f453530296c845cc9cf'), 0) + check_base58(bytes.fromhex('41c1eaf111802559bad61b60d62b1f897c63928a'), 0) + check_base58(bytes.fromhex('0041c1eaf111802559bad61b60d62b1f897c63928a'), 0) + check_base58(bytes.fromhex('000041c1eaf111802559bad61b60d62b1f897c63928a'), 0) + check_base58(bytes.fromhex('00000041c1eaf111802559bad61b60d62b1f897c63928a'), 0) diff --git a/test/functional/test_framework/segwit_addr.py b/test/functional/test_framework/segwit_addr.py index 02368e938f..00c0d8a919 100644 --- a/test/functional/test_framework/segwit_addr.py +++ b/test/functional/test_framework/segwit_addr.py @@ -3,7 +3,7 @@ # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Reference implementation for Bech32 and segwit addresses.""" - +import unittest CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l" @@ -84,7 +84,7 @@ def convertbits(data, frombits, tobits, pad=True): return ret -def decode(hrp, addr): +def decode_segwit_address(hrp, addr): """Decode a segwit address.""" hrpgot, data = bech32_decode(addr) if hrpgot != hrp: @@ -99,9 +99,23 @@ def decode(hrp, addr): return (data[0], decoded) -def encode(hrp, witver, witprog): +def encode_segwit_address(hrp, witver, witprog): """Encode a segwit address.""" ret = bech32_encode(hrp, [witver] + convertbits(witprog, 8, 5)) - if decode(hrp, ret) == (None, None): + if decode_segwit_address(hrp, ret) == (None, None): return None return ret + +class TestFrameworkScript(unittest.TestCase): + def test_segwit_encode_decode(self): + def test_python_bech32(addr): + hrp = addr[:4] + self.assertEqual(hrp, "bcrt") + (witver, witprog) = decode_segwit_address(hrp, addr) + self.assertEqual(encode_segwit_address(hrp, witver, witprog), addr) + + # P2WPKH + test_python_bech32('bcrt1qthmht0k2qnh3wy7336z05lu2km7emzfpm3wg46') + # P2WSH + test_python_bech32('bcrt1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq3xueyj') + test_python_bech32('bcrt1qft5p2uhsdcdc3l2ua4ap5qqfg4pjaqlp250x7us7a8qqhrxrxfsqseac85') diff --git a/test/functional/test_framework/test_node.py b/test/functional/test_framework/test_node.py index d034986821..046efe730e 100755 --- a/test/functional/test_framework/test_node.py +++ b/test/functional/test_framework/test_node.py @@ -542,15 +542,6 @@ class TestNode(): return p2p_conn - @property - def p2p(self): - """Return the first p2p connection - - Convenience property - most tests only use a single p2p connection to each - node, so this saves having to write node.p2ps[0] many times.""" - assert self.p2ps, self._node_msg("No p2p connection") - return self.p2ps[0] - def num_test_p2p_connections(self): """Return number of test framework p2p connections to the node.""" return len([peer for peer in self.getpeerinfo() if peer['subver'] == MY_SUBVERSION]) diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index 6c3d50df93..cb86305cc6 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -71,6 +71,7 @@ TEST_FRAMEWORK_MODULES = [ "blocktools", "muhash", "script", + "segwit_addr", "util", ] @@ -251,7 +252,7 @@ BASE_SCRIPTS = [ 'feature_config_args.py', 'feature_settings.py', 'rpc_getdescriptorinfo.py', - 'rpc_getpeerinfo_banscore_deprecation.py', + 'rpc_getpeerinfo_deprecation.py', 'rpc_help.py', 'feature_help.py', 'feature_shutdown.py', diff --git a/test/functional/wallet_address_types.py b/test/functional/wallet_address_types.py index 68e22b7e86..bba0b8974d 100755 --- a/test/functional/wallet_address_types.py +++ b/test/functional/wallet_address_types.py @@ -64,10 +64,6 @@ from test_framework.util import ( assert_raises_rpc_error, connect_nodes, ) -from test_framework.segwit_addr import ( - encode, - decode, -) class AddressTypeTest(BitcoinTestFramework): def set_test_params(self): @@ -101,13 +97,6 @@ class AddressTypeTest(BitcoinTestFramework): """Return a list of balances.""" return [self.nodes[i].getbalances()['mine'][key] for i in range(4)] - # Quick test of python bech32 implementation - def test_python_bech32(self, addr): - hrp = addr[:4] - assert_equal(hrp, "bcrt") - (witver, witprog) = decode(hrp, addr) - assert_equal(encode(hrp, witver, witprog), addr) - def test_address(self, node, address, multisig, typ): """Run sanity checks on an address.""" info = self.nodes[node].getaddressinfo(address) @@ -132,7 +121,6 @@ class AddressTypeTest(BitcoinTestFramework): assert_equal(info['witness_version'], 0) assert_equal(len(info['witness_program']), 40) assert 'pubkey' in info - self.test_python_bech32(info["address"]) elif typ == 'legacy': # P2SH-multisig assert info['isscript'] @@ -158,7 +146,6 @@ class AddressTypeTest(BitcoinTestFramework): assert_equal(info['witness_version'], 0) assert_equal(len(info['witness_program']), 64) assert 'pubkeys' in info - self.test_python_bech32(info["address"]) else: # Unknown type assert False diff --git a/test/functional/wallet_basic.py b/test/functional/wallet_basic.py index bb208341a0..689a0fa4df 100755 --- a/test/functional/wallet_basic.py +++ b/test/functional/wallet_basic.py @@ -661,6 +661,18 @@ class WalletTest(BitcoinTestFramework): assert_array_result(tx["details"], {"category": "receive"}, expected_receive_vout) assert_equal(tx[verbose_field], self.nodes[0].decoderawtransaction(tx["hex"])) + self.log.info("Test send* RPCs with verbose=True") + address = self.nodes[0].getnewaddress("test") + txid_feeReason_one = self.nodes[2].sendtoaddress(address=address, amount=5, verbose=True) + assert_equal(txid_feeReason_one["fee_reason"], "Fallback fee") + txid_feeReason_two = self.nodes[2].sendmany(dummy='', amounts={address: 5}, verbose=True) + assert_equal(txid_feeReason_two["fee_reason"], "Fallback fee") + self.log.info("Test send* RPCs with verbose=False") + txid_feeReason_three = self.nodes[2].sendtoaddress(address=address, amount=5, verbose=False) + assert_equal(self.nodes[2].gettransaction(txid_feeReason_three)['txid'], txid_feeReason_three) + txid_feeReason_four = self.nodes[2].sendmany(dummy='', amounts={address: 5}, verbose=False) + assert_equal(self.nodes[2].gettransaction(txid_feeReason_four)['txid'], txid_feeReason_four) + if __name__ == '__main__': WalletTest().main() diff --git a/test/functional/wallet_multiwallet.py b/test/functional/wallet_multiwallet.py index aaf050ebf7..f0be271c66 100755 --- a/test/functional/wallet_multiwallet.py +++ b/test/functional/wallet_multiwallet.py @@ -21,8 +21,6 @@ from test_framework.util import ( get_rpc_proxy, ) -FEATURE_LATEST = 169900 - got_loading_error = False def test_load_unload(node, name): global got_loading_error diff --git a/test/functional/wallet_resendwallettransactions.py b/test/functional/wallet_resendwallettransactions.py index 0327c9e070..d3c03c4764 100755 --- a/test/functional/wallet_resendwallettransactions.py +++ b/test/functional/wallet_resendwallettransactions.py @@ -21,7 +21,7 @@ class ResendWalletTransactionsTest(BitcoinTestFramework): def run_test(self): node = self.nodes[0] # alias - node.add_p2p_connection(P2PTxInvStore()) + peer_first = node.add_p2p_connection(P2PTxInvStore()) self.log.info("Create a new transaction and wait until it's broadcast") txid = node.sendtoaddress(node.getnewaddress(), 1) @@ -33,10 +33,10 @@ class ResendWalletTransactionsTest(BitcoinTestFramework): time.sleep(1.1) # Can take a few seconds due to transaction trickling - node.p2p.wait_for_broadcast([txid]) + peer_first.wait_for_broadcast([txid]) # Add a second peer since txs aren't rebroadcast to the same peer (see filterInventoryKnown) - node.add_p2p_connection(P2PTxInvStore()) + peer_second = node.add_p2p_connection(P2PTxInvStore()) self.log.info("Create a block") # Create and submit a block without the transaction. @@ -58,13 +58,13 @@ class ResendWalletTransactionsTest(BitcoinTestFramework): two_min = 2 * 60 node.setmocktime(now + twelve_hrs - two_min) time.sleep(2) # ensure enough time has passed for rebroadcast attempt to occur - assert_equal(int(txid, 16) in node.p2ps[1].get_invs(), False) + assert_equal(int(txid, 16) in peer_second.get_invs(), False) self.log.info("Bump time & check that transaction is rebroadcast") # Transaction should be rebroadcast approximately 24 hours in the future, # but can range from 12-36. So bump 36 hours to be sure. node.setmocktime(now + 36 * 60 * 60) - node.p2p.wait_for_broadcast([txid]) + peer_second.wait_for_broadcast([txid]) if __name__ == '__main__': diff --git a/test/functional/wallet_send.py b/test/functional/wallet_send.py index b64d2030a4..4fdfad01c3 100755 --- a/test/functional/wallet_send.py +++ b/test/functional/wallet_send.py @@ -29,9 +29,9 @@ class WalletSendTest(BitcoinTestFramework): def test_send(self, from_wallet, to_wallet=None, amount=None, data=None, arg_conf_target=None, arg_estimate_mode=None, - conf_target=None, estimate_mode=None, add_to_wallet=None,psbt=None, - inputs=None,add_inputs=None,change_address=None,change_position=None,change_type=None, - include_watching=None,locktime=None,lock_unspents=None,replaceable=None,subtract_fee_from_outputs=None, + conf_target=None, estimate_mode=None, add_to_wallet=None, psbt=None, + inputs=None, add_inputs=None, change_address=None, change_position=None, change_type=None, + include_watching=None, locktime=None, lock_unspents=None, replaceable=None, subtract_fee_from_outputs=None, expect_error=None): assert (amount is None) != (data is None) @@ -92,13 +92,13 @@ class WalletSendTest(BitcoinTestFramework): res = from_wallet.send(outputs=outputs, conf_target=arg_conf_target, estimate_mode=arg_estimate_mode, options=options) else: try: - assert_raises_rpc_error(expect_error[0],expect_error[1],from_wallet.send, - outputs=outputs,conf_target=arg_conf_target,estimate_mode=arg_estimate_mode,options=options) + assert_raises_rpc_error(expect_error[0], expect_error[1], from_wallet.send, + outputs=outputs, conf_target=arg_conf_target, estimate_mode=arg_estimate_mode, 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,conf_target=arg_conf_target,estimate_mode=arg_estimate_mode,options=options) + res = from_wallet.send(outputs=outputs, conf_target=arg_conf_target, estimate_mode=arg_estimate_mode, options=options) self.log.error(res) if "txid" in res and add_to_wallet: self.log.error("Transaction details:") @@ -131,7 +131,7 @@ class WalletSendTest(BitcoinTestFramework): assert tx assert_equal(tx["bip125-replaceable"], "yes" if replaceable else "no") # Ensure transaction exists in the mempool: - tx = from_wallet.getrawtransaction(res["txid"],True) + tx = from_wallet.getrawtransaction(res["txid"], True) assert tx if amount: if subtract_fee_from_outputs: @@ -164,7 +164,7 @@ class WalletSendTest(BitcoinTestFramework): 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) + 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() @@ -188,7 +188,7 @@ class WalletSendTest(BitcoinTestFramework): self.sync_blocks() # w4 has private keys enabled, but only contains watch-only keys (from w2) - self.nodes[1].createwallet(wallet_name="w4",disable_private_keys=False) + 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() @@ -253,7 +253,7 @@ class WalletSendTest(BitcoinTestFramework): self.test_send(from_wallet=w0, to_wallet=w1, amount=1, conf_target=-1, estimate_mode="sat/b", expect_error=(-3, "Amount out of range")) # Fee rate of 0.1 satoshi per byte should throw an error - # TODO: error should say 1.000 sat/b + # TODO: error should use sat/b self.test_send(from_wallet=w0, to_wallet=w1, amount=1, conf_target=0.1, estimate_mode="sat/b", expect_error=(-4, "Fee rate (0.00000100 BTC/kB) is lower than the minimum fee rate setting (0.00001000 BTC/kB)")) @@ -325,11 +325,16 @@ class WalletSendTest(BitcoinTestFramework): locked_coins = w0.listlockunspent() assert_equal(len(locked_coins), 1) # Locked coins are automatically unlocked when manually selected - self.test_send(from_wallet=w0, to_wallet=w1, amount=1, inputs=[utxo1],add_to_wallet=False) + res = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, inputs=[utxo1], add_to_wallet=False) + assert res["complete"] self.log.info("Replaceable...") - self.test_send(from_wallet=w0, to_wallet=w1, amount=1, add_to_wallet=False, replaceable=True) - self.test_send(from_wallet=w0, to_wallet=w1, amount=1, add_to_wallet=False, replaceable=False) + res = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, add_to_wallet=True, replaceable=True) + assert res["complete"] + assert_equal(self.nodes[0].gettransaction(res["txid"])["bip125-replaceable"], "yes") + res = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, add_to_wallet=True, replaceable=False) + assert res["complete"] + assert_equal(self.nodes[0].gettransaction(res["txid"])["bip125-replaceable"], "no") self.log.info("Subtract fee from output") self.test_send(from_wallet=w0, to_wallet=w1, amount=1, subtract_fee_from_outputs=[0]) diff --git a/test/functional/wallet_txn_clone.py b/test/functional/wallet_txn_clone.py index 5e1a804d33..33a2a9411e 100755 --- a/test/functional/wallet_txn_clone.py +++ b/test/functional/wallet_txn_clone.py @@ -25,7 +25,7 @@ class TxnMallTest(BitcoinTestFramework): parser.add_argument("--mineblock", dest="mine_block", default=False, action="store_true", help="Test double-spend of 1-confirmed transaction") parser.add_argument("--segwit", dest="segwit", default=False, action="store_true", - help="Test behaviour with SegWit txn (which should fail") + help="Test behaviour with SegWit txn (which should fail)") def setup_network(self): # Start with split network: diff --git a/test/sanitizer_suppressions/ubsan b/test/sanitizer_suppressions/ubsan index b3d9b9e6ec..75257d886b 100644 --- a/test/sanitizer_suppressions/ubsan +++ b/test/sanitizer_suppressions/ubsan @@ -1,6 +1,5 @@ # -fsanitize=undefined suppressions # ================================= -float-divide-by-zero:policy/fees.cpp float-divide-by-zero:validation.cpp float-divide-by-zero:wallet/wallet.cpp |