diff options
Diffstat (limited to 'test/functional')
42 files changed, 462 insertions, 258 deletions
diff --git a/test/functional/abandonconflict.py b/test/functional/abandonconflict.py index 9748757641..c87c02492d 100755 --- a/test/functional/abandonconflict.py +++ b/test/functional/abandonconflict.py @@ -73,8 +73,8 @@ class AbandonConflictTest(BitcoinTestFramework): # Restart the node with a higher min relay fee so the parent tx is no longer in mempool # TODO: redo with eviction - stop_node(self.nodes[0],0) - self.nodes[0]=start_node(0, self.options.tmpdir, ["-minrelaytxfee=0.0001"]) + self.stop_node(0) + self.nodes[0] = self.start_node(0, self.options.tmpdir, ["-minrelaytxfee=0.0001"]) # Verify txs no longer in either node's mempool assert_equal(len(self.nodes[0].getrawmempool()), 0) @@ -100,8 +100,8 @@ class AbandonConflictTest(BitcoinTestFramework): balance = newbalance # Verify that even with a low min relay fee, the tx is not reaccepted from wallet on startup once abandoned - stop_node(self.nodes[0],0) - self.nodes[0]=start_node(0, self.options.tmpdir, ["-minrelaytxfee=0.00001"]) + self.stop_node(0) + self.nodes[0] = self.start_node(0, self.options.tmpdir, ["-minrelaytxfee=0.00001"]) assert_equal(len(self.nodes[0].getrawmempool()), 0) assert_equal(self.nodes[0].getbalance(), balance) @@ -120,8 +120,8 @@ class AbandonConflictTest(BitcoinTestFramework): balance = newbalance # Remove using high relay fee again - stop_node(self.nodes[0],0) - self.nodes[0]=start_node(0, self.options.tmpdir, ["-minrelaytxfee=0.0001"]) + self.stop_node(0) + self.nodes[0] = self.start_node(0, self.options.tmpdir, ["-minrelaytxfee=0.0001"]) assert_equal(len(self.nodes[0].getrawmempool()), 0) newbalance = self.nodes[0].getbalance() assert_equal(newbalance, balance - Decimal("24.9996")) diff --git a/test/functional/assumevalid.py b/test/functional/assumevalid.py index 8e301c4379..9d17faac51 100755 --- a/test/functional/assumevalid.py +++ b/test/functional/assumevalid.py @@ -45,7 +45,7 @@ from test_framework.mininode import (CBlockHeader, msg_headers) from test_framework.script import (CScript, OP_TRUE) from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import (start_node, p2p_port, assert_equal) +from test_framework.util import (p2p_port, assert_equal) class BaseNode(NodeConnCB): def send_header_for_blocks(self, new_blocks): @@ -63,7 +63,7 @@ class AssumeValidTest(BitcoinTestFramework): # Start node0. We don't start the other nodes yet since # we need to pre-mine a block with an invalid transaction # signature so we can pass in the block hash as assumevalid. - self.nodes = [start_node(0, self.options.tmpdir)] + self.nodes = [self.start_node(0, self.options.tmpdir)] def send_blocks_until_disconnected(self, node): """Keep sending blocks to the node until we're disconnected.""" @@ -162,14 +162,14 @@ class AssumeValidTest(BitcoinTestFramework): height += 1 # Start node1 and node2 with assumevalid so they accept a block with a bad signature. - self.nodes.append(start_node(1, self.options.tmpdir, + self.nodes.append(self.start_node(1, self.options.tmpdir, ["-assumevalid=" + hex(block102.sha256)])) node1 = BaseNode() # connects to node1 connections.append(NodeConn('127.0.0.1', p2p_port(1), self.nodes[1], node1)) node1.add_connection(connections[1]) node1.wait_for_verack() - self.nodes.append(start_node(2, self.options.tmpdir, + self.nodes.append(self.start_node(2, self.options.tmpdir, ["-assumevalid=" + hex(block102.sha256)])) node2 = BaseNode() # connects to node2 connections.append(NodeConn('127.0.0.1', p2p_port(2), self.nodes[2], node2)) diff --git a/test/functional/bip68-sequence.py b/test/functional/bip68-sequence.py index db66b7719c..87a50692f6 100755 --- a/test/functional/bip68-sequence.py +++ b/test/functional/bip68-sequence.py @@ -241,7 +241,7 @@ class BIP68Test(BitcoinTestFramework): # Now mine some blocks, but make sure tx2 doesn't get mined. # Use prioritisetransaction to lower the effective feerate to 0 - self.nodes[0].prioritisetransaction(tx2.hash, int(-self.relayfee*COIN)) + self.nodes[0].prioritisetransaction(txid=tx2.hash, fee_delta=int(-self.relayfee*COIN)) cur_time = int(time.time()) for i in range(10): self.nodes[0].setmocktime(cur_time + 600) @@ -254,7 +254,7 @@ class BIP68Test(BitcoinTestFramework): test_nonzero_locks(tx2, self.nodes[0], self.relayfee, use_height_lock=False) # Mine tx2, and then try again - self.nodes[0].prioritisetransaction(tx2.hash, int(self.relayfee*COIN)) + self.nodes[0].prioritisetransaction(txid=tx2.hash, fee_delta=int(self.relayfee*COIN)) # Advance the time on the node so that we can test timelocks self.nodes[0].setmocktime(cur_time+600) diff --git a/test/functional/bip9-softforks.py b/test/functional/bip9-softforks.py index fff47fcca9..b90b0ca628 100755 --- a/test/functional/bip9-softforks.py +++ b/test/functional/bip9-softforks.py @@ -239,7 +239,7 @@ class BIP9SoftForksTest(ComparisonTestFramework): # Restart all self.test.clear_all_connections() - stop_nodes(self.nodes) + self.stop_nodes() shutil.rmtree(self.options.tmpdir + "/node0") self.setup_chain() self.setup_network() diff --git a/test/functional/blockchain.py b/test/functional/blockchain.py index 4bfd3ee677..e205c6400c 100755 --- a/test/functional/blockchain.py +++ b/test/functional/blockchain.py @@ -10,6 +10,7 @@ Test the following RPCs: - getbestblockhash - getblockhash - getblockheader + - getchaintxstats - getnetworkhashps - verifychain @@ -17,13 +18,16 @@ Tests correspond to code in rpc/blockchain.cpp. """ from decimal import Decimal +import subprocess from test_framework.test_framework import BitcoinTestFramework from test_framework.util import ( assert_equal, + assert_raises, assert_raises_jsonrpc, assert_is_hex_string, assert_is_hash_string, + bitcoind_processes, ) @@ -33,13 +37,24 @@ class BlockchainTest(BitcoinTestFramework): super().__init__() self.setup_clean_chain = False self.num_nodes = 1 + self.extra_args = [['-stopatheight=207']] def run_test(self): + self._test_getchaintxstats() self._test_gettxoutsetinfo() self._test_getblockheader() self._test_getdifficulty() self._test_getnetworkhashps() - self.nodes[0].verifychain(4, 0) + self._test_stopatheight() + assert self.nodes[0].verifychain(4, 0) + + def _test_getchaintxstats(self): + chaintxstats = self.nodes[0].getchaintxstats(1) + # 200 txs plus genesis tx + assert_equal(chaintxstats['txcount'], 201) + # tx rate should be 1 per 10 minutes, or 1/600 + # we have to round because of binary math + assert_equal(round(chaintxstats['txrate'] * 600, 10), Decimal(1)) def _test_gettxoutsetinfo(self): node = self.nodes[0] @@ -49,6 +64,7 @@ class BlockchainTest(BitcoinTestFramework): assert_equal(res['transactions'], 200) assert_equal(res['height'], 200) assert_equal(res['txouts'], 200) + assert_equal(res['bogosize'], 17000), assert_equal(res['bestblock'], node.getblockhash(200)) size = res['disk_size'] assert size > 6400 @@ -65,6 +81,7 @@ class BlockchainTest(BitcoinTestFramework): assert_equal(res2['total_amount'], Decimal('0')) assert_equal(res2['height'], 0) assert_equal(res2['txouts'], 0) + assert_equal(res2['bogosize'], 0), assert_equal(res2['bestblock'], node.getblockhash(0)) assert_equal(len(res2['hash_serialized_2']), 64) @@ -76,6 +93,7 @@ class BlockchainTest(BitcoinTestFramework): assert_equal(res['transactions'], res3['transactions']) assert_equal(res['height'], res3['height']) assert_equal(res['txouts'], res3['txouts']) + assert_equal(res['bogosize'], res3['bogosize']) assert_equal(res['bestblock'], res3['bestblock']) assert_equal(res['hash_serialized_2'], res3['hash_serialized_2']) @@ -116,5 +134,18 @@ class BlockchainTest(BitcoinTestFramework): # This should be 2 hashes every 10 minutes or 1/300 assert abs(hashes_per_second * 300 - 1) < 0.0001 + def _test_stopatheight(self): + assert_equal(self.nodes[0].getblockcount(), 200) + self.nodes[0].generate(6) + assert_equal(self.nodes[0].getblockcount(), 206) + self.log.debug('Node should not stop at this height') + assert_raises(subprocess.TimeoutExpired, lambda: bitcoind_processes[0].wait(timeout=3)) + self.nodes[0].generate(1) + self.log.debug('Node should stop at this height...') + bitcoind_processes[0].wait(timeout=3) + self.nodes[0] = self.start_node(0, self.options.tmpdir) + assert_equal(self.nodes[0].getblockcount(), 207) + + if __name__ == '__main__': BlockchainTest().main() diff --git a/test/functional/bumpfee.py b/test/functional/bumpfee.py index aaed420690..d42bab6cbf 100755 --- a/test/functional/bumpfee.py +++ b/test/functional/bumpfee.py @@ -38,12 +38,12 @@ class BumpFeeTest(BitcoinTestFramework): def setup_network(self, split=False): extra_args = [["-prematurewitness", "-walletprematurewitness", "-walletrbf={}".format(i)] for i in range(self.num_nodes)] - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args) + self.nodes = self.start_nodes(self.num_nodes, self.options.tmpdir, extra_args) # Encrypt wallet for test_locked_wallet_fails test self.nodes[1].encryptwallet(WALLET_PASSPHRASE) bitcoind_processes[1].wait() - self.nodes[1] = start_node(1, self.options.tmpdir, extra_args[1]) + self.nodes[1] = self.start_node(1, self.options.tmpdir, extra_args[1]) self.nodes[1].walletpassphrase(WALLET_PASSPHRASE, WALLET_PASSPHRASE_TIMEOUT) connect_nodes_bi(self.nodes, 0, 1) diff --git a/test/functional/config.ini.in b/test/functional/config.ini.in deleted file mode 100644 index 29586c555d..0000000000 --- a/test/functional/config.ini.in +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) 2013-2016 The Bitcoin Core developers -# Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. - -# These environment variables are set by the build process and read by -# test/functional/test_runner.py - -[environment] -SRCDIR=@abs_top_srcdir@ -BUILDDIR=@abs_top_builddir@ -EXEEXT=@EXEEXT@ - -[components] -# Which components are enabled. These are commented out by `configure` if they were disabled when running config. -@ENABLE_WALLET_TRUE@ENABLE_WALLET=true -@BUILD_BITCOIN_UTILS_TRUE@ENABLE_UTILS=true -@BUILD_BITCOIND_TRUE@ENABLE_BITCOIND=true -@ENABLE_ZMQ_TRUE@ENABLE_ZMQ=true diff --git a/test/functional/disconnect_ban.py b/test/functional/disconnect_ban.py index f453fc0261..89b68aeb25 100755 --- a/test/functional/disconnect_ban.py +++ b/test/functional/disconnect_ban.py @@ -9,10 +9,7 @@ from test_framework.mininode import wait_until from test_framework.test_framework import BitcoinTestFramework from test_framework.util import (assert_equal, assert_raises_jsonrpc, - connect_nodes_bi, - start_node, - stop_node, - ) + connect_nodes_bi) class DisconnectBanTest(BitcoinTestFramework): @@ -68,9 +65,9 @@ class DisconnectBanTest(BitcoinTestFramework): self.nodes[1].setmocktime(old_time + 3) assert_equal(len(self.nodes[1].listbanned()), 3) - stop_node(self.nodes[1], 1) + self.stop_node(1) - self.nodes[1] = start_node(1, self.options.tmpdir) + self.nodes[1] = self.start_node(1, self.options.tmpdir) listAfterShutdown = self.nodes[1].listbanned() assert_equal("127.0.0.0/24", listAfterShutdown[0]['address']) assert_equal("127.0.0.0/32", listAfterShutdown[1]['address']) diff --git a/test/functional/forknotify.py b/test/functional/forknotify.py index 9db61c8350..3bcf0a6795 100755 --- a/test/functional/forknotify.py +++ b/test/functional/forknotify.py @@ -21,10 +21,10 @@ class ForkNotifyTest(BitcoinTestFramework): self.alert_filename = os.path.join(self.options.tmpdir, "alert.txt") with open(self.alert_filename, 'w', encoding='utf8'): pass # Just open then close to create zero-length file - self.nodes.append(start_node(0, self.options.tmpdir, + self.nodes.append(self.start_node(0, self.options.tmpdir, ["-blockversion=2", "-alertnotify=echo %s >> \"" + self.alert_filename + "\""])) # Node1 mines block.version=211 blocks - self.nodes.append(start_node(1, self.options.tmpdir, + self.nodes.append(self.start_node(1, self.options.tmpdir, ["-blockversion=211"])) connect_nodes(self.nodes[1], 0) diff --git a/test/functional/fundrawtransaction.py b/test/functional/fundrawtransaction.py index 9ddafeb611..0a3166b89b 100755 --- a/test/functional/fundrawtransaction.py +++ b/test/functional/fundrawtransaction.py @@ -448,13 +448,13 @@ class RawTransactionsTest(BitcoinTestFramework): ############################################################ # locked wallet test + self.stop_node(0) + self.stop_node(2) + self.stop_node(3) self.nodes[1].encryptwallet("test") - self.nodes.pop(1) - stop_node(self.nodes[0], 0) - stop_node(self.nodes[1], 2) - stop_node(self.nodes[2], 3) + bitcoind_processes[1].wait(timeout=BITCOIND_PROC_WAIT_TIMEOUT) - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) + self.nodes = self.start_nodes(self.num_nodes, self.options.tmpdir) # This test is not meant to test fee estimation and we'd like # to be sure all txs are sent at a consistent desired feerate for node in self.nodes: diff --git a/test/functional/import-rescan.py b/test/functional/import-rescan.py index 5be095e62d..4fc5078217 100755 --- a/test/functional/import-rescan.py +++ b/test/functional/import-rescan.py @@ -21,7 +21,7 @@ happened previously. from test_framework.authproxy import JSONRPCException from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import (start_nodes, connect_nodes, sync_blocks, assert_equal, set_node_times) +from test_framework.util import (connect_nodes, sync_blocks, assert_equal, set_node_times) import collections import enum @@ -121,7 +121,7 @@ class ImportRescanTest(BitcoinTestFramework): if import_node.prune: extra_args[i] += ["-prune=1"] - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args) + self.nodes = self.start_nodes(self.num_nodes, self.options.tmpdir, extra_args) for i in range(1, self.num_nodes): connect_nodes(self.nodes[i], 0) diff --git a/test/functional/importmulti.py b/test/functional/importmulti.py index 9e3491c428..e83e85de13 100755 --- a/test/functional/importmulti.py +++ b/test/functional/importmulti.py @@ -428,8 +428,8 @@ class ImportMultiTest (BitcoinTestFramework): # restart nodes to check for proper serialization/deserialization of watch only address - stop_nodes(self.nodes) - self.nodes = start_nodes(2, self.options.tmpdir) + self.stop_nodes() + self.nodes = self.start_nodes(2, self.options.tmpdir) address_assert = self.nodes[1].validateaddress(watchonly_address) assert_equal(address_assert['iswatchonly'], True) assert_equal(address_assert['ismine'], False) diff --git a/test/functional/keypool.py b/test/functional/keypool.py index c276e64c7c..f23a427d1f 100755 --- a/test/functional/keypool.py +++ b/test/functional/keypool.py @@ -20,7 +20,7 @@ class KeyPoolTest(BitcoinTestFramework): nodes[0].encryptwallet('test') bitcoind_processes[0].wait() # Restart node 0 - nodes[0] = start_node(0, self.options.tmpdir) + nodes[0] = self.start_node(0, self.options.tmpdir) # Keep creating keys addr = nodes[0].getnewaddress() addr_data = nodes[0].validateaddress(addr) diff --git a/test/functional/listtransactions.py b/test/functional/listtransactions.py index cba370d8b0..f69f1c5724 100755 --- a/test/functional/listtransactions.py +++ b/test/functional/listtransactions.py @@ -24,7 +24,7 @@ class ListTransactionsTest(BitcoinTestFramework): def setup_nodes(self): #This test requires mocktime enable_mocktime() - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) + self.nodes = self.start_nodes(self.num_nodes, self.options.tmpdir) def run_test(self): # Simple send, 0 to 1: diff --git a/test/functional/maxuploadtarget.py b/test/functional/maxuploadtarget.py index bff1b53234..66e5bd29e6 100755 --- a/test/functional/maxuploadtarget.py +++ b/test/functional/maxuploadtarget.py @@ -146,8 +146,8 @@ class MaxUploadTest(BitcoinTestFramework): #stop and start node 0 with 1MB maxuploadtarget, whitelist 127.0.0.1 self.log.info("Restarting nodes with -whitelist=127.0.0.1") - stop_node(self.nodes[0], 0) - self.nodes[0] = start_node(0, self.options.tmpdir, ["-whitelist=127.0.0.1", "-maxuploadtarget=1", "-blockmaxsize=999000"]) + self.stop_node(0) + self.nodes[0] = self.start_node(0, self.options.tmpdir, ["-whitelist=127.0.0.1", "-maxuploadtarget=1", "-blockmaxsize=999000"]) #recreate/reconnect a test node test_nodes = [TestNode()] diff --git a/test/functional/mempool_packages.py b/test/functional/mempool_packages.py index 72f04095f4..e225493816 100755 --- a/test/functional/mempool_packages.py +++ b/test/functional/mempool_packages.py @@ -96,7 +96,7 @@ class MempoolPackagesTest(BitcoinTestFramework): # Check that ancestor modified fees includes fee deltas from # prioritisetransaction - self.nodes[0].prioritisetransaction(chain[0], 1000) + self.nodes[0].prioritisetransaction(txid=chain[0], fee_delta=1000) mempool = self.nodes[0].getrawmempool(True) ancestor_fees = 0 for x in chain: @@ -104,11 +104,11 @@ class MempoolPackagesTest(BitcoinTestFramework): assert_equal(mempool[x]['ancestorfees'], ancestor_fees * COIN + 1000) # Undo the prioritisetransaction for later tests - self.nodes[0].prioritisetransaction(chain[0], -1000) + self.nodes[0].prioritisetransaction(txid=chain[0], fee_delta=-1000) # Check that descendant modified fees includes fee deltas from # prioritisetransaction - self.nodes[0].prioritisetransaction(chain[-1], 1000) + self.nodes[0].prioritisetransaction(txid=chain[-1], fee_delta=1000) mempool = self.nodes[0].getrawmempool(True) descendant_fees = 0 @@ -126,7 +126,7 @@ class MempoolPackagesTest(BitcoinTestFramework): assert_equal(len(self.nodes[0].getrawmempool()), 0) # Prioritise a transaction that has been mined, then add it back to the # mempool by using invalidateblock. - self.nodes[0].prioritisetransaction(chain[-1], 2000) + self.nodes[0].prioritisetransaction(txid=chain[-1], fee_delta=2000) self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash()) # Keep node1's tip synced with node0 self.nodes[1].invalidateblock(self.nodes[1].getbestblockhash()) diff --git a/test/functional/mempool_persist.py b/test/functional/mempool_persist.py index 7b15476ea2..e0889fd5e9 100755 --- a/test/functional/mempool_persist.py +++ b/test/functional/mempool_persist.py @@ -63,27 +63,27 @@ class MempoolPersistTest(BitcoinTestFramework): assert_equal(len(self.nodes[1].getrawmempool()), 5) self.log.debug("Stop-start node0 and node1. Verify that node0 has the transactions in its mempool and node1 does not.") - stop_nodes(self.nodes) + self.stop_nodes() self.nodes = [] - self.nodes.append(start_node(0, self.options.tmpdir)) - self.nodes.append(start_node(1, self.options.tmpdir)) + self.nodes.append(self.start_node(0, self.options.tmpdir)) + self.nodes.append(self.start_node(1, self.options.tmpdir)) # Give bitcoind a second to reload the mempool time.sleep(1) assert wait_until(lambda: len(self.nodes[0].getrawmempool()) == 5) assert_equal(len(self.nodes[1].getrawmempool()), 0) self.log.debug("Stop-start node0 with -persistmempool=0. Verify that it doesn't load its mempool.dat file.") - stop_nodes(self.nodes) + self.stop_nodes() self.nodes = [] - self.nodes.append(start_node(0, self.options.tmpdir, ["-persistmempool=0"])) + self.nodes.append(self.start_node(0, self.options.tmpdir, ["-persistmempool=0"])) # Give bitcoind a second to reload the mempool time.sleep(1) assert_equal(len(self.nodes[0].getrawmempool()), 0) self.log.debug("Stop-start node0. Verify that it has the transactions in its mempool.") - stop_nodes(self.nodes) + self.stop_nodes() self.nodes = [] - self.nodes.append(start_node(0, self.options.tmpdir)) + self.nodes.append(self.start_node(0, self.options.tmpdir)) assert wait_until(lambda: len(self.nodes[0].getrawmempool()) == 5) if __name__ == '__main__': diff --git a/test/functional/merkle_blocks.py b/test/functional/merkle_blocks.py index 06af72ef10..bcc65c8408 100755 --- a/test/functional/merkle_blocks.py +++ b/test/functional/merkle_blocks.py @@ -39,7 +39,8 @@ class MerkleBlockTest(BitcoinTestFramework): txid1 = self.nodes[0].sendrawtransaction(self.nodes[0].signrawtransaction(tx1)["hex"]) tx2 = self.nodes[0].createrawtransaction([node0utxos.pop()], {self.nodes[1].getnewaddress(): 49.99}) txid2 = self.nodes[0].sendrawtransaction(self.nodes[0].signrawtransaction(tx2)["hex"]) - assert_raises(JSONRPCException, self.nodes[0].gettxoutproof, [txid1]) + # This will raise an exception because the transaction is not yet in a block + assert_raises_jsonrpc(-5, "Transaction not yet in block", self.nodes[0].gettxoutproof, [txid1]) self.nodes[0].generate(1) blockhash = self.nodes[0].getblockhash(chain_height + 1) @@ -56,7 +57,7 @@ class MerkleBlockTest(BitcoinTestFramework): txin_spent = self.nodes[1].listunspent(1).pop() tx3 = self.nodes[1].createrawtransaction([txin_spent], {self.nodes[0].getnewaddress(): 49.98}) - self.nodes[0].sendrawtransaction(self.nodes[1].signrawtransaction(tx3)["hex"]) + txid3 = self.nodes[0].sendrawtransaction(self.nodes[1].signrawtransaction(tx3)["hex"]) self.nodes[0].generate(1) self.sync_all() @@ -64,17 +65,21 @@ class MerkleBlockTest(BitcoinTestFramework): txid_unspent = txid1 if txin_spent["txid"] != txid1 else txid2 # We can't find the block from a fully-spent tx - assert_raises(JSONRPCException, self.nodes[2].gettxoutproof, [txid_spent]) - # ...but we can if we specify the block + assert_raises_jsonrpc(-5, "Transaction not yet in block", self.nodes[2].gettxoutproof, [txid_spent]) + # We can get the proof if we specify the block assert_equal(self.nodes[2].verifytxoutproof(self.nodes[2].gettxoutproof([txid_spent], blockhash)), [txid_spent]) - # ...or if the first tx is not fully-spent + # We can't get the proof if we specify a non-existent block + assert_raises_jsonrpc(-5, "Block not found", self.nodes[2].gettxoutproof, [txid_spent], "00000000000000000000000000000000") + # We can get the proof if the transaction is unspent assert_equal(self.nodes[2].verifytxoutproof(self.nodes[2].gettxoutproof([txid_unspent])), [txid_unspent]) - try: - assert_equal(self.nodes[2].verifytxoutproof(self.nodes[2].gettxoutproof([txid1, txid2])), txlist) - except JSONRPCException: - assert_equal(self.nodes[2].verifytxoutproof(self.nodes[2].gettxoutproof([txid2, txid1])), txlist) - # ...or if we have a -txindex + # We can get the proof if we provide a list of transactions and one of them is unspent. The ordering of the list should not matter. + assert_equal(sorted(self.nodes[2].verifytxoutproof(self.nodes[2].gettxoutproof([txid1, txid2]))), sorted(txlist)) + assert_equal(sorted(self.nodes[2].verifytxoutproof(self.nodes[2].gettxoutproof([txid2, txid1]))), sorted(txlist)) + # We can always get a proof if we have a -txindex assert_equal(self.nodes[2].verifytxoutproof(self.nodes[3].gettxoutproof([txid_spent])), [txid_spent]) + # We can't get a proof if we specify transactions from different blocks + assert_raises_jsonrpc(-5, "Not all transactions found in specified or retrieved block", self.nodes[2].gettxoutproof, [txid1, txid3]) + if __name__ == '__main__': MerkleBlockTest().main() diff --git a/test/functional/multi_rpc.py b/test/functional/multi_rpc.py index 6ff91a960b..a30e15ace9 100755 --- a/test/functional/multi_rpc.py +++ b/test/functional/multi_rpc.py @@ -16,16 +16,21 @@ class HTTPBasicsTest (BitcoinTestFramework): def __init__(self): super().__init__() self.setup_clean_chain = False - self.num_nodes = 1 + self.num_nodes = 2 def setup_chain(self): super().setup_chain() #Append rpcauth to bitcoin.conf before initialization rpcauth = "rpcauth=rt:93648e835a54c573682c2eb19f882535$7681e9c5b74bdd85e78166031d2058e1069b3ed7ed967c93fc63abba06f31144" rpcauth2 = "rpcauth=rt2:f8607b1a88861fac29dfccf9b52ff9f$ff36a0c23c8c62b4846112e50fa888416e94c17bfd4c42f88fd8f55ec6a3137e" + rpcuser = "rpcuser=rpcuser💻" + rpcpassword = "rpcpassword=rpcpassword🔑" with open(os.path.join(self.options.tmpdir+"/node0", "bitcoin.conf"), 'a', encoding='utf8') as f: f.write(rpcauth+"\n") f.write(rpcauth2+"\n") + with open(os.path.join(self.options.tmpdir+"/node1", "bitcoin.conf"), 'a', encoding='utf8') as f: + f.write(rpcuser+"\n") + f.write(rpcpassword+"\n") def run_test(self): @@ -50,7 +55,7 @@ class HTTPBasicsTest (BitcoinTestFramework): conn.connect() conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) resp = conn.getresponse() - assert_equal(resp.status==401, False) + assert_equal(resp.status, 200) conn.close() #Use new authpair to confirm both work @@ -60,7 +65,7 @@ class HTTPBasicsTest (BitcoinTestFramework): conn.connect() conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) resp = conn.getresponse() - assert_equal(resp.status==401, False) + assert_equal(resp.status, 200) conn.close() #Wrong login name with rt's password @@ -71,7 +76,7 @@ class HTTPBasicsTest (BitcoinTestFramework): conn.connect() conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) resp = conn.getresponse() - assert_equal(resp.status==401, True) + assert_equal(resp.status, 401) conn.close() #Wrong password for rt @@ -82,7 +87,7 @@ class HTTPBasicsTest (BitcoinTestFramework): conn.connect() conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) resp = conn.getresponse() - assert_equal(resp.status==401, True) + assert_equal(resp.status, 401) conn.close() #Correct for rt2 @@ -93,7 +98,7 @@ class HTTPBasicsTest (BitcoinTestFramework): conn.connect() conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) resp = conn.getresponse() - assert_equal(resp.status==401, False) + assert_equal(resp.status, 200) conn.close() #Wrong password for rt2 @@ -104,7 +109,46 @@ class HTTPBasicsTest (BitcoinTestFramework): conn.connect() conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) resp = conn.getresponse() - assert_equal(resp.status==401, True) + assert_equal(resp.status, 401) + conn.close() + + ############################################################### + # Check correctness of the rpcuser/rpcpassword config options # + ############################################################### + url = urllib.parse.urlparse(self.nodes[1].url) + + # rpcuser and rpcpassword authpair + rpcuserauthpair = "rpcuser💻:rpcpassword🔑" + + headers = {"Authorization": "Basic " + str_to_b64str(rpcuserauthpair)} + + conn = http.client.HTTPConnection(url.hostname, url.port) + conn.connect() + conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) + resp = conn.getresponse() + assert_equal(resp.status, 200) + conn.close() + + #Wrong login name with rpcuser's password + rpcuserauthpair = "rpcuserwrong:rpcpassword" + headers = {"Authorization": "Basic " + str_to_b64str(rpcuserauthpair)} + + conn = http.client.HTTPConnection(url.hostname, url.port) + conn.connect() + conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) + resp = conn.getresponse() + assert_equal(resp.status, 401) + conn.close() + + #Wrong password for rpcuser + rpcuserauthpair = "rpcuser:rpcpasswordwrong" + headers = {"Authorization": "Basic " + str_to_b64str(rpcuserauthpair)} + + conn = http.client.HTTPConnection(url.hostname, url.port) + conn.connect() + conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) + resp = conn.getresponse() + assert_equal(resp.status, 401) conn.close() diff --git a/test/functional/net.py b/test/functional/net.py index fb46064441..3ba3764cf9 100755 --- a/test/functional/net.py +++ b/test/functional/net.py @@ -29,6 +29,7 @@ class NetTest(BitcoinTestFramework): self._test_getnettotals() self._test_getnetworkinginfo() self._test_getaddednodeinfo() + self._test_getpeerinfo() def _test_connection_count(self): # connect_nodes_bi connects each node to the other @@ -88,6 +89,12 @@ class NetTest(BitcoinTestFramework): assert_raises_jsonrpc(-24, "Node has not been added", self.nodes[0].getaddednodeinfo, '1.1.1.1') + def _test_getpeerinfo(self): + peer_info = [x.getpeerinfo() for x in self.nodes] + # check both sides of bidirectional connection between nodes + # the address bound to on one side will be the source address for the other node + assert_equal(peer_info[0][0]['addrbind'], peer_info[1][0]['addr']) + assert_equal(peer_info[1][0]['addrbind'], peer_info[0][0]['addr']) if __name__ == '__main__': NetTest().main() diff --git a/test/functional/p2p-compactblocks.py b/test/functional/p2p-compactblocks.py index 9b302120ac..ff76e49fba 100755 --- a/test/functional/p2p-compactblocks.py +++ b/test/functional/p2p-compactblocks.py @@ -98,7 +98,7 @@ class CompactBlocksTest(BitcoinTestFramework): self.setup_clean_chain = True # Node0 = pre-segwit, node1 = segwit-aware self.num_nodes = 2 - self.extra_args = [["-bip9params=segwit:0:0"], ["-txindex"]] + self.extra_args = [["-vbparams=segwit:0:0"], ["-txindex"]] self.utxos = [] def build_block_on_tip(self, node, segwit=False): diff --git a/test/functional/p2p-segwit.py b/test/functional/p2p-segwit.py index 24d4d37c42..63dfbb8ae6 100755 --- a/test/functional/p2p-segwit.py +++ b/test/functional/p2p-segwit.py @@ -114,7 +114,7 @@ class SegWitTest(BitcoinTestFramework): super().__init__() self.setup_clean_chain = True self.num_nodes = 3 - self.extra_args = [["-whitelist=127.0.0.1"], ["-whitelist=127.0.0.1", "-acceptnonstdtxn=0"], ["-whitelist=127.0.0.1", "-bip9params=segwit:0:0"]] + self.extra_args = [["-whitelist=127.0.0.1"], ["-whitelist=127.0.0.1", "-acceptnonstdtxn=0"], ["-whitelist=127.0.0.1", "-vbparams=segwit:0:0"]] def setup_network(self): self.setup_nodes() @@ -1486,7 +1486,7 @@ class SegWitTest(BitcoinTestFramework): # nodes would have stored, this requires special handling. # To enable this test, pass --oldbinary=<path-to-pre-segwit-bitcoind> to # the test. - def test_upgrade_after_activation(self, node, node_id): + def test_upgrade_after_activation(self, node_id): self.log.info("Testing software upgrade after softfork activation") assert(node_id != 0) # node0 is assumed to be a segwit-active bitcoind @@ -1495,21 +1495,21 @@ class SegWitTest(BitcoinTestFramework): sync_blocks(self.nodes) # Restart with the new binary - stop_node(node, node_id) - self.nodes[node_id] = start_node(node_id, self.options.tmpdir) + self.stop_node(node_id) + self.nodes[node_id] = self.start_node(node_id, self.options.tmpdir) connect_nodes(self.nodes[0], node_id) sync_blocks(self.nodes) # Make sure that this peer thinks segwit has activated. - assert(get_bip9_status(node, 'segwit')['status'] == "active") + assert(get_bip9_status(self.nodes[node_id], 'segwit')['status'] == "active") # Make sure this peers blocks match those of node0. - height = node.getblockcount() + height = self.nodes[node_id].getblockcount() while height >= 0: - block_hash = node.getblockhash(height) + block_hash = self.nodes[node_id].getblockhash(height) assert_equal(block_hash, self.nodes[0].getblockhash(height)) - assert_equal(self.nodes[0].getblock(block_hash), node.getblock(block_hash)) + assert_equal(self.nodes[0].getblock(block_hash), self.nodes[node_id].getblock(block_hash)) height -= 1 @@ -1944,7 +1944,7 @@ class SegWitTest(BitcoinTestFramework): self.test_signature_version_1() self.test_non_standard_witness() sync_blocks(self.nodes) - self.test_upgrade_after_activation(self.nodes[2], 2) + self.test_upgrade_after_activation(node_id=2) self.test_witness_sigops() diff --git a/test/functional/p2p-versionbits-warning.py b/test/functional/p2p-versionbits-warning.py index 41921fe14e..df7e8ce5c1 100755 --- a/test/functional/p2p-versionbits-warning.py +++ b/test/functional/p2p-versionbits-warning.py @@ -108,22 +108,22 @@ class VersionBitsWarningTest(BitcoinTestFramework): # is cleared, and restart the node. This should move the versionbit state # to ACTIVE. self.nodes[0].generate(VB_PERIOD) - stop_nodes(self.nodes) + self.stop_nodes() # Empty out the alert file with open(self.alert_filename, 'w', encoding='utf8') as _: pass - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, self.extra_args) + self.nodes = self.start_nodes(self.num_nodes, self.options.tmpdir, self.extra_args) # Connecting one block should be enough to generate an error. self.nodes[0].generate(1) assert(WARN_UNKNOWN_RULES_ACTIVE in self.nodes[0].getinfo()["errors"]) assert(WARN_UNKNOWN_RULES_ACTIVE in self.nodes[0].getmininginfo()["errors"]) assert(WARN_UNKNOWN_RULES_ACTIVE in self.nodes[0].getnetworkinfo()["warnings"]) - stop_nodes(self.nodes) + self.stop_nodes() self.test_versionbits_in_alert_file() # Test framework expects the node to still be running... - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, self.extra_args) + self.nodes = self.start_nodes(self.num_nodes, self.options.tmpdir, self.extra_args) if __name__ == '__main__': VersionBitsWarningTest().main() diff --git a/test/functional/prioritise_transaction.py b/test/functional/prioritise_transaction.py index 9c3b3fd5d9..4fc03d2547 100755 --- a/test/functional/prioritise_transaction.py +++ b/test/functional/prioritise_transaction.py @@ -46,7 +46,7 @@ class PrioritiseTransactionTest(BitcoinTestFramework): # add a fee delta to something in the cheapest bucket and make sure it gets mined # also check that a different entry in the cheapest bucket is NOT mined - self.nodes[0].prioritisetransaction(txids[0][0], int(3*base_fee*COIN)) + self.nodes[0].prioritisetransaction(txid=txids[0][0], fee_delta=int(3*base_fee*COIN)) self.nodes[0].generate(1) @@ -65,7 +65,7 @@ class PrioritiseTransactionTest(BitcoinTestFramework): # Add a prioritisation before a tx is in the mempool (de-prioritising a # high-fee transaction so that it's now low fee). - self.nodes[0].prioritisetransaction(high_fee_tx, -int(2*base_fee*COIN)) + self.nodes[0].prioritisetransaction(txid=high_fee_tx, fee_delta=-int(2*base_fee*COIN)) # Add everything back to mempool self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash()) @@ -109,7 +109,7 @@ class PrioritiseTransactionTest(BitcoinTestFramework): # This is a less than 1000-byte transaction, so just set the fee # to be the minimum for a 1000 byte transaction and check that it is # accepted. - self.nodes[0].prioritisetransaction(tx_id, int(self.relayfee*COIN)) + self.nodes[0].prioritisetransaction(txid=tx_id, fee_delta=int(self.relayfee*COIN)) self.log.info("Assert that prioritised free transaction is accepted to mempool") assert_equal(self.nodes[0].sendrawtransaction(tx_hex), tx_id) @@ -120,7 +120,7 @@ class PrioritiseTransactionTest(BitcoinTestFramework): mock_time = int(time.time()) self.nodes[0].setmocktime(mock_time) template = self.nodes[0].getblocktemplate() - self.nodes[0].prioritisetransaction(tx_id, -int(self.relayfee*COIN)) + self.nodes[0].prioritisetransaction(txid=tx_id, fee_delta=-int(self.relayfee*COIN)) self.nodes[0].setmocktime(mock_time+10) new_template = self.nodes[0].getblocktemplate() diff --git a/test/functional/proxy_test.py b/test/functional/proxy_test.py index 69384d9d85..ae6f843ddc 100755 --- a/test/functional/proxy_test.py +++ b/test/functional/proxy_test.py @@ -35,7 +35,6 @@ from test_framework.test_framework import BitcoinTestFramework from test_framework.util import ( PORT_MIN, PORT_RANGE, - start_nodes, assert_equal, ) from test_framework.netutil import test_ipv6_local @@ -90,7 +89,7 @@ class ProxyTest(BitcoinTestFramework): ] if self.have_ipv6: args[3] = ['-listen', '-proxy=[%s]:%i' % (self.conf3.addr),'-proxyrandomize=0', '-noonion'] - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args=args) + self.nodes = self.start_nodes(self.num_nodes, self.options.tmpdir, extra_args=args) def node_test(self, node, proxies, auth, test_onion=True): rv = [] diff --git a/test/functional/pruning.py b/test/functional/pruning.py index 7995e418c9..37e9d29738 100755 --- a/test/functional/pruning.py +++ b/test/functional/pruning.py @@ -98,7 +98,7 @@ class PruneTest(BitcoinTestFramework): # Node 2 stays connected, so it hears about the stale blocks and then reorg's when node0 reconnects # Stopping node 0 also clears its mempool, so it doesn't have node1's transactions to accidentally mine self.stop_node(0) - self.nodes[0]=start_node(0, self.options.tmpdir, self.full_node_default_args, timewait=900) + self.nodes[0]=self.start_node(0, self.options.tmpdir, self.full_node_default_args, timewait=900) # Mine 24 blocks in node 1 for i in range(24): if j == 0: @@ -126,7 +126,7 @@ class PruneTest(BitcoinTestFramework): # Reboot node 1 to clear its mempool (hopefully make the invalidate faster) # Lower the block max size so we don't keep mining all our big mempool transactions (from disconnected blocks) self.stop_node(1) - self.nodes[1]=start_node(1, self.options.tmpdir, ["-maxreceivebuffer=20000","-blockmaxsize=5000", "-checkblocks=5", "-disablesafemode"], timewait=900) + self.nodes[1] = self.start_node(1, self.options.tmpdir, ["-maxreceivebuffer=20000","-blockmaxsize=5000", "-checkblocks=5", "-disablesafemode"], timewait=900) height = self.nodes[1].getblockcount() self.log.info("Current block height: %d" % height) @@ -149,7 +149,7 @@ class PruneTest(BitcoinTestFramework): # Reboot node1 to clear those giant tx's from mempool self.stop_node(1) - self.nodes[1]=start_node(1, self.options.tmpdir, ["-maxreceivebuffer=20000","-blockmaxsize=5000", "-checkblocks=5", "-disablesafemode"], timewait=900) + self.nodes[1] = self.start_node(1, self.options.tmpdir, ["-maxreceivebuffer=20000","-blockmaxsize=5000", "-checkblocks=5", "-disablesafemode"], timewait=900) self.log.info("Generating new longer chain of 300 more blocks") self.nodes[1].generate(300) @@ -227,13 +227,13 @@ class PruneTest(BitcoinTestFramework): def manual_test(self, node_number, use_timestamp): # at this point, node has 995 blocks and has not yet run in prune mode - node = self.nodes[node_number] = start_node(node_number, self.options.tmpdir, timewait=900) + node = self.nodes[node_number] = self.start_node(node_number, self.options.tmpdir, timewait=900) assert_equal(node.getblockcount(), 995) assert_raises_jsonrpc(-1, "not in prune mode", node.pruneblockchain, 500) self.stop_node(node_number) # now re-start in manual pruning mode - node = self.nodes[node_number] = start_node(node_number, self.options.tmpdir, ["-prune=1"], timewait=900) + node = self.nodes[node_number] = self.start_node(node_number, self.options.tmpdir, ["-prune=1"], timewait=900) assert_equal(node.getblockcount(), 995) def height(index): @@ -307,7 +307,7 @@ class PruneTest(BitcoinTestFramework): # stop node, start back up with auto-prune at 550MB, make sure still runs self.stop_node(node_number) - self.nodes[node_number] = start_node(node_number, self.options.tmpdir, ["-prune=550"], timewait=900) + self.nodes[node_number] = self.start_node(node_number, self.options.tmpdir, ["-prune=550"], timewait=900) self.log.info("Success") @@ -315,7 +315,7 @@ class PruneTest(BitcoinTestFramework): # check that the pruning node's wallet is still in good shape self.log.info("Stop and start pruning node to trigger wallet rescan") self.stop_node(2) - start_node(2, self.options.tmpdir, ["-prune=550"]) + self.nodes[2] = self.start_node(2, self.options.tmpdir, ["-prune=550"]) self.log.info("Success") # check that wallet loads loads successfully when restarting a pruned node after IBD. @@ -325,7 +325,7 @@ class PruneTest(BitcoinTestFramework): nds = [self.nodes[0], self.nodes[5]] sync_blocks(nds, wait=5, timeout=300) self.stop_node(5) #stop and start to trigger rescan - start_node(5, self.options.tmpdir, ["-prune=550"]) + self.nodes[5] = self.start_node(5, self.options.tmpdir, ["-prune=550"]) self.log.info("Success") def run_test(self): diff --git a/test/functional/receivedby.py b/test/functional/receivedby.py index a1cae301c5..2cad6269ac 100755 --- a/test/functional/receivedby.py +++ b/test/functional/receivedby.py @@ -32,7 +32,7 @@ class ReceivedByTest(BitcoinTestFramework): def setup_nodes(self): #This test requires mocktime enable_mocktime() - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) + self.nodes = self.start_nodes(self.num_nodes, self.options.tmpdir) def run_test(self): ''' diff --git a/test/functional/reindex.py b/test/functional/reindex.py index 8b8c5f3e71..b446baa04d 100755 --- a/test/functional/reindex.py +++ b/test/functional/reindex.py @@ -10,11 +10,7 @@ """ from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import ( - start_nodes, - stop_nodes, - assert_equal, -) +from test_framework.util import assert_equal import time class ReindexTest(BitcoinTestFramework): @@ -27,9 +23,9 @@ class ReindexTest(BitcoinTestFramework): def reindex(self, justchainstate=False): self.nodes[0].generate(3) blockcount = self.nodes[0].getblockcount() - stop_nodes(self.nodes) + self.stop_nodes() extra_args = [["-reindex-chainstate" if justchainstate else "-reindex", "-checkblockindex=1"]] - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args) + self.nodes = self.start_nodes(self.num_nodes, self.options.tmpdir, extra_args) while self.nodes[0].getblockcount() < blockcount: time.sleep(0.1) assert_equal(self.nodes[0].getblockcount(), blockcount) diff --git a/test/functional/replace-by-fee.py b/test/functional/replace-by-fee.py index e940ce535c..d6bf3ea59f 100755 --- a/test/functional/replace-by-fee.py +++ b/test/functional/replace-by-fee.py @@ -99,6 +99,9 @@ class ReplaceByFeeTest(BitcoinTestFramework): self.log.info("Running test opt-in...") self.test_opt_in() + self.log.info("Running test RPC...") + self.test_rpc() + self.log.info("Running test prioritised transactions...") self.test_prioritised_transactions() @@ -482,7 +485,7 @@ class ReplaceByFeeTest(BitcoinTestFramework): assert_raises_jsonrpc(-26, "insufficient fee", self.nodes[0].sendrawtransaction, tx1b_hex, True) # Use prioritisetransaction to set tx1a's fee to 0. - self.nodes[0].prioritisetransaction(tx1a_txid, int(-0.1*COIN)) + self.nodes[0].prioritisetransaction(txid=tx1a_txid, fee_delta=int(-0.1*COIN)) # Now tx1b should be able to replace tx1a tx1b_txid = self.nodes[0].sendrawtransaction(tx1b_hex, True) @@ -509,12 +512,32 @@ class ReplaceByFeeTest(BitcoinTestFramework): assert_raises_jsonrpc(-26, "insufficient fee", self.nodes[0].sendrawtransaction, tx2b_hex, True) # Now prioritise tx2b to have a higher modified fee - self.nodes[0].prioritisetransaction(tx2b.hash, int(0.1*COIN)) + self.nodes[0].prioritisetransaction(txid=tx2b.hash, fee_delta=int(0.1*COIN)) # tx2b should now be accepted tx2b_txid = self.nodes[0].sendrawtransaction(tx2b_hex, True) assert(tx2b_txid in self.nodes[0].getrawmempool()) + def test_rpc(self): + us0 = self.nodes[0].listunspent()[0] + ins = [us0] + outs = {self.nodes[0].getnewaddress() : Decimal(1.0000000)} + rawtx0 = self.nodes[0].createrawtransaction(ins, outs, 0, True) + rawtx1 = self.nodes[0].createrawtransaction(ins, outs, 0, False) + json0 = self.nodes[0].decoderawtransaction(rawtx0) + json1 = self.nodes[0].decoderawtransaction(rawtx1) + assert_equal(json0["vin"][0]["sequence"], 4294967293) + assert_equal(json1["vin"][0]["sequence"], 4294967295) + + rawtx2 = self.nodes[0].createrawtransaction([], outs) + frawtx2a = self.nodes[0].fundrawtransaction(rawtx2, {"optIntoRbf": True}) + frawtx2b = self.nodes[0].fundrawtransaction(rawtx2, {"optIntoRbf": False}) + + json0 = self.nodes[0].decoderawtransaction(frawtx2a['hex']) + json1 = self.nodes[0].decoderawtransaction(frawtx2b['hex']) + assert_equal(json0["vin"][0]["sequence"], 4294967293) + assert_equal(json1["vin"][0]["sequence"], 4294967294) + if __name__ == '__main__': ReplaceByFeeTest().main() diff --git a/test/functional/rpcbind_test.py b/test/functional/rpcbind_test.py index efc36481d1..198599010e 100755 --- a/test/functional/rpcbind_test.py +++ b/test/functional/rpcbind_test.py @@ -7,7 +7,7 @@ import socket import sys -from test_framework.test_framework import BitcoinTestFramework +from test_framework.test_framework import BitcoinTestFramework, SkipTest from test_framework.util import * from test_framework.netutil import * @@ -36,10 +36,10 @@ class RPCBindTest(BitcoinTestFramework): if allow_ips: base_args += ['-rpcallowip=' + x for x in allow_ips] binds = ['-rpcbind='+addr for addr in addresses] - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, [base_args + binds], connect_to) + self.nodes = self.start_nodes(self.num_nodes, self.options.tmpdir, [base_args + binds], connect_to) pid = bitcoind_processes[0].pid assert_equal(set(get_bind_addrs(pid)), set(expected)) - stop_nodes(self.nodes) + self.stop_nodes() def run_allowip_test(self, allow_ips, rpchost, rpcport): ''' @@ -47,17 +47,16 @@ class RPCBindTest(BitcoinTestFramework): at a non-localhost IP. ''' base_args = ['-disablewallet', '-nolisten'] + ['-rpcallowip='+x for x in allow_ips] - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, [base_args]) + self.nodes = self.start_nodes(self.num_nodes, self.options.tmpdir, [base_args]) # connect to node through non-loopback interface - node = get_rpc_proxy(rpc_url(0, "%s:%d" % (rpchost, rpcport)), 0) + node = get_rpc_proxy(rpc_url(get_datadir_path(self.options.tmpdir, 0), 0, "%s:%d" % (rpchost, rpcport)), 0) node.getnetworkinfo() - stop_nodes(self.nodes) + self.stop_nodes() def run_test(self): # due to OS-specific network stats queries, this test works only on Linux if not sys.platform.startswith('linux'): - self.log.warning("This test can only be run on linux. Skipping test.") - sys.exit(self.TEST_EXIT_SKIPPED) + raise SkipTest("This test can only be run on linux.") # find the first non-loopback interface for testing non_loopback_ip = None for name,ip in all_interfaces(): @@ -65,15 +64,13 @@ class RPCBindTest(BitcoinTestFramework): non_loopback_ip = ip break if non_loopback_ip is None: - self.log.warning("This test requires at least one non-loopback IPv4 interface. Skipping test.") - sys.exit(self.TEST_EXIT_SKIPPED) + raise SkipTest("This test requires at least one non-loopback IPv4 interface.") try: s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM) s.connect(("::1",1)) s.close except OSError: - self.log.warning("This test requires IPv6 support. Skipping test.") - sys.exit(self.TEST_EXIT_SKIPPED) + raise SkipTest("This test requires IPv6 support.") self.log.info("Using interface %s for testing" % non_loopback_ip) diff --git a/test/functional/smartfees.py b/test/functional/smartfees.py index 4124f8025e..482c77863f 100755 --- a/test/functional/smartfees.py +++ b/test/functional/smartfees.py @@ -155,7 +155,7 @@ class EstimateFeeTest(BitcoinTestFramework): """ self.nodes = [] # Use node0 to mine blocks for input splitting - self.nodes.append(start_node(0, self.options.tmpdir, ["-maxorphantx=1000", + self.nodes.append(self.start_node(0, self.options.tmpdir, ["-maxorphantx=1000", "-whitelist=127.0.0.1"])) self.log.info("This test is time consuming, please be patient") @@ -191,7 +191,7 @@ class EstimateFeeTest(BitcoinTestFramework): # Node1 mines small blocks but that are bigger than the expected transaction rate. # NOTE: the CreateNewBlock code starts counting block size at 1,000 bytes, # (17k is room enough for 110 or so transactions) - self.nodes.append(start_node(1, self.options.tmpdir, + self.nodes.append(self.start_node(1, self.options.tmpdir, ["-blockmaxsize=17000", "-maxorphantx=1000"])) connect_nodes(self.nodes[1], 0) @@ -199,7 +199,7 @@ class EstimateFeeTest(BitcoinTestFramework): # produces too small blocks (room for only 55 or so transactions) node2args = ["-blockmaxsize=8000", "-maxorphantx=1000"] - self.nodes.append(start_node(2, self.options.tmpdir, node2args)) + self.nodes.append(self.start_node(2, self.options.tmpdir, node2args)) connect_nodes(self.nodes[0], 2) connect_nodes(self.nodes[2], 1) diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py index 4b5b311385..c7fd44b81c 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -5,6 +5,7 @@ """Base class for RPC testing.""" from collections import deque +from enum import Enum import logging import optparse import os @@ -27,20 +28,30 @@ from .util import ( get_mocktime, get_rpc_proxy, initialize_datadir, + get_datadir_path, log_filename, p2p_port, rpc_url, set_node_times, - start_node, - start_nodes, - stop_node, - stop_nodes, + _start_node, + _start_nodes, + _stop_node, + _stop_nodes, sync_blocks, sync_mempools, wait_for_bitcoind_start, ) from .authproxy import JSONRPCException +class TestStatus(Enum): + PASSED = 1 + FAILED = 2 + SKIPPED = 3 + +TEST_EXIT_PASSED = 0 +TEST_EXIT_FAILED = 1 +TEST_EXIT_SKIPPED = 77 + class BitcoinTestFramework(object): """Base class for a bitcoin test script. @@ -57,11 +68,6 @@ class BitcoinTestFramework(object): This class also contains various public and private helper methods.""" # Methods to override in subclass test scripts. - - TEST_EXIT_PASSED = 0 - TEST_EXIT_FAILED = 1 - TEST_EXIT_SKIPPED = 77 - def __init__(self): self.num_nodes = 4 self.setup_clean_chain = False @@ -91,7 +97,7 @@ class BitcoinTestFramework(object): extra_args = None if hasattr(self, "extra_args"): extra_args = self.extra_args - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args) + self.nodes = _start_nodes(self.num_nodes, self.options.tmpdir, extra_args) def run_test(self): raise NotImplementedError @@ -139,15 +145,18 @@ class BitcoinTestFramework(object): self.options.tmpdir = tempfile.mkdtemp(prefix="test") self._start_logging() - success = False + success = TestStatus.FAILED try: self.setup_chain() self.setup_network() self.run_test() - success = True + success = TestStatus.PASSED except JSONRPCException as e: self.log.exception("JSONRPC error") + except SkipTest as e: + self.log.warning("Test Skipped: %s" % e.message) + success = TestStatus.SKIPPED except AssertionError as e: self.log.exception("Assertion failed") except KeyError as e: @@ -159,11 +168,12 @@ class BitcoinTestFramework(object): if not self.options.noshutdown: self.log.info("Stopping nodes") - self.stop_nodes() + if self.nodes: + self.stop_nodes() else: self.log.info("Note: bitcoinds were not stopped and may still be running") - if not self.options.nocleanup and not self.options.noshutdown and success: + if not self.options.nocleanup and not self.options.noshutdown and success != TestStatus.FAILED: self.log.info("Cleaning up") shutil.rmtree(self.options.tmpdir) else: @@ -183,27 +193,31 @@ class BitcoinTestFramework(object): except OSError: print("Opening file %s failed." % fn) traceback.print_exc() - if success: + + if success == TestStatus.PASSED: self.log.info("Tests successful") - sys.exit(self.TEST_EXIT_PASSED) + sys.exit(TEST_EXIT_PASSED) + elif success == TestStatus.SKIPPED: + self.log.info("Test skipped") + sys.exit(TEST_EXIT_SKIPPED) else: self.log.error("Test failed. Test logging available at %s/test_framework.log", self.options.tmpdir) logging.shutdown() - sys.exit(self.TEST_EXIT_FAILED) + sys.exit(TEST_EXIT_FAILED) # Public helper methods. These can be accessed by the subclass test scripts. def start_node(self, i, dirname, extra_args=None, rpchost=None, timewait=None, binary=None, stderr=None): - return start_node(i, dirname, extra_args, rpchost, timewait, binary, stderr) + return _start_node(i, dirname, extra_args, rpchost, timewait, binary, stderr) def start_nodes(self, num_nodes, dirname, extra_args=None, rpchost=None, timewait=None, binary=None): - return start_nodes(num_nodes, dirname, extra_args, rpchost, timewait, binary) + return _start_nodes(num_nodes, dirname, extra_args, rpchost, timewait, binary) def stop_node(self, num_node): - stop_node(self.nodes[num_node], num_node) + _stop_node(self.nodes[num_node], num_node) def stop_nodes(self): - stop_nodes(self.nodes) + _stop_nodes(self.nodes) def split_network(self): """ @@ -287,13 +301,13 @@ class BitcoinTestFramework(object): args.append("-connect=127.0.0.1:" + str(p2p_port(0))) bitcoind_processes[i] = subprocess.Popen(args) self.log.debug("initialize_chain: bitcoind started, waiting for RPC to come up") - wait_for_bitcoind_start(bitcoind_processes[i], rpc_url(i), i) + wait_for_bitcoind_start(bitcoind_processes[i], datadir, i) self.log.debug("initialize_chain: RPC successfully started") self.nodes = [] for i in range(MAX_NODES): try: - self.nodes.append(get_rpc_proxy(rpc_url(i), i)) + self.nodes.append(get_rpc_proxy(rpc_url(get_datadir_path(cachedir, i), i), i)) except: self.log.exception("Error connecting to node %d" % i) sys.exit(1) @@ -346,6 +360,11 @@ class BitcoinTestFramework(object): # 2 binaries: 1 test binary, 1 ref binary # n>2 binaries: 1 test binary, n-1 ref binaries +class SkipTest(Exception): + """This exception is raised to skip a test""" + def __init__(self, message): + self.message = message + class ComparisonTestFramework(BitcoinTestFramework): def __init__(self): diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py index 2b56fe8d62..d2a609451d 100644 --- a/test/functional/test_framework/util.py +++ b/test/functional/test_framework/util.py @@ -181,21 +181,40 @@ def initialize_datadir(dirname, n): datadir = os.path.join(dirname, "node"+str(n)) if not os.path.isdir(datadir): os.makedirs(datadir) - rpc_u, rpc_p = rpc_auth_pair(n) with open(os.path.join(datadir, "bitcoin.conf"), 'w', encoding='utf8') as f: f.write("regtest=1\n") - f.write("rpcuser=" + rpc_u + "\n") - f.write("rpcpassword=" + rpc_p + "\n") f.write("port="+str(p2p_port(n))+"\n") f.write("rpcport="+str(rpc_port(n))+"\n") f.write("listenonion=0\n") return datadir -def rpc_auth_pair(n): - return 'rpcuser💻' + str(n), 'rpcpass🔑' + str(n) - -def rpc_url(i, rpchost=None): - rpc_u, rpc_p = rpc_auth_pair(i) +def get_datadir_path(dirname, n): + return os.path.join(dirname, "node"+str(n)) + +def get_auth_cookie(datadir, n): + user = None + password = None + if os.path.isfile(os.path.join(datadir, "bitcoin.conf")): + with open(os.path.join(datadir, "bitcoin.conf"), 'r') as f: + for line in f: + if line.startswith("rpcuser="): + assert user is None # Ensure that there is only one rpcuser line + user = line.split("=")[1].strip("\n") + if line.startswith("rpcpassword="): + assert password is None # Ensure that there is only one rpcpassword line + password = line.split("=")[1].strip("\n") + if os.path.isfile(os.path.join(datadir, "regtest", ".cookie")): + with open(os.path.join(datadir, "regtest", ".cookie"), 'r') as f: + userpass = f.read() + split_userpass = userpass.split(':') + user = split_userpass[0] + password = split_userpass[1] + if user is None or password is None: + raise ValueError("No RPC credentials") + return user, password + +def rpc_url(datadir, i, rpchost=None): + rpc_u, rpc_p = get_auth_cookie(datadir, i) host = '127.0.0.1' port = rpc_port(i) if rpchost: @@ -206,7 +225,7 @@ def rpc_url(i, rpchost=None): host = rpchost return "http://%s:%s@%s:%d" % (rpc_u, rpc_p, host, int(port)) -def wait_for_bitcoind_start(process, url, i): +def wait_for_bitcoind_start(process, datadir, i, rpchost=None): ''' Wait for bitcoind to start. This means that RPC is accessible and fully initialized. Raise an exception if bitcoind exits during initialization. @@ -215,7 +234,8 @@ def wait_for_bitcoind_start(process, url, i): if process.poll() is not None: raise Exception('bitcoind exited with status %i during initialization' % process.returncode) try: - rpc = get_rpc_proxy(url, i) + # Check if .cookie file to be created + rpc = get_rpc_proxy(rpc_url(datadir, i, rpchost), i) blocks = rpc.getblockcount() break # break out of loop on success except IOError as e: @@ -224,13 +244,17 @@ def wait_for_bitcoind_start(process, url, i): except JSONRPCException as e: # Initialization phase if e.error['code'] != -28: # RPC in warmup? raise # unknown JSON RPC exception + except ValueError as e: # cookie file not found and no rpcuser or rpcassword. bitcoind still starting + if "No RPC credentials" not in str(e): + raise time.sleep(0.25) -def start_node(i, dirname, extra_args=None, rpchost=None, timewait=None, binary=None, stderr=None): - """ - Start a bitcoind and return RPC connection to it - """ +def _start_node(i, dirname, extra_args=None, rpchost=None, timewait=None, binary=None, stderr=None): + """Start a bitcoind and return RPC connection to it + + This function should only be called from within test_framework, not by individual test scripts.""" + datadir = os.path.join(dirname, "node"+str(i)) if binary is None: binary = os.getenv("BITCOIND", "bitcoind") @@ -238,10 +262,9 @@ def start_node(i, dirname, extra_args=None, rpchost=None, timewait=None, binary= if extra_args is not None: args.extend(extra_args) bitcoind_processes[i] = subprocess.Popen(args, stderr=stderr) logger.debug("initialize_chain: bitcoind started, waiting for RPC to come up") - url = rpc_url(i, rpchost) - wait_for_bitcoind_start(bitcoind_processes[i], url, i) + wait_for_bitcoind_start(bitcoind_processes[i], datadir, i, rpchost) logger.debug("initialize_chain: RPC successfully started") - proxy = get_rpc_proxy(url, i, timeout=timewait) + proxy = get_rpc_proxy(rpc_url(datadir, i, rpchost), i, timeout=timewait) if COVERAGE_DIR: coverage.write_all_rpc_commands(COVERAGE_DIR, proxy) @@ -251,8 +274,8 @@ def start_node(i, dirname, extra_args=None, rpchost=None, timewait=None, binary= def assert_start_raises_init_error(i, dirname, extra_args=None, expected_msg=None): with tempfile.SpooledTemporaryFile(max_size=2**16) as log_stderr: try: - node = start_node(i, dirname, extra_args, stderr=log_stderr) - stop_node(node, i) + node = _start_node(i, dirname, extra_args, stderr=log_stderr) + _stop_node(node, i) except Exception as e: assert 'bitcoind exited' in str(e) #node must have shutdown if expected_msg is not None: @@ -267,10 +290,11 @@ def assert_start_raises_init_error(i, dirname, extra_args=None, expected_msg=Non assert_msg = "bitcoind should have exited with expected error " + expected_msg raise AssertionError(assert_msg) -def start_nodes(num_nodes, dirname, extra_args=None, rpchost=None, timewait=None, binary=None): - """ - Start multiple bitcoinds, return RPC connections to them - """ +def _start_nodes(num_nodes, dirname, extra_args=None, rpchost=None, timewait=None, binary=None): + """Start multiple bitcoinds, return RPC connections to them + + This function should only be called from within test_framework, not by individual test scripts.""" + if extra_args is None: extra_args = [ None for _ in range(num_nodes) ] if binary is None: binary = [ None for _ in range(num_nodes) ] assert_equal(len(extra_args), num_nodes) @@ -278,16 +302,20 @@ def start_nodes(num_nodes, dirname, extra_args=None, rpchost=None, timewait=None rpcs = [] try: for i in range(num_nodes): - rpcs.append(start_node(i, dirname, extra_args[i], rpchost, timewait=timewait, binary=binary[i])) + rpcs.append(_start_node(i, dirname, extra_args[i], rpchost, timewait=timewait, binary=binary[i])) except: # If one node failed to start, stop the others - stop_nodes(rpcs) + _stop_nodes(rpcs) raise return rpcs def log_filename(dirname, n_node, logname): return os.path.join(dirname, "node"+str(n_node), "regtest", logname) -def stop_node(node, i): +def _stop_node(node, i): + """Stop a bitcoind test node + + This function should only be called from within test_framework, not by individual test scripts.""" + logger.debug("Stopping node %d" % i) try: node.stop() @@ -297,9 +325,13 @@ def stop_node(node, i): assert_equal(return_code, 0) del bitcoind_processes[i] -def stop_nodes(nodes): +def _stop_nodes(nodes): + """Stop multiple bitcoind test nodes + + This function should only be called from within test_framework, not by individual test scripts.""" + for i, node in enumerate(nodes): - stop_node(node, i) + _stop_node(node, i) assert not bitcoind_processes.values() # All connections must be gone now def set_node_times(nodes, t): diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index b2aee7c739..0dca318af8 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -20,6 +20,7 @@ import datetime import os import time import shutil +import signal import sys import subprocess import tempfile @@ -78,7 +79,7 @@ BASE_SCRIPTS= [ 'rawtransactions.py', 'reindex.py', # vv Tests less than 30s vv - "zmq_test.py", + 'zmq_test.py', 'mempool_resurrect_test.py', 'txn_doublespend.py --mineblock', 'txn_clone.py', @@ -111,6 +112,7 @@ BASE_SCRIPTS= [ 'rpcnamedargs.py', 'listsinceblock.py', 'p2p-leaktests.py', + 'wallet-encryption.py', ] EXTENDED_SCRIPTS = [ @@ -180,7 +182,7 @@ def main(): # Read config generated by configure. config = configparser.ConfigParser() - configfile = os.path.abspath(os.path.dirname(__file__)) + "/config.ini" + configfile = os.path.abspath(os.path.dirname(__file__)) + "/../config.ini" config.read_file(open(configfile)) passon_args.append("--configfile=%s" % configfile) @@ -389,6 +391,10 @@ class TestHandler: time.sleep(.5) for j in self.jobs: (name, time0, proc, log_out, log_err) = j + if os.getenv('TRAVIS') == 'true' and int(time.time() - time0) > 20 * 60: + # In travis, timeout individual tests after 20 minutes (to stop tests hanging and not + # providing useful output. + proc.send_signal(signal.SIGINT) if proc.poll() is not None: log_out.seek(0), log_err.seek(0) [stdout, stderr] = [l.read().decode('utf-8') for l in (log_out, log_err)] diff --git a/test/functional/wallet-accounts.py b/test/functional/wallet-accounts.py index e6635bea1c..158aa9ae89 100755 --- a/test/functional/wallet-accounts.py +++ b/test/functional/wallet-accounts.py @@ -14,9 +14,7 @@ RPCs tested are: """ from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import ( - assert_equal, -) +from test_framework.util import assert_equal class WalletAccountsTest(BitcoinTestFramework): diff --git a/test/functional/wallet-dump.py b/test/functional/wallet-dump.py index 8876f935a4..9cb32d4650 100755 --- a/test/functional/wallet-dump.py +++ b/test/functional/wallet-dump.py @@ -4,8 +4,10 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the dumpwallet RPC.""" +import os + from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import (start_nodes, start_node, assert_equal, bitcoind_processes) +from test_framework.util import (assert_equal, bitcoind_processes) def read_dump(file_name, addrs, hd_master_addr_old): @@ -66,7 +68,7 @@ class WalletDumpTest(BitcoinTestFramework): # longer than the default 30 seconds due to an expensive # CWallet::TopUpKeyPool call, and the encryptwallet RPC made later in # the test often takes even longer. - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, self.extra_args, timewait=60) + self.nodes = self.start_nodes(self.num_nodes, self.options.tmpdir, self.extra_args, timewait=60) def run_test (self): tmpdir = self.options.tmpdir @@ -82,7 +84,8 @@ class WalletDumpTest(BitcoinTestFramework): self.nodes[0].keypoolrefill() # dump unencrypted wallet - self.nodes[0].dumpwallet(tmpdir + "/node0/wallet.unencrypted.dump") + result = self.nodes[0].dumpwallet(tmpdir + "/node0/wallet.unencrypted.dump") + assert_equal(result['filename'], os.path.abspath(tmpdir + "/node0/wallet.unencrypted.dump")) found_addr, found_addr_chg, found_addr_rsv, hd_master_addr_unenc = \ read_dump(tmpdir + "/node0/wallet.unencrypted.dump", addrs, None) @@ -93,7 +96,7 @@ class WalletDumpTest(BitcoinTestFramework): #encrypt wallet, restart, unlock and dump self.nodes[0].encryptwallet('test') bitcoind_processes[0].wait() - self.nodes[0] = start_node(0, self.options.tmpdir, self.extra_args[0]) + self.nodes[0] = self.start_node(0, self.options.tmpdir, self.extra_args[0]) self.nodes[0].walletpassphrase('test', 10) # Should be a no-op: self.nodes[0].keypoolrefill() diff --git a/test/functional/wallet-encryption.py b/test/functional/wallet-encryption.py new file mode 100755 index 0000000000..33872e3c94 --- /dev/null +++ b/test/functional/wallet-encryption.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python3 +# Copyright (c) 2016 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 Wallet encryption""" + +import time + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import ( + assert_equal, + assert_raises_jsonrpc, + bitcoind_processes, + BITCOIND_PROC_WAIT_TIMEOUT, +) + +class WalletEncryptionTest(BitcoinTestFramework): + + def __init__(self): + super().__init__() + self.setup_clean_chain = True + self.num_nodes = 1 + + def run_test(self): + passphrase = "WalletPassphrase" + passphrase2 = "SecondWalletPassphrase" + + # Make sure the wallet isn't encrypted first + address = self.nodes[0].getnewaddress() + privkey = self.nodes[0].dumpprivkey(address) + assert_equal(privkey[:1], "c") + assert_equal(len(privkey), 52) + + # Encrypt the wallet + self.nodes[0].encryptwallet(passphrase) + bitcoind_processes[0].wait(timeout=BITCOIND_PROC_WAIT_TIMEOUT) + self.nodes[0] = self.start_node(0, self.options.tmpdir) + + # Test that the wallet is encrypted + assert_raises_jsonrpc(-13, "Please enter the wallet passphrase with walletpassphrase first", self.nodes[0].dumpprivkey, address) + + # Check that walletpassphrase works + self.nodes[0].walletpassphrase(passphrase, 2) + assert_equal(privkey, self.nodes[0].dumpprivkey(address)) + + # Check that the timeout is right + time.sleep(2) + assert_raises_jsonrpc(-13, "Please enter the wallet passphrase with walletpassphrase first", self.nodes[0].dumpprivkey, address) + + # Test wrong passphrase + assert_raises_jsonrpc(-14, "wallet passphrase entered was incorrect", self.nodes[0].walletpassphrase, passphrase + "wrong", 10) + + # Test walletlock + self.nodes[0].walletpassphrase(passphrase, 84600) + assert_equal(privkey, self.nodes[0].dumpprivkey(address)) + self.nodes[0].walletlock() + assert_raises_jsonrpc(-13, "Please enter the wallet passphrase with walletpassphrase first", self.nodes[0].dumpprivkey, address) + + # Test passphrase changes + self.nodes[0].walletpassphrasechange(passphrase, passphrase2) + assert_raises_jsonrpc(-14, "wallet passphrase entered was incorrect", self.nodes[0].walletpassphrase, passphrase, 10) + self.nodes[0].walletpassphrase(passphrase2, 10) + assert_equal(privkey, self.nodes[0].dumpprivkey(address)) + +if __name__ == '__main__': + WalletEncryptionTest().main() diff --git a/test/functional/wallet-hd.py b/test/functional/wallet-hd.py index aab3b4bc2d..e7ec72a248 100755 --- a/test/functional/wallet-hd.py +++ b/test/functional/wallet-hd.py @@ -6,7 +6,6 @@ from test_framework.test_framework import BitcoinTestFramework from test_framework.util import ( - start_node, assert_equal, connect_nodes_bi, assert_start_raises_init_error @@ -29,7 +28,7 @@ class WalletHDTest(BitcoinTestFramework): # Make sure can't switch off usehd after wallet creation self.stop_node(1) assert_start_raises_init_error(1, self.options.tmpdir, ['-usehd=0'], 'already existing HD wallet') - self.nodes[1] = start_node(1, self.options.tmpdir, self.extra_args[1]) + self.nodes[1] = self.start_node(1, self.options.tmpdir, self.extra_args[1]) connect_nodes_bi(self.nodes, 0, 1) # Make sure we use hd, keep masterkeyid @@ -76,7 +75,7 @@ class WalletHDTest(BitcoinTestFramework): self.stop_node(1) os.remove(self.options.tmpdir + "/node1/regtest/wallet.dat") shutil.copyfile(tmpdir + "/hd.bak", tmpdir + "/node1/regtest/wallet.dat") - self.nodes[1] = start_node(1, self.options.tmpdir, self.extra_args[1]) + self.nodes[1] = self.start_node(1, self.options.tmpdir, self.extra_args[1]) #connect_nodes_bi(self.nodes, 0, 1) # Assert that derivation is deterministic @@ -90,7 +89,7 @@ class WalletHDTest(BitcoinTestFramework): # Needs rescan self.stop_node(1) - self.nodes[1] = start_node(1, self.options.tmpdir, self.extra_args[1] + ['-rescan']) + self.nodes[1] = self.start_node(1, self.options.tmpdir, self.extra_args[1] + ['-rescan']) #connect_nodes_bi(self.nodes, 0, 1) assert_equal(self.nodes[1].getbalance(), num_hd_adds + 1) diff --git a/test/functional/wallet.py b/test/functional/wallet.py index efde2e005e..3e3e8fcddb 100755 --- a/test/functional/wallet.py +++ b/test/functional/wallet.py @@ -21,7 +21,7 @@ class WalletTest(BitcoinTestFramework): self.extra_args = [['-usehd={:d}'.format(i%2==0)] for i in range(4)] def setup_network(self): - self.nodes = start_nodes(3, self.options.tmpdir, self.extra_args[:3]) + self.nodes = self.start_nodes(3, self.options.tmpdir, self.extra_args[:3]) connect_nodes_bi(self.nodes,0,1) connect_nodes_bi(self.nodes,1,2) connect_nodes_bi(self.nodes,0,2) @@ -178,7 +178,7 @@ class WalletTest(BitcoinTestFramework): txid2 = self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), 1) sync_mempools(self.nodes) - self.nodes.append(start_node(3, self.options.tmpdir, self.extra_args[3])) + self.nodes.append(self.start_node(3, self.options.tmpdir, self.extra_args[3])) connect_nodes_bi(self.nodes, 0, 3) sync_blocks(self.nodes) @@ -221,8 +221,8 @@ class WalletTest(BitcoinTestFramework): assert(found) #do some -walletbroadcast tests - stop_nodes(self.nodes) - self.nodes = start_nodes(3, self.options.tmpdir, [["-walletbroadcast=0"],["-walletbroadcast=0"],["-walletbroadcast=0"]]) + self.stop_nodes() + self.nodes = self.start_nodes(3, self.options.tmpdir, [["-walletbroadcast=0"],["-walletbroadcast=0"],["-walletbroadcast=0"]]) connect_nodes_bi(self.nodes,0,1) connect_nodes_bi(self.nodes,1,2) connect_nodes_bi(self.nodes,0,2) @@ -246,8 +246,8 @@ class WalletTest(BitcoinTestFramework): txIdNotBroadcasted = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 2) #restart the nodes with -walletbroadcast=1 - stop_nodes(self.nodes) - self.nodes = start_nodes(3, self.options.tmpdir) + self.stop_nodes() + self.nodes = self.start_nodes(3, self.options.tmpdir) connect_nodes_bi(self.nodes,0,1) connect_nodes_bi(self.nodes,1,2) connect_nodes_bi(self.nodes,0,2) @@ -348,9 +348,9 @@ class WalletTest(BitcoinTestFramework): chainlimit = 6 for m in maintenance: self.log.info("check " + m) - stop_nodes(self.nodes) + self.stop_nodes() # set lower ancestor limit for later - self.nodes = start_nodes(3, self.options.tmpdir, [[m, "-limitancestorcount="+str(chainlimit)]] * 3) + self.nodes = self.start_nodes(3, self.options.tmpdir, [[m, "-limitancestorcount="+str(chainlimit)]] * 3) while m == '-reindex' and [block_count] * 3 != [self.nodes[i].getblockcount() for i in range(3)]: # reindex will leave rpc warm up "early"; Wait for it to finish time.sleep(0.1) @@ -397,8 +397,8 @@ class WalletTest(BitcoinTestFramework): # Try with walletrejectlongchains # Double chain limit but require combining inputs, so we pass SelectCoinsMinConf - stop_node(self.nodes[0],0) - self.nodes[0] = start_node(0, self.options.tmpdir, ["-walletrejectlongchains", "-limitancestorcount="+str(2*chainlimit)]) + self.stop_node(0) + self.nodes[0] = self.start_node(0, self.options.tmpdir, ["-walletrejectlongchains", "-limitancestorcount="+str(2*chainlimit)]) # wait for loadmempool timeout = 10 diff --git a/test/functional/walletbackup.py b/test/functional/walletbackup.py index 0492132af6..a4507182a2 100755 --- a/test/functional/walletbackup.py +++ b/test/functional/walletbackup.py @@ -77,18 +77,18 @@ class WalletBackupTest(BitcoinTestFramework): # As above, this mirrors the original bash test. def start_three(self): - self.nodes[0] = start_node(0, self.options.tmpdir) - self.nodes[1] = start_node(1, self.options.tmpdir) - self.nodes[2] = start_node(2, self.options.tmpdir) + self.nodes[0] = self.start_node(0, self.options.tmpdir) + self.nodes[1] = self.start_node(1, self.options.tmpdir) + self.nodes[2] = self.start_node(2, self.options.tmpdir) connect_nodes(self.nodes[0], 3) connect_nodes(self.nodes[1], 3) connect_nodes(self.nodes[2], 3) connect_nodes(self.nodes[2], 0) def stop_three(self): - stop_node(self.nodes[0], 0) - stop_node(self.nodes[1], 1) - stop_node(self.nodes[2], 2) + self.stop_node(0) + self.stop_node(1) + self.stop_node(2) def erase_three(self): os.remove(self.options.tmpdir + "/node0/regtest/wallet.dat") diff --git a/test/functional/zapwallettxes.py b/test/functional/zapwallettxes.py index 7987edeb54..a8600e82f6 100755 --- a/test/functional/zapwallettxes.py +++ b/test/functional/zapwallettxes.py @@ -58,18 +58,16 @@ class ZapWalletTXesTest (BitcoinTestFramework): assert_equal(tx3['txid'], txid3) #tx3 must be available (unconfirmed) #restart bitcoind - self.nodes[0].stop() - bitcoind_processes[0].wait() - self.nodes[0] = start_node(0,self.options.tmpdir) + self.stop_node(0) + self.nodes[0] = self.start_node(0,self.options.tmpdir) tx3 = self.nodes[0].gettransaction(txid3) assert_equal(tx3['txid'], txid3) #tx must be available (unconfirmed) - self.nodes[0].stop() - bitcoind_processes[0].wait() + self.stop_node(0) #restart bitcoind with zapwallettxes - self.nodes[0] = start_node(0,self.options.tmpdir, ["-zapwallettxes=1"]) + self.nodes[0] = self.start_node(0,self.options.tmpdir, ["-zapwallettxes=1"]) assert_raises(JSONRPCException, self.nodes[0].gettransaction, [txid3]) #there must be a expection because the unconfirmed wallettx0 must be gone by now diff --git a/test/functional/zmq_test.py b/test/functional/zmq_test.py index 918e13bcd4..26c946d215 100755 --- a/test/functional/zmq_test.py +++ b/test/functional/zmq_test.py @@ -6,92 +6,96 @@ import configparser import os import struct -import sys -from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import * +from test_framework.test_framework import BitcoinTestFramework, SkipTest +from test_framework.util import (assert_equal, + bytes_to_hex_str, + ) class ZMQTest (BitcoinTestFramework): def __init__(self): super().__init__() - self.num_nodes = 4 - - port = 28332 + self.num_nodes = 2 def setup_nodes(self): # Try to import python3-zmq. Skip this test if the import fails. try: import zmq except ImportError: - self.log.warning("python3-zmq module not available. Skipping zmq tests!") - sys.exit(self.TEST_EXIT_SKIPPED) + raise SkipTest("python3-zmq module not available.") # Check that bitcoin has been built with ZMQ enabled config = configparser.ConfigParser() if not self.options.configfile: - self.options.configfile = os.path.dirname(__file__) + "/config.ini" + self.options.configfile = os.path.dirname(__file__) + "/../config.ini" config.read_file(open(self.options.configfile)) if not config["components"].getboolean("ENABLE_ZMQ"): - self.log.warning("bitcoind has not been built with zmq enabled. Skipping zmq tests!") - sys.exit(self.TEST_EXIT_SKIPPED) + raise SkipTest("bitcoind has not been built with zmq enabled.") self.zmqContext = zmq.Context() self.zmqSubSocket = self.zmqContext.socket(zmq.SUB) + self.zmqSubSocket.set(zmq.RCVTIMEO, 60000) self.zmqSubSocket.setsockopt(zmq.SUBSCRIBE, b"hashblock") self.zmqSubSocket.setsockopt(zmq.SUBSCRIBE, b"hashtx") - self.zmqSubSocket.connect("tcp://127.0.0.1:%i" % self.port) - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args=[ - ['-zmqpubhashtx=tcp://127.0.0.1:'+str(self.port), '-zmqpubhashblock=tcp://127.0.0.1:'+str(self.port)], - [], - [], - [] - ]) + ip_address = "tcp://127.0.0.1:28332" + self.zmqSubSocket.connect(ip_address) + extra_args = [['-zmqpubhashtx=%s' % ip_address, '-zmqpubhashblock=%s' % ip_address], []] + self.nodes = self.start_nodes(self.num_nodes, self.options.tmpdir, extra_args) def run_test(self): - self.sync_all() + try: + self._zmq_test() + finally: + # Destroy the zmq context + self.log.debug("Destroying zmq context") + self.zmqContext.destroy(linger=None) + def _zmq_test(self): genhashes = self.nodes[0].generate(1) self.sync_all() - self.log.info("listen...") + self.log.info("Wait for tx") msg = self.zmqSubSocket.recv_multipart() topic = msg[0] assert_equal(topic, b"hashtx") body = msg[1] msgSequence = struct.unpack('<I', msg[-1])[-1] - assert_equal(msgSequence, 0) #must be sequence 0 on hashtx + assert_equal(msgSequence, 0) # must be sequence 0 on hashtx + self.log.info("Wait for block") msg = self.zmqSubSocket.recv_multipart() topic = msg[0] body = msg[1] msgSequence = struct.unpack('<I', msg[-1])[-1] - assert_equal(msgSequence, 0) #must be sequence 0 on hashblock + assert_equal(msgSequence, 0) # must be sequence 0 on hashblock blkhash = bytes_to_hex_str(body) - assert_equal(genhashes[0], blkhash) #blockhash from generate must be equal to the hash received over zmq + assert_equal(genhashes[0], blkhash) # blockhash from generate must be equal to the hash received over zmq + self.log.info("Generate 10 blocks (and 10 coinbase txes)") n = 10 genhashes = self.nodes[1].generate(n) self.sync_all() zmqHashes = [] blockcount = 0 - for x in range(0,n*2): + for x in range(n * 2): msg = self.zmqSubSocket.recv_multipart() topic = msg[0] body = msg[1] if topic == b"hashblock": zmqHashes.append(bytes_to_hex_str(body)) msgSequence = struct.unpack('<I', msg[-1])[-1] - assert_equal(msgSequence, blockcount+1) + assert_equal(msgSequence, blockcount + 1) blockcount += 1 - for x in range(0,n): - assert_equal(genhashes[x], zmqHashes[x]) #blockhash from generate must be equal to the hash received over zmq + for x in range(n): + assert_equal(genhashes[x], zmqHashes[x]) # blockhash from generate must be equal to the hash received over zmq - #test tx from a second node + self.log.info("Wait for tx from second node") + # test tx from a second node hashRPC = self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), 1.0) self.sync_all() @@ -99,14 +103,12 @@ class ZMQTest (BitcoinTestFramework): msg = self.zmqSubSocket.recv_multipart() topic = msg[0] body = msg[1] - hashZMQ = "" - if topic == b"hashtx": - hashZMQ = bytes_to_hex_str(body) - msgSequence = struct.unpack('<I', msg[-1])[-1] - assert_equal(msgSequence, blockcount+1) - - assert_equal(hashRPC, hashZMQ) #blockhash from generate must be equal to the hash received over zmq + assert_equal(topic, b"hashtx") + hashZMQ = bytes_to_hex_str(body) + msgSequence = struct.unpack('<I', msg[-1])[-1] + assert_equal(msgSequence, blockcount + 1) + assert_equal(hashRPC, hashZMQ) # txid from sendtoaddress must be equal to the hash received over zmq if __name__ == '__main__': - ZMQTest ().main () + ZMQTest().main() |