From 4e81732c57b9513d0cc3de53d4a61918b064a3e7 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 25 Feb 2021 09:48:28 +0100 Subject: [PATCH] Merge #21200: test: Speed up rpc_blockchain.py by removing miniwallet.generate() faa137eb9eac5554504b062a6dc865ca87fd572b test: Speed up rpc_blockchain.py by removing miniwallet.generate() (MarcoFalke) fa1fe80c757df0adcbfaf41b5c5c8a468bc07b6f test: Change address type from P2PKH to P2WSH in rpc_blockchain (MarcoFalke) fa4d8f3169e38cbdbae20258efebe7070c49f522 test: Cache 25 mature coins for ADDRESS_BCRT1_P2WSH_OP_TRUE (MarcoFalke) fad25153f5c8e88f72cf666b16b0b0dbdc45d3b1 test: Remove unused bug workaround (MarcoFalke) faabce7d07c5776e4116b1a7ad1f6c408a4a4e46 test: Start only the number of nodes that are needed (MarcoFalke) Pull request description: Speed up various tests: * Remove unused nodes, which only consume time on start/stop * Remove unused "bug workarounds" * Remove the need for `miniwallet.generate()` by adding `miniwallet.scan_blocks()`. (On my system, with valgrind, generating 105 blocks takes 3.31 seconds. Rescanning 5 blocks takes 0.11 seconds.) ACKs for top commit: laanwj: Code review ACK faa137eb9eac5554504b062a6dc865ca87fd572b Tree-SHA512: ead1988d5aaa748ef9f8520af1e0bf812cf1d72e281ad22fbd172b7306d850053040526f8adbcec0b9a971c697a0ee7ee8962684644d65b791663eedd505a025 --- test/functional/rpc_blockchain.py | 13 ++++++------- test/functional/test_framework/test_framework.py | 8 +++++--- test/functional/test_framework/wallet.py | 9 +++++++++ test/functional/wallet_txn_clone.py | 7 ++++--- test/functional/wallet_txn_doublespend.py | 7 ++++--- 5 files changed, 28 insertions(+), 16 deletions(-) diff --git a/test/functional/rpc_blockchain.py b/test/functional/rpc_blockchain.py index 514c890dc7..8318ee0d6d 100755 --- a/test/functional/rpc_blockchain.py +++ b/test/functional/rpc_blockchain.py @@ -25,6 +25,7 @@ import http.client import os import subprocess +from test_framework.address import ADDRESS_BCRT1_P2SH_OP_TRUE from test_framework.blocktools import ( create_block, create_coinbase, @@ -81,11 +82,10 @@ class BlockchainTest(BitcoinTestFramework): def mine_chain(self): self.log.info(f"Generate {HEIGHT} blocks after the genesis block in 156 sec") - address = self.nodes[0].get_deterministic_priv_key().address for t in range(TIME_GENESIS_BLOCK, TIME_RANGE_END, TIME_RANGE_STEP): # 156 sec steps from genesis block time set_node_times(self.nodes, t) - self.nodes[0].generatetoaddress(1, address) + self.nodes[0].generatetoaddress(1, ADDRESS_BCRT1_P2SH_OP_TRUE) assert_equal(self.nodes[0].getblockchaininfo()['blocks'], 200) def _test_getblockchaininfo(self): @@ -258,7 +258,7 @@ class BlockchainTest(BitcoinTestFramework): assert_equal(res['transactions'], HEIGHT) assert_equal(res['height'], HEIGHT) assert_equal(res['txouts'], HEIGHT) - assert_equal(res['bogosize'], 15000), + assert_equal(res['bogosize'], 14600), size = res['disk_size'] assert size > 6400 assert size < 64000 @@ -365,12 +365,12 @@ class BlockchainTest(BitcoinTestFramework): def _test_stopatheight(self): assert_equal(self.nodes[0].getblockcount(), HEIGHT) - self.nodes[0].generatetoaddress(6, self.nodes[0].get_deterministic_priv_key().address) + self.nodes[0].generatetoaddress(6, ADDRESS_BCRT1_P2SH_OP_TRUE) assert_equal(self.nodes[0].getblockcount(), HEIGHT + 6) self.log.debug('Node should not stop at this height') assert_raises(subprocess.TimeoutExpired, lambda: self.nodes[0].process.wait(timeout=3)) try: - self.nodes[0].generatetoaddress(1, self.nodes[0].get_deterministic_priv_key().address) + self.nodes[0].generatetoaddress(1, ADDRESS_BCRT1_P2SH_OP_TRUE) except (ConnectionError, http.client.BadStatusLine): pass # The node already shut down before response self.log.debug('Node should stop at this height...') @@ -420,8 +420,7 @@ class BlockchainTest(BitcoinTestFramework): node = self.nodes[0] miniwallet = MiniWallet(node) - miniwallet.generate(5) - node.generate(100) + miniwallet.scan_blocks(num=5) fee_per_byte = Decimal('0.00000010') fee_per_kb = 1000 * fee_per_byte diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py index 585a6a74d6..f0a9f974db 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -23,6 +23,7 @@ import time from concurrent.futures import ThreadPoolExecutor from typing import List +from .address import ADDRESS_BCRT1_P2SH_OP_TRUE from .authproxy import JSONRPCException from test_framework.blocktools import TIME_GENESIS_BLOCK from . import coverage @@ -905,18 +906,19 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass): # Set a time in the past, so that blocks don't end up in the future cache_node.setmocktime(cache_node.getblockheader(cache_node.getbestblockhash())['time']) - # Create a 199-block-long chain; each of the 4 first nodes + # Create a 199-block-long chain; each of the 3 first nodes # gets 25 mature blocks and 25 immature. - # The 4th node gets only 24 immature blocks so that the very last + # The 4th address gets 25 mature and only 24 immature blocks so that the very last # block in the cache does not age too much (have an old tip age). # This is needed so that we are out of IBD when the test starts, # see the tip age check in IsInitialBlockDownload(). self.set_genesis_mocktime() + gen_addresses = [k.address for k in TestNode.PRIV_KEYS] + [ADDRESS_BCRT1_P2SH_OP_TRUE] for i in range(8): self.bump_mocktime((25 if i != 7 else 24) * 156) cache_node.generatetoaddress( nblocks=25 if i != 7 else 24, - address=TestNode.PRIV_KEYS[i % 4].address, + address=gen_addresses[i % 4], ) assert_equal(cache_node.getblockchaininfo()["blocks"], 199) diff --git a/test/functional/test_framework/wallet.py b/test/functional/test_framework/wallet.py index 46ade5512a..ff2d73efdd 100644 --- a/test/functional/test_framework/wallet.py +++ b/test/functional/test_framework/wallet.py @@ -32,6 +32,15 @@ class MiniWallet: self._address = ADDRESS_BCRT1_P2SH_OP_TRUE self._scriptPubKey = hex_str_to_bytes(self._test_node.validateaddress(self._address)['scriptPubKey']) + def scan_blocks(self, *, start=1, num): + """Scan the blocks for self._address outputs and add them to self._utxos""" + for i in range(start, start + num): + block = self._test_node.getblock(blockhash=self._test_node.getblockhash(i), verbosity=2) + for tx in block['tx']: + for out in tx['vout']: + if out['scriptPubKey']['hex'] == self._scriptPubKey.hex(): + self._utxos.append({'txid': tx['txid'], 'vout': out['n'], 'value': out['value']}) + def generate(self, num_blocks): """Generate blocks with coinbase outputs to the internal address, and append the outputs to the internal list""" blocks = self._test_node.generatetoaddress(num_blocks, self._address) diff --git a/test/functional/wallet_txn_clone.py b/test/functional/wallet_txn_clone.py index a29e3b5155..d0a23de5d6 100755 --- a/test/functional/wallet_txn_clone.py +++ b/test/functional/wallet_txn_clone.py @@ -13,9 +13,10 @@ from test_framework.messages import ( tx_from_hex, ) + class TxnMallTest(BitcoinTestFramework): def set_test_params(self): - self.num_nodes = 4 + self.num_nodes = 3 self.supports_cli = False def skip_test_if_missing_module(self): @@ -33,9 +34,8 @@ class TxnMallTest(BitcoinTestFramework): def run_test(self): # All nodes should start with 12,500 DASH: starting_balance = 12500 - for i in range(4): + for i in range(3): assert_equal(self.nodes[i].getbalance(), starting_balance) - self.nodes[i].getnewaddress() # bug workaround, coins generated assigned to first getnewaddress! self.nodes[0].settxfee(.001) @@ -129,5 +129,6 @@ class TxnMallTest(BitcoinTestFramework): expected -= 500 assert_equal(self.nodes[0].getbalance(), expected) + if __name__ == '__main__': TxnMallTest().main() diff --git a/test/functional/wallet_txn_doublespend.py b/test/functional/wallet_txn_doublespend.py index 1663cd6908..322a4bebb9 100755 --- a/test/functional/wallet_txn_doublespend.py +++ b/test/functional/wallet_txn_doublespend.py @@ -11,9 +11,10 @@ from test_framework.util import ( find_output, ) + class TxnMallTest(BitcoinTestFramework): def set_test_params(self): - self.num_nodes = 4 + self.num_nodes = 3 self.supports_cli = False def skip_test_if_missing_module(self): @@ -39,9 +40,8 @@ class TxnMallTest(BitcoinTestFramework): for n in self.nodes: assert n.getblockchaininfo()["initialblockdownload"] == False - for i in range(4): + for i in range(3): assert_equal(self.nodes[i].getbalance(), starting_balance) - self.nodes[i].getnewaddress("") # bug workaround, coins generated assigned to first getnewaddress! # Assign coins to foo and bar addresses: node0_address_foo = self.nodes[0].getnewaddress() @@ -136,5 +136,6 @@ class TxnMallTest(BitcoinTestFramework): # Node1's balance should be its initial balance (12500 for 25 block rewards) plus the doublespend: assert_equal(self.nodes[1].getbalance(), 12500 + 12400) + if __name__ == '__main__': TxnMallTest().main()