diff options
Diffstat (limited to 'test')
-rwxr-xr-x | test/functional/feature_blockfilterindex_prune.py | 55 | ||||
-rwxr-xr-x | test/functional/feature_config_args.py | 51 | ||||
-rwxr-xr-x | test/functional/feature_proxy.py | 41 | ||||
-rwxr-xr-x | test/functional/interface_zmq.py | 42 | ||||
-rwxr-xr-x | test/functional/rpc_blockchain.py | 13 | ||||
-rwxr-xr-x | test/functional/rpc_getblockfilter.py | 6 | ||||
-rwxr-xr-x | test/functional/rpc_net.py | 4 | ||||
-rwxr-xr-x | test/functional/rpc_signmessage.py | 22 | ||||
-rwxr-xr-x | test/functional/test_framework/test_framework.py | 8 | ||||
-rw-r--r-- | test/functional/test_framework/util.py | 1 | ||||
-rw-r--r-- | test/functional/test_framework/wallet.py | 9 | ||||
-rwxr-xr-x | test/functional/wallet_listdescriptors.py | 16 | ||||
-rwxr-xr-x | test/functional/wallet_txn_clone.py | 7 | ||||
-rwxr-xr-x | test/functional/wallet_txn_doublespend.py | 7 |
14 files changed, 204 insertions, 78 deletions
diff --git a/test/functional/feature_blockfilterindex_prune.py b/test/functional/feature_blockfilterindex_prune.py index 455073ef9c..d13d191b20 100755 --- a/test/functional/feature_blockfilterindex_prune.py +++ b/test/functional/feature_blockfilterindex_prune.py @@ -5,49 +5,60 @@ """Test blockfilterindex in conjunction with prune.""" from test_framework.test_framework import BitcoinTestFramework from test_framework.util import ( - assert_raises_rpc_error, + assert_equal, assert_greater_than, + assert_raises_rpc_error, ) class FeatureBlockfilterindexPruneTest(BitcoinTestFramework): def set_test_params(self): - self.num_nodes = 2 - self.extra_args = [["-fastprune", "-prune=1"], ["-fastprune", "-prune=1", "-blockfilterindex=1"]] + self.num_nodes = 1 + self.extra_args = [["-fastprune", "-prune=1", "-blockfilterindex=1"]] + + def sync_index(self, height): + expected = {'basic block filter index': {'synced': True, 'best_block_height': height}} + self.wait_until(lambda: self.nodes[0].getindexinfo() == expected) def run_test(self): - # test basic pruning compatibility & filter access of pruned blocks self.log.info("check if we can access a blockfilter when pruning is enabled but no blocks are actually pruned") - assert len(self.nodes[1].getblockfilter(self.nodes[1].getbestblockhash())['filter']) > 0 + self.sync_index(height=200) + assert_greater_than(len(self.nodes[0].getblockfilter(self.nodes[0].getbestblockhash())['filter']), 0) # Mine two batches of blocks to avoid hitting NODE_NETWORK_LIMITED_MIN_BLOCKS disconnection - self.nodes[1].generate(250) + self.nodes[0].generate(250) self.sync_all() - self.nodes[1].generate(250) + self.nodes[0].generate(250) self.sync_all() + self.sync_index(height=700) + self.log.info("prune some blocks") - pruneheight = self.nodes[1].pruneblockchain(400) - assert pruneheight != 0 + pruneheight = self.nodes[0].pruneblockchain(400) + assert_equal(pruneheight, 250) + self.log.info("check if we can access the tips blockfilter when we have pruned some blocks") - assert len(self.nodes[1].getblockfilter(self.nodes[1].getbestblockhash())['filter']) > 0 + assert_greater_than(len(self.nodes[0].getblockfilter(self.nodes[0].getbestblockhash())['filter']), 0) + self.log.info("check if we can access the blockfilter of a pruned block") - assert len(self.nodes[1].getblockfilter(self.nodes[1].getblockhash(2))['filter']) > 0 + assert_greater_than(len(self.nodes[0].getblockfilter(self.nodes[0].getblockhash(2))['filter']), 0) + self.log.info("start node without blockfilterindex") - self.stop_node(1) - self.start_node(1, extra_args=self.extra_args[0]) + self.restart_node(0, extra_args=["-fastprune", "-prune=1"]) + self.log.info("make sure accessing the blockfilters throws an error") - assert_raises_rpc_error(-1, "Index is not enabled for filtertype basic", self.nodes[1].getblockfilter, self.nodes[1].getblockhash(2)) - self.nodes[1].generate(1000) + assert_raises_rpc_error(-1, "Index is not enabled for filtertype basic", self.nodes[0].getblockfilter, self.nodes[0].getblockhash(2)) + self.nodes[0].generate(1000) + self.log.info("prune below the blockfilterindexes best block while blockfilters are disabled") - pruneheight_new = self.nodes[1].pruneblockchain(1000) + pruneheight_new = self.nodes[0].pruneblockchain(1000) assert_greater_than(pruneheight_new, pruneheight) - self.stop_node(1) + self.stop_node(0) + self.log.info("make sure we get an init error when starting the node again with block filters") - with self.nodes[1].assert_debug_log(["basic block filter index best block of the index goes beyond pruned data. Please disable the index or reindex (which will download the whole blockchain again)"]): - self.nodes[1].assert_start_raises_init_error(extra_args=self.extra_args[1]) + with self.nodes[0].assert_debug_log(["basic block filter index best block of the index goes beyond pruned data. Please disable the index or reindex (which will download the whole blockchain again)"]): + self.nodes[0].assert_start_raises_init_error(extra_args=["-fastprune", "-prune=1", "-blockfilterindex=1"]) + self.log.info("make sure the node starts again with the -reindex arg") - reindex_args = self.extra_args[1] - reindex_args.append("-reindex") - self.start_node(1, extra_args=reindex_args) + self.start_node(0, extra_args = ["-fastprune", "-prune=1", "-blockfilterindex", "-reindex"]) if __name__ == '__main__': diff --git a/test/functional/feature_config_args.py b/test/functional/feature_config_args.py index 573760a8cb..a0bcd9f12a 100755 --- a/test/functional/feature_config_args.py +++ b/test/functional/feature_config_args.py @@ -19,7 +19,7 @@ class ConfArgsTest(BitcoinTestFramework): self.wallet_names = [] def test_config_file_parser(self): - # Assume node is stopped + self.stop_node(0) inc_conf_file_path = os.path.join(self.nodes[0].datadir, 'include.conf') with open(os.path.join(self.nodes[0].datadir, 'bitcoin.conf'), 'a', encoding='utf-8') as conf: @@ -89,11 +89,12 @@ class ConfArgsTest(BitcoinTestFramework): ) def test_log_buffer(self): + self.stop_node(0) 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']) - self.stop_node(0) def test_args_log(self): + self.stop_node(0) self.log.info('Test config args logging') with self.nodes[0].assert_debug_log( expected_msgs=[ @@ -120,37 +121,41 @@ class ConfArgsTest(BitcoinTestFramework): '-rpcuser=secret-rpcuser', '-torpassword=secret-torpassword', ]) - self.stop_node(0) def test_networkactive(self): self.log.info('Test -networkactive option') + self.stop_node(0) with self.nodes[0].assert_debug_log(expected_msgs=['SetNetworkActive: true\n']): self.start_node(0) - self.stop_node(0) + self.stop_node(0) with self.nodes[0].assert_debug_log(expected_msgs=['SetNetworkActive: true\n']): self.start_node(0, extra_args=['-networkactive']) - self.stop_node(0) + self.stop_node(0) with self.nodes[0].assert_debug_log(expected_msgs=['SetNetworkActive: true\n']): self.start_node(0, extra_args=['-networkactive=1']) - self.stop_node(0) + self.stop_node(0) with self.nodes[0].assert_debug_log(expected_msgs=['SetNetworkActive: false\n']): self.start_node(0, extra_args=['-networkactive=0']) - self.stop_node(0) + self.stop_node(0) with self.nodes[0].assert_debug_log(expected_msgs=['SetNetworkActive: false\n']): self.start_node(0, extra_args=['-nonetworkactive']) - self.stop_node(0) + self.stop_node(0) with self.nodes[0].assert_debug_log(expected_msgs=['SetNetworkActive: false\n']): self.start_node(0, extra_args=['-nonetworkactive=1']) - self.stop_node(0) def test_seed_peers(self): self.log.info('Test seed peers') default_data_dir = self.nodes[0].datadir + # Only regtest has no fixed seeds. To avoid connections to random + # nodes, regtest is the only network where it is safe to enable + # -fixedseeds in tests + util.assert_equal(self.nodes[0].getblockchaininfo()['chain'],'regtest') + self.stop_node(0) # No peers.dat exists and -dnsseed=1 # We expect the node will use DNS Seeds, but Regtest mode has 0 DNS seeds @@ -159,10 +164,12 @@ class ConfArgsTest(BitcoinTestFramework): start = int(time.time()) with self.nodes[0].assert_debug_log(expected_msgs=[ "Loaded 0 addresses from peers.dat", - "0 addresses found from DNS seeds"]): - self.start_node(0, extra_args=['-dnsseed=1 -mocktime={}'.format(start)]) + "0 addresses found from DNS seeds", + ]): + self.start_node(0, extra_args=['-dnsseed=1', '-fixedseeds=1', f'-mocktime={start}']) with self.nodes[0].assert_debug_log(expected_msgs=[ - "Adding fixed seeds as 60 seconds have passed and addrman is empty"]): + "Adding fixed seeds as 60 seconds have passed and addrman is empty", + ]): self.nodes[0].setmocktime(start + 65) self.stop_node(0) @@ -173,8 +180,9 @@ class ConfArgsTest(BitcoinTestFramework): with self.nodes[0].assert_debug_log(expected_msgs=[ "Loaded 0 addresses from peers.dat", "DNS seeding disabled", - "Adding fixed seeds as -dnsseed=0, -addnode is not provided and all -seednode(s) attempted\n"]): - self.start_node(0, extra_args=['-dnsseed=0']) + "Adding fixed seeds as -dnsseed=0, -addnode is not provided and all -seednode(s) attempted\n", + ]): + self.start_node(0, extra_args=['-dnsseed=0', '-fixedseeds=1']) assert time.time() - start < 60 self.stop_node(0) @@ -185,7 +193,8 @@ class ConfArgsTest(BitcoinTestFramework): with self.nodes[0].assert_debug_log(expected_msgs=[ "Loaded 0 addresses from peers.dat", "DNS seeding disabled", - "Fixed seeds are disabled"]): + "Fixed seeds are disabled", + ]): self.start_node(0, extra_args=['-dnsseed=0', '-fixedseeds=0']) assert time.time() - start < 60 self.stop_node(0) @@ -196,17 +205,15 @@ class ConfArgsTest(BitcoinTestFramework): start = int(time.time()) with self.nodes[0].assert_debug_log(expected_msgs=[ "Loaded 0 addresses from peers.dat", - "DNS seeding disabled"]): - self.start_node(0, extra_args=['-dnsseed=0', '-addnode=fakenodeaddr -mocktime={}'.format(start)]) + "DNS seeding disabled", + ]): + self.start_node(0, extra_args=['-dnsseed=0', '-fixedseeds=1', '-addnode=fakenodeaddr', f'-mocktime={start}']) with self.nodes[0].assert_debug_log(expected_msgs=[ - "Adding fixed seeds as 60 seconds have passed and addrman is empty"]): + "Adding fixed seeds as 60 seconds have passed and addrman is empty", + ]): self.nodes[0].setmocktime(start + 65) - self.stop_node(0) - def run_test(self): - self.stop_node(0) - self.test_log_buffer() self.test_args_log() self.test_seed_peers() diff --git a/test/functional/feature_proxy.py b/test/functional/feature_proxy.py index 2983feaa0d..8bee43b8ad 100755 --- a/test/functional/feature_proxy.py +++ b/test/functional/feature_proxy.py @@ -49,9 +49,10 @@ NET_UNROUTABLE = "not_publicly_routable" NET_IPV4 = "ipv4" NET_IPV6 = "ipv6" NET_ONION = "onion" +NET_I2P = "i2p" # Networks returned by RPC getnetworkinfo, defined in src/rpc/net.cpp::GetNetworksInfo() -NETWORKS = frozenset({NET_IPV4, NET_IPV6, NET_ONION}) +NETWORKS = frozenset({NET_IPV4, NET_IPV6, NET_ONION, NET_I2P}) class ProxyTest(BitcoinTestFramework): @@ -90,11 +91,15 @@ class ProxyTest(BitcoinTestFramework): self.serv3 = Socks5Server(self.conf3) self.serv3.start() + # We will not try to connect to this. + self.i2p_sam = ('127.0.0.1', 7656) + # Note: proxies are not used to connect to local nodes. This is because the proxy to # use is based on CService.GetNetwork(), which returns NET_UNROUTABLE for localhost. args = [ ['-listen', '-proxy=%s:%i' % (self.conf1.addr),'-proxyrandomize=1'], - ['-listen', '-proxy=%s:%i' % (self.conf1.addr),'-onion=%s:%i' % (self.conf2.addr),'-proxyrandomize=0'], + ['-listen', '-proxy=%s:%i' % (self.conf1.addr),'-onion=%s:%i' % (self.conf2.addr), + '-i2psam=%s:%i' % (self.i2p_sam), '-i2pacceptincoming=0', '-proxyrandomize=0'], ['-listen', '-proxy=%s:%i' % (self.conf2.addr),'-proxyrandomize=1'], [] ] @@ -199,9 +204,16 @@ class ProxyTest(BitcoinTestFramework): n0 = networks_dict(self.nodes[0].getnetworkinfo()) assert_equal(NETWORKS, n0.keys()) for net in NETWORKS: - assert_equal(n0[net]['proxy'], '%s:%i' % (self.conf1.addr)) - assert_equal(n0[net]['proxy_randomize_credentials'], True) + if net == NET_I2P: + expected_proxy = '' + expected_randomize = False + else: + expected_proxy = '%s:%i' % (self.conf1.addr) + expected_randomize = True + assert_equal(n0[net]['proxy'], expected_proxy) + assert_equal(n0[net]['proxy_randomize_credentials'], expected_randomize) assert_equal(n0['onion']['reachable'], True) + assert_equal(n0['i2p']['reachable'], False) n1 = networks_dict(self.nodes[1].getnetworkinfo()) assert_equal(NETWORKS, n1.keys()) @@ -211,21 +223,36 @@ class ProxyTest(BitcoinTestFramework): assert_equal(n1['onion']['proxy'], '%s:%i' % (self.conf2.addr)) assert_equal(n1['onion']['proxy_randomize_credentials'], False) assert_equal(n1['onion']['reachable'], True) + assert_equal(n1['i2p']['proxy'], '%s:%i' % (self.i2p_sam)) + assert_equal(n1['i2p']['proxy_randomize_credentials'], False) + assert_equal(n1['i2p']['reachable'], True) n2 = networks_dict(self.nodes[2].getnetworkinfo()) assert_equal(NETWORKS, n2.keys()) for net in NETWORKS: - assert_equal(n2[net]['proxy'], '%s:%i' % (self.conf2.addr)) - assert_equal(n2[net]['proxy_randomize_credentials'], True) + if net == NET_I2P: + expected_proxy = '' + expected_randomize = False + else: + expected_proxy = '%s:%i' % (self.conf2.addr) + expected_randomize = True + assert_equal(n2[net]['proxy'], expected_proxy) + assert_equal(n2[net]['proxy_randomize_credentials'], expected_randomize) assert_equal(n2['onion']['reachable'], True) + assert_equal(n2['i2p']['reachable'], False) if self.have_ipv6: n3 = networks_dict(self.nodes[3].getnetworkinfo()) assert_equal(NETWORKS, n3.keys()) for net in NETWORKS: - assert_equal(n3[net]['proxy'], '[%s]:%i' % (self.conf3.addr)) + if net == NET_I2P: + expected_proxy = '' + else: + expected_proxy = '[%s]:%i' % (self.conf3.addr) + assert_equal(n3[net]['proxy'], expected_proxy) assert_equal(n3[net]['proxy_randomize_credentials'], False) assert_equal(n3['onion']['reachable'], False) + assert_equal(n3['i2p']['reachable'], False) if __name__ == '__main__': diff --git a/test/functional/interface_zmq.py b/test/functional/interface_zmq.py index d0967a9340..94e162b748 100755 --- a/test/functional/interface_zmq.py +++ b/test/functional/interface_zmq.py @@ -62,6 +62,31 @@ class ZMQSubscriber: return (hash, label, mempool_sequence) +class ZMQTestSetupBlock: + """Helper class for setting up a ZMQ test via the "sync up" procedure. + Generates a block on the specified node on instantiation and provides a + method to check whether a ZMQ notification matches, i.e. the event was + caused by this generated block. Assumes that a notification either contains + the generated block's hash, it's (coinbase) transaction id, the raw block or + raw transaction data. + """ + + def __init__(self, node): + self.block_hash = node.generate(1)[0] + coinbase = node.getblock(self.block_hash, 2)['tx'][0] + self.tx_hash = coinbase['txid'] + self.raw_tx = coinbase['hex'] + self.raw_block = node.getblock(self.block_hash, 0) + + def caused_notification(self, notification): + return ( + self.block_hash in notification + or self.tx_hash in notification + or self.raw_block in notification + or self.raw_tx in notification + ) + + class ZMQTest (BitcoinTestFramework): def set_test_params(self): self.num_nodes = 2 @@ -105,17 +130,18 @@ class ZMQTest (BitcoinTestFramework): # Ensure that all zmq publisher notification interfaces are ready by # running the following "sync up" procedure: # 1. Generate a block on the node - # 2. Try to receive a notification on all subscribers - # 3. If all subscribers get a message within the timeout (1 second), + # 2. Try to receive the corresponding notification on all subscribers + # 3. If all subscribers get the message within the timeout (1 second), # we are done, otherwise repeat starting from step 1 for sub in subscribers: sub.socket.set(zmq.RCVTIMEO, 1000) while True: - self.nodes[0].generate(1) + test_block = ZMQTestSetupBlock(self.nodes[0]) recv_failed = False for sub in subscribers: try: - sub.receive() + while not test_block.caused_notification(sub.receive().hex()): + self.log.debug("Ignoring sync-up notification for previously generated block.") except zmq.error.Again: self.log.debug("Didn't receive sync-up notification, trying again.") recv_failed = True @@ -340,7 +366,7 @@ class ZMQTest (BitcoinTestFramework): block_count = self.nodes[0].getblockcount() best_hash = self.nodes[0].getbestblockhash() self.nodes[0].invalidateblock(best_hash) - sleep(2) # Bit of room to make sure transaction things happened + sleep(2) # Bit of room to make sure transaction things happened # Make sure getrawmempool mempool_sequence results aren't "queued" but immediately reflective # of the time they were gathered. @@ -389,8 +415,8 @@ class ZMQTest (BitcoinTestFramework): assert_equal(label, "A") # More transactions to be simply mined for i in range(len(more_tx)): - assert_equal((more_tx[i], "A", mempool_seq), seq.receive_sequence()) - mempool_seq += 1 + assert_equal((more_tx[i], "A", mempool_seq), seq.receive_sequence()) + mempool_seq += 1 # Bumped by rbf assert_equal((orig_txid, "R", mempool_seq), seq.receive_sequence()) mempool_seq += 1 @@ -405,7 +431,7 @@ class ZMQTest (BitcoinTestFramework): assert_equal((orig_txid_2, "A", mempool_seq), seq.receive_sequence()) mempool_seq += 1 self.nodes[0].generatetoaddress(1, ADDRESS_BCRT1_UNSPENDABLE) - self.sync_all() # want to make sure we didn't break "consensus" for other tests + self.sync_all() # want to make sure we didn't break "consensus" for other tests def test_mempool_sync(self): """ diff --git a/test/functional/rpc_blockchain.py b/test/functional/rpc_blockchain.py index a6afbad0fc..e090030205 100755 --- a/test/functional/rpc_blockchain.py +++ b/test/functional/rpc_blockchain.py @@ -23,6 +23,7 @@ import http.client import os import subprocess +from test_framework.address import ADDRESS_BCRT1_P2WSH_OP_TRUE from test_framework.blocktools import ( create_block, create_coinbase, @@ -71,11 +72,10 @@ class BlockchainTest(BitcoinTestFramework): def mine_chain(self): self.log.info('Create some old blocks') - address = self.nodes[0].get_deterministic_priv_key().address for t in range(TIME_GENESIS_BLOCK, TIME_GENESIS_BLOCK + 200 * 600, 600): # ten-minute steps from genesis block time self.nodes[0].setmocktime(t) - self.nodes[0].generatetoaddress(1, address) + self.nodes[0].generatetoaddress(1, ADDRESS_BCRT1_P2WSH_OP_TRUE) assert_equal(self.nodes[0].getblockchaininfo()['blocks'], 200) def _test_getblockchaininfo(self): @@ -227,7 +227,7 @@ class BlockchainTest(BitcoinTestFramework): assert_equal(res['transactions'], 200) assert_equal(res['height'], 200) assert_equal(res['txouts'], 200) - assert_equal(res['bogosize'], 15000), + assert_equal(res['bogosize'], 16800), assert_equal(res['bestblock'], node.getblockhash(200)) size = res['disk_size'] assert size > 6400 @@ -332,12 +332,12 @@ class BlockchainTest(BitcoinTestFramework): def _test_stopatheight(self): assert_equal(self.nodes[0].getblockcount(), 200) - self.nodes[0].generatetoaddress(6, self.nodes[0].get_deterministic_priv_key().address) + self.nodes[0].generatetoaddress(6, ADDRESS_BCRT1_P2WSH_OP_TRUE) assert_equal(self.nodes[0].getblockcount(), 206) 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_P2WSH_OP_TRUE) except (ConnectionError, http.client.BadStatusLine): pass # The node already shut down before response self.log.debug('Node should stop at this height...') @@ -387,8 +387,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/rpc_getblockfilter.py b/test/functional/rpc_getblockfilter.py index 044dbd35bf..a99e50f29f 100755 --- a/test/functional/rpc_getblockfilter.py +++ b/test/functional/rpc_getblockfilter.py @@ -54,5 +54,11 @@ class GetBlockFilterTest(BitcoinTestFramework): genesis_hash = self.nodes[0].getblockhash(0) assert_raises_rpc_error(-5, "Unknown filtertype", self.nodes[0].getblockfilter, genesis_hash, "unknown") + # Test getblockfilter fails on node without compact block filter index + self.restart_node(0, extra_args=["-blockfilterindex=0"]) + for filter_type in FILTER_TYPES: + assert_raises_rpc_error(-1, "Index is not enabled for filtertype {}".format(filter_type), + self.nodes[0].getblockfilter, genesis_hash, filter_type) + if __name__ == '__main__': GetBlockFilterTest().main() diff --git a/test/functional/rpc_net.py b/test/functional/rpc_net.py index 2d41963beb..9adb32c3c5 100755 --- a/test/functional/rpc_net.py +++ b/test/functional/rpc_net.py @@ -105,7 +105,7 @@ class NetTest(BitcoinTestFramework): assert_equal(peer_info[1][1]['connection_type'], 'inbound') # Check dynamically generated networks list in getpeerinfo help output. - assert "(ipv4, ipv6, onion, not_publicly_routable)" in self.nodes[0].help("getpeerinfo") + assert "(ipv4, ipv6, onion, i2p, not_publicly_routable)" in self.nodes[0].help("getpeerinfo") def test_getnettotals(self): self.log.info("Test getnettotals") @@ -156,7 +156,7 @@ class NetTest(BitcoinTestFramework): assert_net_servicesnames(int(info["localservices"], 0x10), info["localservicesnames"]) # Check dynamically generated networks list in getnetworkinfo help output. - assert "(ipv4, ipv6, onion)" in self.nodes[0].help("getnetworkinfo") + assert "(ipv4, ipv6, onion, i2p)" in self.nodes[0].help("getnetworkinfo") def test_getaddednodeinfo(self): self.log.info("Test getaddednodeinfo") diff --git a/test/functional/rpc_signmessage.py b/test/functional/rpc_signmessage.py index 0cb3ce4215..1c71732a61 100755 --- a/test/functional/rpc_signmessage.py +++ b/test/functional/rpc_signmessage.py @@ -5,7 +5,10 @@ """Test RPC commands for signing and verifying messages.""" from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import assert_equal +from test_framework.util import ( + assert_equal, + assert_raises_rpc_error, +) class SignMessagesTest(BitcoinTestFramework): def set_test_params(self): @@ -38,5 +41,22 @@ class SignMessagesTest(BitcoinTestFramework): assert not self.nodes[0].verifymessage(other_address, signature, message) assert not self.nodes[0].verifymessage(address, other_signature, message) + self.log.info('test parameter validity and error codes') + # signmessage(withprivkey) have two required parameters + for num_params in [0, 1, 3, 4, 5]: + param_list = ["dummy"]*num_params + assert_raises_rpc_error(-1, "signmessagewithprivkey", self.nodes[0].signmessagewithprivkey, *param_list) + assert_raises_rpc_error(-1, "signmessage", self.nodes[0].signmessage, *param_list) + # verifymessage has three required parameters + for num_params in [0, 1, 2, 4, 5]: + param_list = ["dummy"]*num_params + assert_raises_rpc_error(-1, "verifymessage", self.nodes[0].verifymessage, *param_list) + # invalid key or address provided + assert_raises_rpc_error(-5, "Invalid private key", self.nodes[0].signmessagewithprivkey, "invalid_key", message) + assert_raises_rpc_error(-5, "Invalid address", self.nodes[0].signmessage, "invalid_addr", message) + assert_raises_rpc_error(-5, "Invalid address", self.nodes[0].verifymessage, "invalid_addr", signature, message) + # malformed signature provided + assert_raises_rpc_error(-3, "Malformed base64 encoding", self.nodes[0].verifymessage, self.nodes[0].getnewaddress(), "invalid_sig", message) + if __name__ == '__main__': SignMessagesTest().main() diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py index f7eaaa548f..02eb10b5a4 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -19,6 +19,7 @@ import tempfile import time from typing import List +from .address import ADDRESS_BCRT1_P2WSH_OP_TRUE from .authproxy import JSONRPCException from . import coverage from .p2p import NetworkThread @@ -732,16 +733,17 @@ 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(). + gen_addresses = [k.address for k in TestNode.PRIV_KEYS] + [ADDRESS_BCRT1_P2WSH_OP_TRUE] for i in range(8): 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/util.py b/test/functional/test_framework/util.py index 123c48852c..d335d4ea79 100644 --- a/test/functional/test_framework/util.py +++ b/test/functional/test_framework/util.py @@ -368,6 +368,7 @@ def write_config(config_path, *, n, chain, extra_config=""): f.write("keypool=1\n") f.write("discover=0\n") f.write("dnsseed=0\n") + f.write("fixedseeds=0\n") f.write("listenonion=0\n") f.write("printtoconsole=0\n") f.write("upnp=0\n") diff --git a/test/functional/test_framework/wallet.py b/test/functional/test_framework/wallet.py index edd7792608..38fbf3c1a6 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_P2WSH_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_listdescriptors.py b/test/functional/wallet_listdescriptors.py index 9f8c341bc7..8d02949ff4 100755 --- a/test/functional/wallet_listdescriptors.py +++ b/test/functional/wallet_listdescriptors.py @@ -50,6 +50,22 @@ class ListDescriptorsTest(BitcoinTestFramework): assert item['range'] == [0, 0] assert item['timestamp'] is not None + self.log.info('Test descriptors with hardened derivations are listed in importable form.') + xprv = 'tprv8ZgxMBicQKsPeuVhWwi6wuMQGfPKi9Li5GtX35jVNknACgqe3CY4g5xgkfDDJcmtF7o1QnxWDRYw4H5P26PXq7sbcUkEqeR4fg3Kxp2tigg' + xpub_acc = 'tpubDCMVLhErorrAGfApiJSJzEKwqeaf2z3NrkVMxgYQjZLzMjXMBeRw2muGNYbvaekAE8rUFLftyEar4LdrG2wXyyTJQZ26zptmeTEjPTaATts' + hardened_path = '/84\'/1\'/0\'' + wallet = node.get_wallet_rpc('w2') + wallet.importdescriptors([{ + 'desc': descsum_create('wpkh(' + xprv + hardened_path + '/0/*)'), + 'timestamp': 1296688602, + }]) + expected = {'desc': descsum_create('wpkh([80002067' + hardened_path + ']' + xpub_acc + '/0/*)'), + 'timestamp': 1296688602, + 'active': False, + 'range': [0, 0], + 'next': 0} + assert_equal([expected], wallet.listdescriptors()) + self.log.info('Test non-active non-range combo descriptor') node.createwallet(wallet_name='w4', blank=True, descriptors=True) wallet = node.get_wallet_rpc('w4') diff --git a/test/functional/wallet_txn_clone.py b/test/functional/wallet_txn_clone.py index 893a2d9617..6fc1d13c53 100755 --- a/test/functional/wallet_txn_clone.py +++ b/test/functional/wallet_txn_clone.py @@ -11,9 +11,10 @@ from test_framework.util import ( ) from test_framework.messages import CTransaction, COIN + 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): @@ -38,9 +39,8 @@ class TxnMallTest(BitcoinTestFramework): # All nodes should start with 1,250 BTC: starting_balance = 1250 - 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) @@ -139,5 +139,6 @@ class TxnMallTest(BitcoinTestFramework): expected -= 50 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 c7f7a8546a..0cb7328948 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 (1250 for 25 block rewards) plus the doublespend: assert_equal(self.nodes[1].getbalance(), 1250 + 1240) + if __name__ == '__main__': TxnMallTest().main() |