diff options
Diffstat (limited to 'test/functional')
22 files changed, 473 insertions, 149 deletions
diff --git a/test/functional/feature_block.py b/test/functional/feature_block.py index 181c7f3369..38b76239e5 100755 --- a/test/functional/feature_block.py +++ b/test/functional/feature_block.py @@ -1306,7 +1306,13 @@ class FullBlockTest(BitcoinTestFramework): self.nodes[0].disconnect_p2ps() self.nodes[0].add_p2p_connection(P2PDataStore()) network_thread_start() - self.nodes[0].p2p.wait_for_verack() + # We need to wait for the initial getheaders from the peer before we + # start populating our blockstore. If we don't, then we may run ahead + # to the next subtest before we receive the getheaders. We'd then send + # an INV for the next block and receive two getheaders - one for the + # IBD and one for the INV. We'd respond to both and could get + # unexpectedly disconnected if the DoS score for that error is 50. + self.nodes[0].p2p.wait_for_getheaders(timeout=5) def sync_blocks(self, blocks, success=True, reject_code=None, reject_reason=None, request_block=True, reconnect=False, timeout=60): """Sends blocks to test node. Syncs and verifies that tip has advanced to most recent block. diff --git a/test/functional/feature_segwit.py b/test/functional/feature_segwit.py index fa1732c4c5..e835b9d777 100755 --- a/test/functional/feature_segwit.py +++ b/test/functional/feature_segwit.py @@ -150,19 +150,11 @@ class SegWitTest(BitcoinTestFramework): self.skip_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V0][0], True) #block 426 self.skip_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V1][0], True) #block 427 - # TODO: An old node would see these txs without witnesses and be able to mine them - - self.log.info("Verify unsigned bare witness txs in versionbits-setting blocks are valid before the fork") - self.success_mine(self.nodes[2], wit_ids[NODE_2][WIT_V0][1], False) #block 428 - self.success_mine(self.nodes[2], wit_ids[NODE_2][WIT_V1][1], False) #block 429 - self.log.info("Verify unsigned p2sh witness txs without a redeem script are invalid") self.fail_accept(self.nodes[2], "mandatory-script-verify-flag", p2sh_ids[NODE_2][WIT_V0][1], False) self.fail_accept(self.nodes[2], "mandatory-script-verify-flag", p2sh_ids[NODE_2][WIT_V1][1], False) - self.log.info("Verify unsigned p2sh witness txs with a redeem script in versionbits-settings blocks are valid before the fork") - self.success_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V0][1], False, witness_script(False, self.pubkey[2])) #block 430 - self.success_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V1][1], False, witness_script(True, self.pubkey[2])) #block 431 + self.nodes[2].generate(4) # blocks 428-431 self.log.info("Verify previous witness txs skipped for mining can now be mined") assert_equal(len(self.nodes[2].getrawmempool()), 4) diff --git a/test/functional/mining_prioritisetransaction.py b/test/functional/mining_prioritisetransaction.py index e754dd31ad..b433f11aa5 100755 --- a/test/functional/mining_prioritisetransaction.py +++ b/test/functional/mining_prioritisetransaction.py @@ -120,7 +120,7 @@ class PrioritiseTransactionTest(BitcoinTestFramework): tx_id = self.nodes[0].decoderawtransaction(tx_hex)["txid"] # This will raise an exception due to min relay fee not being met - assert_raises_rpc_error(-26, "min relay fee not met (code 66)", self.nodes[0].sendrawtransaction, tx_hex) + assert_raises_rpc_error(-26, "min relay fee not met, 0 < 134 (code 66)", self.nodes[0].sendrawtransaction, tx_hex) assert(tx_id not in self.nodes[0].getrawmempool()) # This is a less than 1000-byte transaction, so just set the fee diff --git a/test/functional/p2p_segwit.py b/test/functional/p2p_segwit.py index f8afe22eaf..4fecd4ffee 100755 --- a/test/functional/p2p_segwit.py +++ b/test/functional/p2p_segwit.py @@ -48,7 +48,7 @@ def test_transaction_acceptance(rpc, p2p, tx, with_witness, accepted, reason=Non with mininode_lock: assert_equal(p2p.last_message["reject"].reason, reason) -def test_witness_block(rpc, p2p, block, accepted, with_witness=True): +def test_witness_block(rpc, p2p, block, accepted, with_witness=True, reason=None): """Send a block to the node and check that it's accepted - Submit the block over the p2p interface @@ -59,6 +59,10 @@ def test_witness_block(rpc, p2p, block, accepted, with_witness=True): p2p.send_message(msg_block(block)) p2p.sync_with_ping() assert_equal(rpc.getbestblockhash() == block.hash, accepted) + if (reason != None and not accepted): + # Check the rejection reason as well. + with mininode_lock: + assert_equal(p2p.last_message["reject"].reason, reason) class TestP2PConn(P2PInterface): def __init__(self): @@ -272,6 +276,80 @@ class SegWitTest(BitcoinTestFramework): self.utxo.pop(0) self.utxo.append(UTXO(tx4.sha256, 0, tx4.vout[0].nValue)) + # ~6 months after segwit activation, the SCRIPT_VERIFY_WITNESS flag was + # backdated so that it applies to all blocks, going back to the genesis + # block. + # + # Consequently, version 0 witness outputs are never spendable without + # witness, and so can't be spent before segwit activation (the point at which + # blocks are permitted to contain witnesses). + def test_v0_outputs_arent_spendable(self): + self.log.info("Testing that v0 witness program outputs aren't spendable before activation") + + assert len(self.utxo), "self.utxo is empty" + + # Create two outputs, a p2wsh and p2sh-p2wsh + witness_program = CScript([OP_TRUE]) + witness_hash = sha256(witness_program) + scriptPubKey = CScript([OP_0, witness_hash]) + + p2sh_pubkey = hash160(scriptPubKey) + p2sh_scriptPubKey = CScript([OP_HASH160, p2sh_pubkey, OP_EQUAL]) + + value = self.utxo[0].nValue // 3 + + tx = CTransaction() + tx.vin = [CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b'')] + tx.vout = [CTxOut(value, scriptPubKey), CTxOut(value, p2sh_scriptPubKey)] + tx.vout.append(CTxOut(value, CScript([OP_TRUE]))) + tx.rehash() + txid = tx.sha256 + + # Add it to a block + block = self.build_next_block() + self.update_witness_block_with_transactions(block, [tx]) + # Verify that segwit isn't activated. A block serialized with witness + # should be rejected prior to activation. + test_witness_block(self.nodes[0], self.test_node, block, accepted=False, with_witness=True, reason = b'unexpected-witness') + # Now send the block without witness. It should be accepted + test_witness_block(self.nodes[0], self.test_node, block, accepted=True, with_witness=False) + + # Now try to spend the outputs. This should fail since SCRIPT_VERIFY_WITNESS is always enabled. + p2wsh_tx = CTransaction() + p2wsh_tx.vin = [CTxIn(COutPoint(txid, 0), b'')] + p2wsh_tx.vout = [CTxOut(value, CScript([OP_TRUE]))] + p2wsh_tx.wit.vtxinwit.append(CTxInWitness()) + p2wsh_tx.wit.vtxinwit[0].scriptWitness.stack = [CScript([OP_TRUE])] + p2wsh_tx.rehash() + + p2sh_p2wsh_tx = CTransaction() + p2sh_p2wsh_tx.vin = [CTxIn(COutPoint(txid, 1), CScript([scriptPubKey]))] + p2sh_p2wsh_tx.vout = [CTxOut(value, CScript([OP_TRUE]))] + p2sh_p2wsh_tx.wit.vtxinwit.append(CTxInWitness()) + p2sh_p2wsh_tx.wit.vtxinwit[0].scriptWitness.stack = [CScript([OP_TRUE])] + p2sh_p2wsh_tx.rehash() + + for tx in [p2wsh_tx, p2sh_p2wsh_tx]: + + block = self.build_next_block() + self.update_witness_block_with_transactions(block, [tx]) + + # When the block is serialized with a witness, the block will be rejected because witness + # data isn't allowed in blocks that don't commit to witness data. + test_witness_block(self.nodes[0], self.test_node, block, accepted=False, with_witness=True, reason=b'unexpected-witness') + + # When the block is serialized without witness, validation fails because the transaction is + # invalid (transactions are always validated with SCRIPT_VERIFY_WITNESS so a segwit v0 transaction + # without a witness is invalid). + # Note: The reject reason for this failure could be + # 'block-validation-failed' (if script check threads > 1) or + # 'non-mandatory-script-verify-flag (Witness program was passed an + # empty witness)' (otherwise). + # TODO: support multiple acceptable reject reasons. + test_witness_block(self.nodes[0], self.test_node, block, accepted=False, with_witness=False) + + self.utxo.pop(0) + self.utxo.append(UTXO(txid, 2, value)) # Mine enough blocks for segwit's vb state to be 'started'. def advance_to_segwit_started(self): @@ -1479,9 +1557,10 @@ class SegWitTest(BitcoinTestFramework): block = self.build_next_block() self.update_witness_block_with_transactions(block, [spend_tx]) - # If we're before activation, then sending this without witnesses - # should be valid. If we're after activation, then sending this with - # witnesses should be valid. + # If we're after activation, then sending this with witnesses should be valid. + # This no longer works before activation, because SCRIPT_VERIFY_WITNESS + # is always set. + # TODO: rewrite this test to make clear that it only works after activation. if segwit_activated: test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=True) else: @@ -1900,6 +1979,7 @@ class SegWitTest(BitcoinTestFramework): self.test_witness_services() # Verifies NODE_WITNESS self.test_non_witness_transaction() # non-witness tx's are accepted self.test_unnecessary_witness_before_segwit_activation() + self.test_v0_outputs_arent_spendable() self.test_block_relay(segwit_activated=False) # Advance to segwit being 'started' @@ -1917,7 +1997,6 @@ class SegWitTest(BitcoinTestFramework): self.test_unnecessary_witness_before_segwit_activation() self.test_witness_tx_relay_before_segwit_activation() self.test_block_relay(segwit_activated=False) - self.test_p2sh_witness(segwit_activated=False) self.test_standardness_v0(segwit_activated=False) sync_blocks(self.nodes) diff --git a/test/functional/rpc_bind.py b/test/functional/rpc_bind.py index 5b50520d3f..343e162058 100755 --- a/test/functional/rpc_bind.py +++ b/test/functional/rpc_bind.py @@ -4,7 +4,6 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test running bitcoind with the -rpcbind and -rpcallowip options.""" -import socket import sys from test_framework.test_framework import BitcoinTestFramework, SkipTest @@ -20,6 +19,11 @@ class RPCBindTest(BitcoinTestFramework): def setup_network(self): self.add_nodes(self.num_nodes, None) + def add_options(self, parser): + parser.add_option("--ipv4", action='store_true', dest="run_ipv4", help="Run ipv4 tests only", default=False) + parser.add_option("--ipv6", action='store_true', dest="run_ipv6", help="Run ipv6 tests only", default=False) + parser.add_option("--nonloopback", action='store_true', dest="run_nonloopback", help="Run non-loopback tests only", default=False) + def run_bind_test(self, allow_ips, connect_to, addresses, expected): ''' Start a node with requested rpcallowip and rpcbind parameters, @@ -54,55 +58,69 @@ class RPCBindTest(BitcoinTestFramework): def run_test(self): # due to OS-specific network stats queries, this test works only on Linux + if sum([self.options.run_ipv4, self.options.run_ipv6, self.options.run_nonloopback]) > 1: + raise AssertionError("Only one of --ipv4, --ipv6 and --nonloopback can be set") + + self.log.info("Check for linux") if not sys.platform.startswith('linux'): - raise SkipTest("This test can only be run on Linux.") - # find the first non-loopback interface for testing - non_loopback_ip = None + raise SkipTest("This test can only be run on linux.") + + self.log.info("Check for ipv6") + have_ipv6 = test_ipv6_local() + if not have_ipv6 and not self.options.run_ipv4: + raise SkipTest("This test requires ipv6 support.") + + self.log.info("Check for non-loopback interface") + self.non_loopback_ip = None for name,ip in all_interfaces(): if ip != '127.0.0.1': - non_loopback_ip = ip + self.non_loopback_ip = ip break - if non_loopback_ip is None: - 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: - raise SkipTest("This test requires IPv6 support.") - - self.log.info("Using interface %s for testing" % non_loopback_ip) - - defaultport = rpc_port(0) - - # check default without rpcallowip (IPv4 and IPv6 localhost) - self.run_bind_test(None, '127.0.0.1', [], - [('127.0.0.1', defaultport), ('::1', defaultport)]) - # check default with rpcallowip (IPv6 any) - self.run_bind_test(['127.0.0.1'], '127.0.0.1', [], - [('::0', defaultport)]) - # check only IPv4 localhost (explicit) - self.run_bind_test(['127.0.0.1'], '127.0.0.1', ['127.0.0.1'], - [('127.0.0.1', defaultport)]) - # check only IPv4 localhost (explicit) with alternative port - self.run_bind_test(['127.0.0.1'], '127.0.0.1:32171', ['127.0.0.1:32171'], - [('127.0.0.1', 32171)]) - # check only IPv4 localhost (explicit) with multiple alternative ports on same host - self.run_bind_test(['127.0.0.1'], '127.0.0.1:32171', ['127.0.0.1:32171', '127.0.0.1:32172'], - [('127.0.0.1', 32171), ('127.0.0.1', 32172)]) - # check only IPv6 localhost (explicit) - self.run_bind_test(['[::1]'], '[::1]', ['[::1]'], - [('::1', defaultport)]) - # check both IPv4 and IPv6 localhost (explicit) - self.run_bind_test(['127.0.0.1'], '127.0.0.1', ['127.0.0.1', '[::1]'], - [('127.0.0.1', defaultport), ('::1', defaultport)]) + if self.non_loopback_ip is None and self.options.run_nonloopback: + raise SkipTest("This test requires a non-loopback ip address.") + + self.defaultport = rpc_port(0) + + if not self.options.run_nonloopback: + self._run_loopback_tests() + if not self.options.run_ipv4 and not self.options.run_ipv6: + self._run_nonloopback_tests() + + def _run_loopback_tests(self): + if self.options.run_ipv4: + # check only IPv4 localhost (explicit) + self.run_bind_test(['127.0.0.1'], '127.0.0.1', ['127.0.0.1'], + [('127.0.0.1', self.defaultport)]) + # check only IPv4 localhost (explicit) with alternative port + self.run_bind_test(['127.0.0.1'], '127.0.0.1:32171', ['127.0.0.1:32171'], + [('127.0.0.1', 32171)]) + # check only IPv4 localhost (explicit) with multiple alternative ports on same host + self.run_bind_test(['127.0.0.1'], '127.0.0.1:32171', ['127.0.0.1:32171', '127.0.0.1:32172'], + [('127.0.0.1', 32171), ('127.0.0.1', 32172)]) + else: + # check default without rpcallowip (IPv4 and IPv6 localhost) + self.run_bind_test(None, '127.0.0.1', [], + [('127.0.0.1', self.defaultport), ('::1', self.defaultport)]) + # check default with rpcallowip (IPv6 any) + self.run_bind_test(['127.0.0.1'], '127.0.0.1', [], + [('::0', self.defaultport)]) + # check only IPv6 localhost (explicit) + self.run_bind_test(['[::1]'], '[::1]', ['[::1]'], + [('::1', self.defaultport)]) + # check both IPv4 and IPv6 localhost (explicit) + self.run_bind_test(['127.0.0.1'], '127.0.0.1', ['127.0.0.1', '[::1]'], + [('127.0.0.1', self.defaultport), ('::1', self.defaultport)]) + + def _run_nonloopback_tests(self): + self.log.info("Using interface %s for testing" % self.non_loopback_ip) + # check only non-loopback interface - self.run_bind_test([non_loopback_ip], non_loopback_ip, [non_loopback_ip], - [(non_loopback_ip, defaultport)]) + self.run_bind_test([self.non_loopback_ip], self.non_loopback_ip, [self.non_loopback_ip], + [(self.non_loopback_ip, self.defaultport)]) # Check that with invalid rpcallowip, we are denied - self.run_allowip_test([non_loopback_ip], non_loopback_ip, defaultport) - assert_raises_rpc_error(-342, "non-JSON HTTP response with '403 Forbidden' from server", self.run_allowip_test, ['1.1.1.1'], non_loopback_ip, defaultport) + self.run_allowip_test([self.non_loopback_ip], self.non_loopback_ip, self.defaultport) + assert_raises_rpc_error(-342, "non-JSON HTTP response with '403 Forbidden' from server", self.run_allowip_test, ['1.1.1.1'], self.non_loopback_ip, self.defaultport) if __name__ == '__main__': RPCBindTest().main() diff --git a/test/functional/rpc_deprecated.py b/test/functional/rpc_deprecated.py index b94b9d8fae..7b7c596506 100755 --- a/test/functional/rpc_deprecated.py +++ b/test/functional/rpc_deprecated.py @@ -4,12 +4,13 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test deprecation of RPC calls.""" from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import assert_raises_rpc_error class DeprecatedRpcTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 2 self.setup_clean_chain = True - self.extra_args = [[], ["-deprecatedrpc=validateaddress"]] + self.extra_args = [[], ["-deprecatedrpc=validateaddress", "-deprecatedrpc=accounts"]] def run_test(self): # This test should be used to verify correct behaviour of deprecated @@ -20,11 +21,92 @@ class DeprecatedRpcTest(BitcoinTestFramework): # self.nodes[1].createmultisig(1, [self.nodes[1].getnewaddress()]) self.log.info("Test validateaddress deprecation") - SOME_ADDRESS = "mnvGjUy3NMj67yJ6gkK5o9e5RS33Z2Vqcu" # This is just some random address to pass as a parameter to validateaddress + SOME_ADDRESS = "mnvGjUy3NMj67yJ6gkK5o9e5RS33Z2Vqcu" # This is just some random address to pass as a parameter to validateaddress dep_validate_address = self.nodes[0].validateaddress(SOME_ADDRESS) assert "ismine" not in dep_validate_address not_dep_val = self.nodes[1].validateaddress(SOME_ADDRESS) assert "ismine" in not_dep_val + self.log.info("Test accounts deprecation") + # The following account RPC methods are deprecated: + # - getaccount + # - getaccountaddress + # - getaddressesbyaccount + # - getreceivedbyaccount + # - listaccouts + # - listreceivedbyaccount + # - move + # - setaccount + # + # The following 'label' RPC methods are usable both with and without the + # -deprecatedrpc=accounts switch enabled. + # - getlabeladdress + # - getaddressesbylabel + # - getreceivedbylabel + # - listlabels + # - listreceivedbylabel + # - setlabel + # + address0 = self.nodes[0].getnewaddress() + self.nodes[0].generatetoaddress(101, address0) + address1 = self.nodes[1].getnewaddress() + self.nodes[1].generatetoaddress(101, address1) + + self.log.info("- getaccount") + assert_raises_rpc_error(-32, "getaccount is deprecated", self.nodes[0].getaccount, address0) + self.nodes[1].getaccount(address1) + + self.log.info("- setaccount") + assert_raises_rpc_error(-32, "setaccount is deprecated", self.nodes[0].setaccount, address0, "label0") + self.nodes[1].setaccount(address1, "label1") + + self.log.info("- setlabel") + self.nodes[0].setlabel(address0, "label0") + self.nodes[1].setlabel(address1, "label1") + + self.log.info("- getaccountaddress") + assert_raises_rpc_error(-32, "getaccountaddress is deprecated", self.nodes[0].getaccountaddress, "label0") + self.nodes[1].getaccountaddress("label1") + + self.log.info("- getlabeladdress") + self.nodes[0].getlabeladdress("label0") + self.nodes[1].getlabeladdress("label1") + + self.log.info("- getaddressesbyaccount") + assert_raises_rpc_error(-32, "getaddressesbyaccount is deprecated", self.nodes[0].getaddressesbyaccount, "label0") + self.nodes[1].getaddressesbyaccount("label1") + + self.log.info("- getaddressesbylabel") + self.nodes[0].getaddressesbylabel("label0") + self.nodes[1].getaddressesbylabel("label1") + + self.log.info("- getreceivedbyaccount") + assert_raises_rpc_error(-32, "getreceivedbyaccount is deprecated", self.nodes[0].getreceivedbyaccount, "label0") + self.nodes[1].getreceivedbyaccount("label1") + + self.log.info("- getreceivedbylabel") + self.nodes[0].getreceivedbylabel("label0") + self.nodes[1].getreceivedbylabel("label1") + + self.log.info("- listaccounts") + assert_raises_rpc_error(-32, "listaccounts is deprecated", self.nodes[0].listaccounts) + self.nodes[1].listaccounts() + + self.log.info("- listlabels") + self.nodes[0].listlabels() + self.nodes[1].listlabels() + + self.log.info("- listreceivedbyaccount") + assert_raises_rpc_error(-32, "listreceivedbyaccount is deprecated", self.nodes[0].listreceivedbyaccount) + self.nodes[1].listreceivedbyaccount() + + self.log.info("- listreceivedbylabel") + self.nodes[0].listreceivedbylabel() + self.nodes[1].listreceivedbylabel() + + self.log.info("- move") + assert_raises_rpc_error(-32, "move is deprecated", self.nodes[0].move, "label0", "label0b", 10) + self.nodes[1].move("label1", "label1b", 10) + if __name__ == '__main__': DeprecatedRpcTest().main() diff --git a/test/functional/rpc_rawtransaction.py b/test/functional/rpc_rawtransaction.py index 658782e82a..48b4a4a9db 100755 --- a/test/functional/rpc_rawtransaction.py +++ b/test/functional/rpc_rawtransaction.py @@ -14,13 +14,10 @@ Test the following RPCs: from collections import OrderedDict from io import BytesIO +from test_framework.messages import CTransaction, ToHex from test_framework.test_framework import BitcoinTestFramework -from test_framework.messages import ( - CTransaction, -) from test_framework.util import * - class multidict(dict): """Dictionary that allows duplicate keys. @@ -363,5 +360,23 @@ class RawTransactionsTest(BitcoinTestFramework): decrawtx= self.nodes[0].decoderawtransaction(rawtx) assert_equal(decrawtx['vin'][0]['sequence'], 4294967294) + #################################### + # TRANSACTION VERSION NUMBER TESTS # + #################################### + + # Test the minimum transaction version number that fits in a signed 32-bit integer. + tx = CTransaction() + tx.nVersion = -0x80000000 + rawtx = ToHex(tx) + decrawtx = self.nodes[0].decoderawtransaction(rawtx) + assert_equal(decrawtx['version'], -0x80000000) + + # Test the maximum transaction version number that fits in a signed 32-bit integer. + tx = CTransaction() + tx.nVersion = 0x7fffffff + rawtx = ToHex(tx) + decrawtx = self.nodes[0].decoderawtransaction(rawtx) + assert_equal(decrawtx['version'], 0x7fffffff) + if __name__ == '__main__': RawTransactionsTest().main() diff --git a/test/functional/rpc_users.py b/test/functional/rpc_users.py index 0ce412f74a..1ef59da5ad 100755 --- a/test/functional/rpc_users.py +++ b/test/functional/rpc_users.py @@ -14,6 +14,10 @@ from test_framework.util import ( import os import http.client import urllib.parse +import subprocess +from random import SystemRandom +import string +import configparser class HTTPBasicsTest(BitcoinTestFramework): @@ -27,9 +31,20 @@ class HTTPBasicsTest(BitcoinTestFramework): rpcauth2 = "rpcauth=rt2:f8607b1a88861fac29dfccf9b52ff9f$ff36a0c23c8c62b4846112e50fa888416e94c17bfd4c42f88fd8f55ec6a3137e" rpcuser = "rpcuser=rpcuser💻" rpcpassword = "rpcpassword=rpcpassword🔑" + + self.user = ''.join(SystemRandom().choice(string.ascii_letters + string.digits) for _ in range(10)) + config = configparser.ConfigParser() + config.read_file(open(self.options.configfile)) + gen_rpcauth = config['environment']['RPCAUTH'] + p = subprocess.Popen([gen_rpcauth, self.user], stdout=subprocess.PIPE, universal_newlines=True) + lines = p.stdout.read().splitlines() + rpcauth3 = lines[1] + self.password = lines[3] + with open(os.path.join(get_datadir_path(self.options.tmpdir, 0), "bitcoin.conf"), 'a', encoding='utf8') as f: f.write(rpcauth+"\n") f.write(rpcauth2+"\n") + f.write(rpcauth3+"\n") with open(os.path.join(get_datadir_path(self.options.tmpdir, 1), "bitcoin.conf"), 'a', encoding='utf8') as f: f.write(rpcuser+"\n") f.write(rpcpassword+"\n") @@ -51,6 +66,7 @@ class HTTPBasicsTest(BitcoinTestFramework): password2 = "8/F3uMDw4KSEbw96U3CA1C4X05dkHDN2BPFjTgZW4KI=" authpairnew = "rt:"+password + self.log.info('Correct...') headers = {"Authorization": "Basic " + str_to_b64str(authpair)} conn = http.client.HTTPConnection(url.hostname, url.port) @@ -61,6 +77,7 @@ class HTTPBasicsTest(BitcoinTestFramework): conn.close() #Use new authpair to confirm both work + self.log.info('Correct...') headers = {"Authorization": "Basic " + str_to_b64str(authpairnew)} conn = http.client.HTTPConnection(url.hostname, url.port) @@ -71,6 +88,7 @@ class HTTPBasicsTest(BitcoinTestFramework): conn.close() #Wrong login name with rt's password + self.log.info('Wrong...') authpairnew = "rtwrong:"+password headers = {"Authorization": "Basic " + str_to_b64str(authpairnew)} @@ -82,6 +100,7 @@ class HTTPBasicsTest(BitcoinTestFramework): conn.close() #Wrong password for rt + self.log.info('Wrong...') authpairnew = "rt:"+password+"wrong" headers = {"Authorization": "Basic " + str_to_b64str(authpairnew)} @@ -93,6 +112,7 @@ class HTTPBasicsTest(BitcoinTestFramework): conn.close() #Correct for rt2 + self.log.info('Correct...') authpairnew = "rt2:"+password2 headers = {"Authorization": "Basic " + str_to_b64str(authpairnew)} @@ -104,6 +124,7 @@ class HTTPBasicsTest(BitcoinTestFramework): conn.close() #Wrong password for rt2 + self.log.info('Wrong...') authpairnew = "rt2:"+password2+"wrong" headers = {"Authorization": "Basic " + str_to_b64str(authpairnew)} @@ -114,12 +135,37 @@ class HTTPBasicsTest(BitcoinTestFramework): assert_equal(resp.status, 401) conn.close() + #Correct for randomly generated user + self.log.info('Correct...') + authpairnew = self.user+":"+self.password + headers = {"Authorization": "Basic " + str_to_b64str(authpairnew)} + + 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 password for randomly generated user + self.log.info('Wrong...') + authpairnew = self.user+":"+self.password+"Wrong" + headers = {"Authorization": "Basic " + str_to_b64str(authpairnew)} + + 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() + ############################################################### # Check correctness of the rpcuser/rpcpassword config options # ############################################################### url = urllib.parse.urlparse(self.nodes[1].url) # rpcuser and rpcpassword authpair + self.log.info('Correct...') rpcuserauthpair = "rpcuser💻:rpcpassword🔑" headers = {"Authorization": "Basic " + str_to_b64str(rpcuserauthpair)} @@ -143,6 +189,7 @@ class HTTPBasicsTest(BitcoinTestFramework): conn.close() #Wrong password for rpcuser + self.log.info('Wrong...') rpcuserauthpair = "rpcuser:rpcpasswordwrong" headers = {"Authorization": "Basic " + str_to_b64str(rpcuserauthpair)} diff --git a/test/functional/test_framework/blocktools.py b/test/functional/test_framework/blocktools.py index 43982cd09a..5c2b1815e5 100644 --- a/test/functional/test_framework/blocktools.py +++ b/test/functional/test_framework/blocktools.py @@ -10,7 +10,24 @@ from .address import ( script_to_p2sh_p2wsh, script_to_p2wsh, ) -from .mininode import * +from .messages import ( + CBlock, + COIN, + COutPoint, + CTransaction, + CTxIn, + CTxInWitness, + CTxOut, + FromHex, + ToHex, + bytes_to_hex_str, + hash256, + hex_str_to_bytes, + ser_string, + ser_uint256, + sha256, + uint256_from_str, +) from .script import ( CScript, OP_0, @@ -23,34 +40,34 @@ from .script import ( ) from .util import assert_equal -# Create a block (with regtest difficulty) -def create_block(hashprev, coinbase, nTime=None): +# From BIP141 +WITNESS_COMMITMENT_HEADER = b"\xaa\x21\xa9\xed" + +def create_block(hashprev, coinbase, ntime=None): + """Create a block (with regtest difficulty).""" block = CBlock() - if nTime is None: + if ntime is None: import time - block.nTime = int(time.time()+600) + block.nTime = int(time.time() + 600) else: - block.nTime = nTime + block.nTime = ntime block.hashPrevBlock = hashprev - block.nBits = 0x207fffff # Will break after a difficulty adjustment... + block.nBits = 0x207fffff # difficulty retargeting is disabled in REGTEST chainparams block.vtx.append(coinbase) block.hashMerkleRoot = block.calc_merkle_root() block.calc_sha256() return block -# From BIP141 -WITNESS_COMMITMENT_HEADER = b"\xaa\x21\xa9\xed" - - def get_witness_script(witness_root, witness_nonce): - witness_commitment = uint256_from_str(hash256(ser_uint256(witness_root)+ser_uint256(witness_nonce))) + witness_commitment = uint256_from_str(hash256(ser_uint256(witness_root) + ser_uint256(witness_nonce))) output_data = WITNESS_COMMITMENT_HEADER + ser_uint256(witness_commitment) return CScript([OP_RETURN, output_data]) - -# According to BIP141, blocks with witness rules active must commit to the -# hash of all in-block transactions including witness. def add_witness_commitment(block, nonce=0): + """Add a witness commitment to the block's coinbase transaction. + + According to BIP141, blocks with witness rules active must commit to the + hash of all in-block transactions including witness.""" # First calculate the merkle root of the block's # transactions, with witnesses. witness_nonce = nonce @@ -65,7 +82,6 @@ def add_witness_commitment(block, nonce=0): block.hashMerkleRoot = block.calc_merkle_root() block.rehash() - def serialize_script_num(value): r = bytearray(0) if value == 0: @@ -81,55 +97,59 @@ def serialize_script_num(value): r[-1] |= 0x80 return r -# Create a coinbase transaction, assuming no miner fees. -# If pubkey is passed in, the coinbase output will be a P2PK output; -# otherwise an anyone-can-spend output. -def create_coinbase(height, pubkey = None): +def create_coinbase(height, pubkey=None): + """Create a coinbase transaction, assuming no miner fees. + + If pubkey is passed in, the coinbase output will be a P2PK output; + otherwise an anyone-can-spend output.""" coinbase = CTransaction() - coinbase.vin.append(CTxIn(COutPoint(0, 0xffffffff), - ser_string(serialize_script_num(height)), 0xffffffff)) + coinbase.vin.append(CTxIn(COutPoint(0, 0xffffffff), + ser_string(serialize_script_num(height)), 0xffffffff)) coinbaseoutput = CTxOut() coinbaseoutput.nValue = 50 * COIN - halvings = int(height/150) # regtest + halvings = int(height / 150) # regtest coinbaseoutput.nValue >>= halvings - if (pubkey != None): + if (pubkey is not None): coinbaseoutput.scriptPubKey = CScript([pubkey, OP_CHECKSIG]) else: coinbaseoutput.scriptPubKey = CScript([OP_TRUE]) - coinbase.vout = [ coinbaseoutput ] + coinbase.vout = [coinbaseoutput] coinbase.calc_sha256() return coinbase -# Create a transaction. -# If the scriptPubKey is not specified, make it anyone-can-spend. -def create_transaction(prevtx, n, sig, value, scriptPubKey=CScript()): +def create_transaction(prevtx, n, sig, value, script_pub_key=CScript()): + """Create a transaction. + + If the script_pub_key is not specified, make it anyone-can-spend.""" tx = CTransaction() assert(n < len(prevtx.vout)) tx.vin.append(CTxIn(COutPoint(prevtx.sha256, n), sig, 0xffffffff)) - tx.vout.append(CTxOut(value, scriptPubKey)) + tx.vout.append(CTxOut(value, script_pub_key)) tx.calc_sha256() return tx -def get_legacy_sigopcount_block(block, fAccurate=True): +def get_legacy_sigopcount_block(block, accurate=True): count = 0 for tx in block.vtx: - count += get_legacy_sigopcount_tx(tx, fAccurate) + count += get_legacy_sigopcount_tx(tx, accurate) return count -def get_legacy_sigopcount_tx(tx, fAccurate=True): +def get_legacy_sigopcount_tx(tx, accurate=True): count = 0 for i in tx.vout: - count += i.scriptPubKey.GetSigOpCount(fAccurate) + count += i.scriptPubKey.GetSigOpCount(accurate) for j in tx.vin: # scriptSig might be of type bytes, so convert to CScript for the moment - count += CScript(j.scriptSig).GetSigOpCount(fAccurate) + count += CScript(j.scriptSig).GetSigOpCount(accurate) return count -# Create a scriptPubKey corresponding to either a P2WPKH output for the -# given pubkey, or a P2WSH output of a 1-of-1 multisig for the given -# pubkey. Returns the hex encoding of the scriptPubKey. def witness_script(use_p2wsh, pubkey): - if (use_p2wsh == False): + """Create a scriptPubKey for a pay-to-wtiness TxOut. + + This is either a P2WPKH output for the given pubkey, or a P2WSH output of a + 1-of-1 multisig for the given pubkey. Returns the hex encoding of the + scriptPubKey.""" + if not use_p2wsh: # P2WPKH instead pubkeyhash = hash160(hex_str_to_bytes(pubkey)) pkscript = CScript([OP_0, pubkeyhash]) @@ -140,9 +160,10 @@ def witness_script(use_p2wsh, pubkey): pkscript = CScript([OP_0, scripthash]) return bytes_to_hex_str(pkscript) -# Return a transaction (in hex) that spends the given utxo to a segwit output, -# optionally wrapping the segwit output using P2SH. def create_witness_tx(node, use_p2wsh, utxo, pubkey, encode_p2sh, amount): + """Return a transaction (in hex) that spends the given utxo to a segwit output. + + Optionally wrap the segwit output using P2SH.""" if use_p2wsh: program = CScript([OP_1, hex_str_to_bytes(pubkey), OP_1, OP_CHECKMULTISIG]) addr = script_to_p2sh_p2wsh(program) if encode_p2sh else script_to_p2wsh(program) @@ -152,12 +173,13 @@ def create_witness_tx(node, use_p2wsh, utxo, pubkey, encode_p2sh, amount): assert_equal(node.getaddressinfo(addr)['scriptPubKey'], witness_script(use_p2wsh, pubkey)) return node.createrawtransaction([utxo], {addr: amount}) -# Create a transaction spending a given utxo to a segwit output corresponding -# to the given pubkey: use_p2wsh determines whether to use P2WPKH or P2WSH; -# encode_p2sh determines whether to wrap in P2SH. -# sign=True will have the given node sign the transaction. -# insert_redeem_script will be added to the scriptSig, if given. def send_to_witness(use_p2wsh, node, utxo, pubkey, encode_p2sh, amount, sign=True, insert_redeem_script=""): + """Create a transaction spending a given utxo to a segwit output. + + The output corresponds to the given pubkey: use_p2wsh determines whether to + use P2WPKH or P2WSH; encode_p2sh determines whether to wrap in P2SH. + sign=True will have the given node sign the transaction. + insert_redeem_script will be added to the scriptSig, if given.""" tx_to_witness = create_witness_tx(node, use_p2wsh, utxo, pubkey, encode_p2sh, amount) if (sign): signed = node.signrawtransactionwithwallet(tx_to_witness) diff --git a/test/functional/test_framework/test_node.py b/test/functional/test_framework/test_node.py index f5c18e7be8..5a6a659392 100755 --- a/test/functional/test_framework/test_node.py +++ b/test/functional/test_framework/test_node.py @@ -18,7 +18,6 @@ import time from .authproxy import JSONRPCException from .util import ( append_config, - assert_equal, delete_cookie_file, get_rpc_proxy, rpc_url, @@ -99,6 +98,14 @@ class TestNode(): self.p2ps = [] + def _node_msg(self, msg: str) -> str: + """Return a modified msg that identifies this node by its index as a debugging aid.""" + return "[node %d] %s" % (self.index, msg) + + def _raise_assertion_error(self, msg: str): + """Raise an AssertionError with msg modified to identify this node.""" + raise AssertionError(self._node_msg(msg)) + def __del__(self): # Ensure that we don't leave any bitcoind processes lying around after # the test ends @@ -106,7 +113,7 @@ class TestNode(): # Should only happen on test failure # Avoid using logger, as that may have already been shutdown when # this destructor is called. - print("Cleaning up leftover process") + print(self._node_msg("Cleaning up leftover process")) self.process.kill() def __getattr__(self, name): @@ -114,7 +121,7 @@ class TestNode(): if self.use_cli: return getattr(self.cli, name) else: - assert self.rpc_connected and self.rpc is not None, "Error: no RPC connection" + assert self.rpc_connected and self.rpc is not None, self._node_msg("Error: no RPC connection") return getattr(self.rpc, name) def start(self, extra_args=None, stderr=None, *args, **kwargs): @@ -137,7 +144,8 @@ class TestNode(): poll_per_s = 4 for _ in range(poll_per_s * self.rpc_timeout): if self.process.poll() is not None: - raise FailedToStartError('bitcoind exited with status {} during initialization'.format(self.process.returncode)) + raise FailedToStartError(self._node_msg( + 'bitcoind exited with status {} during initialization'.format(self.process.returncode))) try: self.rpc = get_rpc_proxy(rpc_url(self.datadir, self.index, self.rpchost), self.index, timeout=self.rpc_timeout, coveragedir=self.coverage_dir) self.rpc.getblockcount() @@ -156,14 +164,13 @@ class TestNode(): if "No RPC credentials" not in str(e): raise time.sleep(1.0 / poll_per_s) - raise AssertionError("Unable to connect to bitcoind") + self._raise_assertion_error("Unable to connect to bitcoind") def get_wallet_rpc(self, wallet_name): if self.use_cli: return self.cli("-rpcwallet={}".format(wallet_name)) else: - assert self.rpc_connected - assert self.rpc + assert self.rpc_connected and self.rpc, self._node_msg("RPC not connected") wallet_path = "wallet/%s" % wallet_name return self.rpc / wallet_path @@ -190,7 +197,8 @@ class TestNode(): return False # process has stopped. Assert that it didn't return an error code. - assert_equal(return_code, 0) + assert return_code == 0, self._node_msg( + "Node returned non-zero exit code (%d) when stopping" % return_code) self.running = False self.process = None self.rpc_connected = False @@ -225,19 +233,22 @@ class TestNode(): stderr = log_stderr.read().decode('utf-8').strip() if match == ErrorMatch.PARTIAL_REGEX: if re.search(expected_msg, stderr, flags=re.MULTILINE) is None: - raise AssertionError('Expected message "{}" does not partially match stderr:\n"{}"'.format(expected_msg, stderr)) + self._raise_assertion_error( + 'Expected message "{}" does not partially match stderr:\n"{}"'.format(expected_msg, stderr)) elif match == ErrorMatch.FULL_REGEX: if re.fullmatch(expected_msg, stderr) is None: - raise AssertionError('Expected message "{}" does not fully match stderr:\n"{}"'.format(expected_msg, stderr)) + self._raise_assertion_error( + 'Expected message "{}" does not fully match stderr:\n"{}"'.format(expected_msg, stderr)) elif match == ErrorMatch.FULL_TEXT: if expected_msg != stderr: - raise AssertionError('Expected message "{}" does not fully match stderr:\n"{}"'.format(expected_msg, stderr)) + self._raise_assertion_error( + 'Expected message "{}" does not fully match stderr:\n"{}"'.format(expected_msg, stderr)) else: if expected_msg is None: assert_msg = "bitcoind should have exited with an error" else: assert_msg = "bitcoind should have exited with expected error " + expected_msg - raise AssertionError(assert_msg) + self._raise_assertion_error(assert_msg) def node_encrypt_wallet(self, passphrase): """"Encrypts the wallet. @@ -268,7 +279,7 @@ class TestNode(): Convenience property - most tests only use a single p2p connection to each node, so this saves having to write node.p2ps[0] many times.""" - assert self.p2ps, "No p2p connection" + assert self.p2ps, self._node_msg("No p2p connection") return self.p2ps[0] def disconnect_p2ps(self): diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index 7be28a258f..f5e1f3d4f7 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -70,7 +70,7 @@ BASE_SCRIPTS = [ 'wallet_labels.py', 'p2p_segwit.py', 'wallet_dump.py', - 'rpc_listtransactions.py', + 'wallet_listtransactions.py', # vv Tests less than 60s vv 'p2p_sendheaders.py', 'wallet_zapwallettxes.py', @@ -120,6 +120,9 @@ BASE_SCRIPTS = [ 'feature_nulldummy.py', 'mempool_accept.py', 'wallet_import_rescan.py', + 'rpc_bind.py --ipv4', + 'rpc_bind.py --ipv6', + 'rpc_bind.py --nonloopback', 'mining_basic.py', 'wallet_bumpfee.py', 'rpc_named_arguments.py', @@ -160,7 +163,6 @@ EXTENDED_SCRIPTS = [ 'p2p_timeouts.py', # vv Tests less than 60s vv 'p2p_feefilter.py', - 'rpc_bind.py', # vv Tests less than 30s vv 'feature_assumevalid.py', 'example_test.py', diff --git a/test/functional/wallet_basic.py b/test/functional/wallet_basic.py index 0436aca6a4..bfe90957a7 100755 --- a/test/functional/wallet_basic.py +++ b/test/functional/wallet_basic.py @@ -10,9 +10,10 @@ class WalletTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 4 self.setup_clean_chain = True + self.extra_args = [['-deprecatedrpc=accounts']] * 4 def setup_network(self): - self.add_nodes(4) + self.add_nodes(4, self.extra_args) self.start_node(0) self.start_node(1) self.start_node(2) @@ -376,9 +377,9 @@ class WalletTest(BitcoinTestFramework): self.log.info("check " + m) self.stop_nodes() # set lower ancestor limit for later - self.start_node(0, [m, "-limitancestorcount="+str(chainlimit)]) - self.start_node(1, [m, "-limitancestorcount="+str(chainlimit)]) - self.start_node(2, [m, "-limitancestorcount="+str(chainlimit)]) + self.start_node(0, [m, "-deprecatedrpc=accounts", "-limitancestorcount="+str(chainlimit)]) + self.start_node(1, [m, "-deprecatedrpc=accounts", "-limitancestorcount="+str(chainlimit)]) + self.start_node(2, [m, "-deprecatedrpc=accounts", "-limitancestorcount="+str(chainlimit)]) if m == '-reindex': # reindex will leave rpc warm up "early"; Wait for it to finish wait_until(lambda: [block_count] * 3 == [self.nodes[i].getblockcount() for i in range(3)]) @@ -426,7 +427,7 @@ class WalletTest(BitcoinTestFramework): # Try with walletrejectlongchains # Double chain limit but require combining inputs, so we pass SelectCoinsMinConf self.stop_node(0) - self.start_node(0, extra_args=["-walletrejectlongchains", "-limitancestorcount="+str(2*chainlimit)]) + self.start_node(0, extra_args=["-deprecatedrpc=accounts", "-walletrejectlongchains", "-limitancestorcount="+str(2*chainlimit)]) # wait for loadmempool timeout = 10 diff --git a/test/functional/wallet_import_rescan.py b/test/functional/wallet_import_rescan.py index b66e9b5d91..6775d8b46d 100755 --- a/test/functional/wallet_import_rescan.py +++ b/test/functional/wallet_import_rescan.py @@ -119,7 +119,7 @@ class ImportRescanTest(BitcoinTestFramework): self.num_nodes = 2 + len(IMPORT_NODES) def setup_network(self): - extra_args = [["-addresstype=legacy"] for _ in range(self.num_nodes)] + extra_args = [["-addresstype=legacy", '-deprecatedrpc=accounts'] for _ in range(self.num_nodes)] for i, import_node in enumerate(IMPORT_NODES, 2): if import_node.prune: extra_args[i] += ["-prune=1"] diff --git a/test/functional/wallet_importprunedfunds.py b/test/functional/wallet_importprunedfunds.py index 5f5bfcf683..d0ec290f36 100755 --- a/test/functional/wallet_importprunedfunds.py +++ b/test/functional/wallet_importprunedfunds.py @@ -10,6 +10,7 @@ class ImportPrunedFundsTest(BitcoinTestFramework): def set_test_params(self): self.setup_clean_chain = True self.num_nodes = 2 + self.extra_args = [['-deprecatedrpc=accounts']] * 2 def run_test(self): self.log.info("Mining blocks...") diff --git a/test/functional/wallet_keypool_topup.py b/test/functional/wallet_keypool_topup.py index 30a0c9a760..ab1493dd04 100755 --- a/test/functional/wallet_keypool_topup.py +++ b/test/functional/wallet_keypool_topup.py @@ -25,7 +25,7 @@ class KeypoolRestoreTest(BitcoinTestFramework): def set_test_params(self): self.setup_clean_chain = True self.num_nodes = 2 - self.extra_args = [[], ['-keypool=100', '-keypoolmin=20']] + self.extra_args = [['-deprecatedrpc=accounts'], ['-deprecatedrpc=accounts', '-keypool=100', '-keypoolmin=20']] def run_test(self): wallet_path = os.path.join(self.nodes[1].datadir, "regtest", "wallets", "wallet.dat") diff --git a/test/functional/wallet_labels.py b/test/functional/wallet_labels.py index 90eefc0438..705dd8985e 100755 --- a/test/functional/wallet_labels.py +++ b/test/functional/wallet_labels.py @@ -6,25 +6,38 @@ RPCs tested are: - getlabeladdress - - getaddressesbyaccount + - getaddressesbyaccount/getaddressesbylabel - listaddressgroupings - setlabel - sendfrom (with account arguments) - move (with account arguments) + +Run the test twice - once using the accounts API and once using the labels API. +The accounts API test can be removed in V0.18. """ from collections import defaultdict 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 WalletLabelsTest(BitcoinTestFramework): def set_test_params(self): self.setup_clean_chain = True - self.num_nodes = 1 - self.extra_args = [[]] + self.num_nodes = 2 + self.extra_args = [['-deprecatedrpc=accounts'], []] + + def setup_network(self): + """Don't connect nodes.""" + self.setup_nodes() def run_test(self): - node = self.nodes[0] + """Run the test twice - once using the accounts API and once using the labels API.""" + self.log.info("Test accounts API") + self._run_subtest(True, self.nodes[0]) + self.log.info("Test labels API") + self._run_subtest(False, self.nodes[1]) + + def _run_subtest(self, accounts_api, node): # Check that there's no UTXO on any of the nodes assert_equal(len(node.listunspent()), 0) @@ -77,7 +90,7 @@ class WalletLabelsTest(BitcoinTestFramework): # Create labels and make sure subsequent label API calls # recognize the label/address associations. - labels = [Label(name) for name in ("a", "b", "c", "d", "e")] + labels = [Label(name, accounts_api) for name in ("a", "b", "c", "d", "e")] for label in labels: label.add_receive_address(node.getlabeladdress(label=label.name, force=True)) label.verify(node) @@ -101,21 +114,23 @@ class WalletLabelsTest(BitcoinTestFramework): # Check that sendfrom label reduces listaccounts balances. for i, label in enumerate(labels): - to_label = labels[(i+1) % len(labels)] + to_label = labels[(i + 1) % len(labels)] node.sendfrom(label.name, to_label.receive_address, amount_to_send) node.generate(1) for label in labels: label.add_receive_address(node.getlabeladdress(label.name)) label.verify(node) assert_equal(node.getreceivedbylabel(label.name), 2) - node.move(label.name, "", node.getbalance(label.name)) + if accounts_api: + node.move(label.name, "", node.getbalance(label.name)) label.verify(node) node.generate(101) expected_account_balances = {"": 5200} for label in labels: expected_account_balances[label.name] = 0 - assert_equal(node.listaccounts(), expected_account_balances) - assert_equal(node.getbalance(""), 5200) + if accounts_api: + assert_equal(node.listaccounts(), expected_account_balances) + assert_equal(node.getbalance(""), 5200) # Check that setlabel can assign a label to a new unused address. for label in labels: @@ -123,7 +138,10 @@ class WalletLabelsTest(BitcoinTestFramework): node.setlabel(address, label.name) label.add_address(address) label.verify(node) - assert(address not in node.getaddressesbyaccount("")) + if accounts_api: + assert(address not in node.getaddressesbyaccount("")) + else: + assert_raises_rpc_error(-11, "No addresses with label", node.getaddressesbylabel, "") # Check that addmultisigaddress can assign labels. for label in labels: @@ -136,8 +154,9 @@ class WalletLabelsTest(BitcoinTestFramework): label.verify(node) node.sendfrom("", multisig_address, 50) node.generate(101) - for label in labels: - assert_equal(node.getbalance(label.name), 50) + if accounts_api: + for label in labels: + assert_equal(node.getbalance(label.name), 50) # Check that setlabel can change the label of an address from a # different label. @@ -156,9 +175,10 @@ class WalletLabelsTest(BitcoinTestFramework): change_label(node, labels[2].receive_address, labels[2], labels[2]) class Label: - def __init__(self, name): + def __init__(self, name, accounts_api): # Label name self.name = name + self.accounts_api = accounts_api # Current receiving address associated with this label. self.receive_address = None # List of all addresses assigned with this label @@ -184,13 +204,16 @@ class Label: node.getaddressinfo(address)['labels'][0], {"name": self.name, "purpose": self.purpose[address]}) - assert_equal(node.getaccount(address), self.name) + if self.accounts_api: + assert_equal(node.getaccount(address), self.name) + else: + assert_equal(node.getaddressinfo(address)['label'], self.name) assert_equal( node.getaddressesbylabel(self.name), {address: {"purpose": self.purpose[address]} for address in self.addresses}) - assert_equal( - set(node.getaddressesbyaccount(self.name)), set(self.addresses)) + if self.accounts_api: + assert_equal(set(node.getaddressesbyaccount(self.name)), set(self.addresses)) def change_label(node, address, old_label, new_label): diff --git a/test/functional/wallet_listreceivedby.py b/test/functional/wallet_listreceivedby.py index 7b34febddc..aba5d642bc 100755 --- a/test/functional/wallet_listreceivedby.py +++ b/test/functional/wallet_listreceivedby.py @@ -14,6 +14,7 @@ from test_framework.util import (assert_array_result, class ReceivedByTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 2 + self.extra_args = [['-deprecatedrpc=accounts']] * 2 def run_test(self): # Generate block to get out of IBD diff --git a/test/functional/wallet_listsinceblock.py b/test/functional/wallet_listsinceblock.py index 0f2434ff0d..930bfcd7b0 100755 --- a/test/functional/wallet_listsinceblock.py +++ b/test/functional/wallet_listsinceblock.py @@ -11,6 +11,7 @@ class ListSinceBlockTest (BitcoinTestFramework): def set_test_params(self): self.num_nodes = 4 self.setup_clean_chain = True + self.extra_args = [['-deprecatedrpc=accounts']] * 4 def run_test(self): self.nodes[2].generate(101) diff --git a/test/functional/rpc_listtransactions.py b/test/functional/wallet_listtransactions.py index 0dd7372e6b..5466bbf18b 100755 --- a/test/functional/rpc_listtransactions.py +++ b/test/functional/wallet_listtransactions.py @@ -18,6 +18,7 @@ def txFromHex(hexstring): class ListTransactionsTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 2 + self.extra_args = [['-deprecatedrpc=accounts']] * 2 self.enable_mocktime() def run_test(self): diff --git a/test/functional/wallet_multiwallet.py b/test/functional/wallet_multiwallet.py index 0a24d34398..e0571ea8f9 100755 --- a/test/functional/wallet_multiwallet.py +++ b/test/functional/wallet_multiwallet.py @@ -91,6 +91,19 @@ class MultiWalletTest(BitcoinTestFramework): open(not_a_dir, 'a').close() self.nodes[0].assert_start_raises_init_error(['-walletdir=' + not_a_dir], 'Error: Specified -walletdir "' + not_a_dir + '" is not a directory') + self.log.info("Do not allow -zapwallettxes with multiwallet") + self.nodes[0].assert_start_raises_init_error(['-zapwallettxes', '-wallet=w1', '-wallet=w2'], "Error: -zapwallettxes is only allowed with a single wallet file") + self.nodes[0].assert_start_raises_init_error(['-zapwallettxes=1', '-wallet=w1', '-wallet=w2'], "Error: -zapwallettxes is only allowed with a single wallet file") + self.nodes[0].assert_start_raises_init_error(['-zapwallettxes=2', '-wallet=w1', '-wallet=w2'], "Error: -zapwallettxes is only allowed with a single wallet file") + + self.log.info("Do not allow -salvagewallet with multiwallet") + self.nodes[0].assert_start_raises_init_error(['-salvagewallet', '-wallet=w1', '-wallet=w2'], "Error: -salvagewallet is only allowed with a single wallet file") + self.nodes[0].assert_start_raises_init_error(['-salvagewallet=1', '-wallet=w1', '-wallet=w2'], "Error: -salvagewallet is only allowed with a single wallet file") + + self.log.info("Do not allow -upgradewallet with multiwallet") + self.nodes[0].assert_start_raises_init_error(['-upgradewallet', '-wallet=w1', '-wallet=w2'], "Error: -upgradewallet is only allowed with a single wallet file") + self.nodes[0].assert_start_raises_init_error(['-upgradewallet=1', '-wallet=w1', '-wallet=w2'], "Error: -upgradewallet is only allowed with a single wallet file") + # if wallets/ doesn't exist, datadir should be the default wallet dir wallet_dir2 = data_dir('walletdir') os.rename(wallet_dir(), wallet_dir2) @@ -150,5 +163,12 @@ class MultiWalletTest(BitcoinTestFramework): assert_equal(batch[0]["result"]["chain"], "regtest") assert_equal(batch[1]["result"]["walletname"], "w1") + self.log.info('Check for per-wallet settxfee call') + assert_equal(w1.getwalletinfo()['paytxfee'], 0) + assert_equal(w2.getwalletinfo()['paytxfee'], 0) + w2.settxfee(4.0) + assert_equal(w1.getwalletinfo()['paytxfee'], 0) + assert_equal(w2.getwalletinfo()['paytxfee'], 4.0) + if __name__ == '__main__': MultiWalletTest().main() diff --git a/test/functional/wallet_txn_clone.py b/test/functional/wallet_txn_clone.py index 7577c4a0d2..aee84f7e90 100755 --- a/test/functional/wallet_txn_clone.py +++ b/test/functional/wallet_txn_clone.py @@ -10,6 +10,7 @@ from test_framework.util import * class TxnMallTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 4 + self.extra_args = [['-deprecatedrpc=accounts']] * 4 def add_options(self, parser): parser.add_option("--mineblock", dest="mine_block", default=False, action="store_true", diff --git a/test/functional/wallet_txn_doublespend.py b/test/functional/wallet_txn_doublespend.py index 8419d6b545..d644a94c73 100755 --- a/test/functional/wallet_txn_doublespend.py +++ b/test/functional/wallet_txn_doublespend.py @@ -10,6 +10,7 @@ from test_framework.util import * class TxnMallTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 4 + self.extra_args = [['-deprecatedrpc=accounts']] * 4 def add_options(self, parser): parser.add_option("--mineblock", dest="mine_block", default=False, action="store_true", |